Skip dropped attributes when converting Python objects to tuples

Pay attention to the attisdropped field and skip over TupleDesc fields
that have it set.  Not a real problem until we get table returning
functions, but it's the right thing to do anyway.

Jan Urbański
This commit is contained in:
Peter Eisentraut 2011-01-18 23:39:09 +02:00
parent 59ea9ef9aa
commit 41282111e6
1 changed files with 21 additions and 2 deletions

View File

@ -2304,6 +2304,9 @@ PLyMapping_ToTuple(PLyTypeInfo *info, PyObject *mapping)
PyObject *volatile value; PyObject *volatile value;
PLyObToDatum *att; PLyObToDatum *att;
if (desc->attrs[i]->attisdropped)
continue;
key = NameStr(desc->attrs[i]->attname); key = NameStr(desc->attrs[i]->attname);
value = NULL; value = NULL;
att = &info->out.r.atts[i]; att = &info->out.r.atts[i];
@ -2354,6 +2357,7 @@ PLySequence_ToTuple(PLyTypeInfo *info, PyObject *sequence)
HeapTuple tuple; HeapTuple tuple;
Datum *values; Datum *values;
bool *nulls; bool *nulls;
volatile int idx;
volatile int i; volatile int i;
Assert(PySequence_Check(sequence)); Assert(PySequence_Check(sequence));
@ -2364,7 +2368,13 @@ PLySequence_ToTuple(PLyTypeInfo *info, PyObject *sequence)
* plpython developer's errors we are strict here * plpython developer's errors we are strict here
*/ */
desc = lookup_rowtype_tupdesc(info->out.d.typoid, -1); desc = lookup_rowtype_tupdesc(info->out.d.typoid, -1);
if (PySequence_Length(sequence) != desc->natts) idx = 0;
for (i = 0; i < desc->natts; i++)
{
if (!desc->attrs[i]->attisdropped)
idx++;
}
if (PySequence_Length(sequence) != idx)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("length of returned sequence did not match number of columns in row"))); errmsg("length of returned sequence did not match number of columns in row")));
@ -2376,16 +2386,20 @@ PLySequence_ToTuple(PLyTypeInfo *info, PyObject *sequence)
/* Build tuple */ /* Build tuple */
values = palloc(sizeof(Datum) * desc->natts); values = palloc(sizeof(Datum) * desc->natts);
nulls = palloc(sizeof(bool) * desc->natts); nulls = palloc(sizeof(bool) * desc->natts);
idx = 0;
for (i = 0; i < desc->natts; ++i) for (i = 0; i < desc->natts; ++i)
{ {
PyObject *volatile value; PyObject *volatile value;
PLyObToDatum *att; PLyObToDatum *att;
if (desc->attrs[i]->attisdropped)
continue;
value = NULL; value = NULL;
att = &info->out.r.atts[i]; att = &info->out.r.atts[i];
PG_TRY(); PG_TRY();
{ {
value = PySequence_GetItem(sequence, i); value = PySequence_GetItem(sequence, idx);
Assert(value); Assert(value);
if (value == Py_None) if (value == Py_None)
{ {
@ -2407,6 +2421,8 @@ PLySequence_ToTuple(PLyTypeInfo *info, PyObject *sequence)
PG_RE_THROW(); PG_RE_THROW();
} }
PG_END_TRY(); PG_END_TRY();
idx++;
} }
tuple = heap_form_tuple(desc, values, nulls); tuple = heap_form_tuple(desc, values, nulls);
@ -2441,6 +2457,9 @@ PLyObject_ToTuple(PLyTypeInfo *info, PyObject *object)
PyObject *volatile value; PyObject *volatile value;
PLyObToDatum *att; PLyObToDatum *att;
if (desc->attrs[i]->attisdropped)
continue;
key = NameStr(desc->attrs[i]->attname); key = NameStr(desc->attrs[i]->attname);
value = NULL; value = NULL;
att = &info->out.r.atts[i]; att = &info->out.r.atts[i];