33 * procedural language
44 *
55 * IDENTIFICATION
6- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.40 2001/03/22 06:16:21 momjian Exp $
6+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.41 2001/04/30 20:05:40 tgl Exp $
77 *
88 * This software is copyrighted by Jan Wieck - Hamburg.
99 *
@@ -2569,8 +2569,7 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
25692569
25702570
25712571/* ----------
2572- * exec_move_row Move one tuples values into a
2573- * record or row
2572+ * exec_move_row Move one tuple's values into a record or row
25742573 * ----------
25752574 */
25762575static void
@@ -2579,12 +2578,6 @@ exec_move_row(PLpgSQL_execstate * estate,
25792578 PLpgSQL_row * row ,
25802579 HeapTuple tup , TupleDesc tupdesc )
25812580{
2582- PLpgSQL_var * var ;
2583- int i ;
2584- Datum value ;
2585- Oid valtype ;
2586- bool isnull ;
2587-
25882581 /*
25892582 * Record is simple - just put the tuple and its descriptor into the
25902583 * record
@@ -2605,41 +2598,49 @@ exec_move_row(PLpgSQL_execstate * estate,
26052598 return ;
26062599 }
26072600
2608-
26092601 /*
2610- * Row is a bit more complicated in that we assign the single
2611- * attributes of the query to the variables the row points to.
2602+ * Row is a bit more complicated in that we assign the individual
2603+ * attributes of the tuple to the variables the row points to.
2604+ *
2605+ * NOTE: this code used to demand row->nfields == tup->t_data->t_natts,
2606+ * but that's wrong. The tuple might have more fields than we expected
2607+ * if it's from an inheritance-child table of the current table, or it
2608+ * might have fewer if the table has had columns added by ALTER TABLE.
2609+ * Ignore extra columns and assume NULL for missing columns, the same
2610+ * as heap_getattr would do.
26122611 */
26132612 if (row != NULL )
26142613 {
2614+ int t_natts ;
2615+ int i ;
2616+
26152617 if (HeapTupleIsValid (tup ))
2618+ t_natts = tup -> t_data -> t_natts ;
2619+ else
2620+ t_natts = 0 ;
2621+
2622+ for (i = 0 ; i < row -> nfields ; i ++ )
26162623 {
2617- if (row -> nfields != tup -> t_data -> t_natts )
2618- {
2619- elog (ERROR , "query didn't return correct # of attributes for %s" ,
2620- row -> refname );
2621- }
2624+ PLpgSQL_var * var ;
2625+ Datum value ;
2626+ bool isnull ;
2627+ Oid valtype ;
26222628
2623- for (i = 0 ; i < row -> nfields ; i ++ )
2629+ var = (PLpgSQL_var * ) (estate -> datums [row -> varnos [i ]]);
2630+ if (i < t_natts )
26242631 {
2625- var = (PLpgSQL_var * ) (estate -> datums [row -> varnos [i ]]);
2626-
2627- valtype = SPI_gettypeid (tupdesc , i + 1 );
26282632 value = SPI_getbinval (tup , tupdesc , i + 1 , & isnull );
2629- exec_assign_value (estate , estate -> datums [row -> varnos [i ]],
2630- value , valtype , & isnull );
2631-
26322633 }
2633- }
2634- else
2635- {
2636- for (i = 0 ; i < row -> nfields ; i ++ )
2634+ else
26372635 {
2638- bool nullval = true;
2639-
2640- exec_assign_value (estate , estate -> datums [row -> varnos [i ]],
2641- (Datum ) 0 , 0 , & nullval );
2636+ value = (Datum ) 0 ;
2637+ isnull = true;
26422638 }
2639+ /* tupdesc should have entries for all columns I expect... */
2640+ valtype = SPI_gettypeid (tupdesc , i + 1 );
2641+
2642+ exec_assign_value (estate , estate -> datums [row -> varnos [i ]],
2643+ value , valtype , & isnull );
26432644 }
26442645
26452646 return ;
0 commit comments