/* ----------
- * exec_move_row Move one tuples values into a
- * record or row
+ * exec_move_row Move one tuple's values into a record or row
* ----------
*/
static void
PLpgSQL_row * row,
HeapTuple tup, TupleDesc tupdesc)
{
- PLpgSQL_var *var;
- int i;
- Datum value;
- Oid valtype;
- bool isnull;
-
/*
* Record is simple - just put the tuple and its descriptor into the
* record
return;
}
-
/*
- * Row is a bit more complicated in that we assign the single
- * attributes of the query to the variables the row points to.
+ * Row is a bit more complicated in that we assign the individual
+ * attributes of the tuple to the variables the row points to.
+ *
+ * NOTE: this code used to demand row->nfields == tup->t_data->t_natts,
+ * but that's wrong. The tuple might have more fields than we expected
+ * if it's from an inheritance-child table of the current table, or it
+ * might have fewer if the table has had columns added by ALTER TABLE.
+ * Ignore extra columns and assume NULL for missing columns, the same
+ * as heap_getattr would do.
*/
if (row != NULL)
{
+ int t_natts;
+ int i;
+
if (HeapTupleIsValid(tup))
+ t_natts = tup->t_data->t_natts;
+ else
+ t_natts = 0;
+
+ for (i = 0; i < row->nfields; i++)
{
- if (row->nfields != tup->t_data->t_natts)
- {
- elog(ERROR, "query didn't return correct # of attributes for %s",
- row->refname);
- }
+ PLpgSQL_var *var;
+ Datum value;
+ bool isnull;
+ Oid valtype;
- for (i = 0; i < row->nfields; i++)
+ var = (PLpgSQL_var *) (estate->datums[row->varnos[i]]);
+ if (i < t_natts)
{
- var = (PLpgSQL_var *) (estate->datums[row->varnos[i]]);
-
- valtype = SPI_gettypeid(tupdesc, i + 1);
value = SPI_getbinval(tup, tupdesc, i + 1, &isnull);
- exec_assign_value(estate, estate->datums[row->varnos[i]],
- value, valtype, &isnull);
-
}
- }
- else
- {
- for (i = 0; i < row->nfields; i++)
+ else
{
- bool nullval = true;
-
- exec_assign_value(estate, estate->datums[row->varnos[i]],
- (Datum) 0, 0, &nullval);
+ value = (Datum) 0;
+ isnull = true;
}
+ /* tupdesc should have entries for all columns I expect... */
+ valtype = SPI_gettypeid(tupdesc, i + 1);
+
+ exec_assign_value(estate, estate->datums[row->varnos[i]],
+ value, valtype, &isnull);
}
return;