3
3
* procedural language
4
4
*
5
5
* 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 $
7
7
*
8
8
* This software is copyrighted by Jan Wieck - Hamburg.
9
9
*
@@ -2569,8 +2569,7 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate,
2569
2569
2570
2570
2571
2571
/* ----------
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
2574
2573
* ----------
2575
2574
*/
2576
2575
static void
@@ -2579,12 +2578,6 @@ exec_move_row(PLpgSQL_execstate * estate,
2579
2578
PLpgSQL_row * row ,
2580
2579
HeapTuple tup , TupleDesc tupdesc )
2581
2580
{
2582
- PLpgSQL_var * var ;
2583
- int i ;
2584
- Datum value ;
2585
- Oid valtype ;
2586
- bool isnull ;
2587
-
2588
2581
/*
2589
2582
* Record is simple - just put the tuple and its descriptor into the
2590
2583
* record
@@ -2605,41 +2598,49 @@ exec_move_row(PLpgSQL_execstate * estate,
2605
2598
return ;
2606
2599
}
2607
2600
2608
-
2609
2601
/*
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.
2612
2611
*/
2613
2612
if (row != NULL )
2614
2613
{
2614
+ int t_natts ;
2615
+ int i ;
2616
+
2615
2617
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 ++ )
2616
2623
{
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 ;
2622
2628
2623
- for (i = 0 ; i < row -> nfields ; i ++ )
2629
+ var = (PLpgSQL_var * ) (estate -> datums [row -> varnos [i ]]);
2630
+ if (i < t_natts )
2624
2631
{
2625
- var = (PLpgSQL_var * ) (estate -> datums [row -> varnos [i ]]);
2626
-
2627
- valtype = SPI_gettypeid (tupdesc , i + 1 );
2628
2632
value = SPI_getbinval (tup , tupdesc , i + 1 , & isnull );
2629
- exec_assign_value (estate , estate -> datums [row -> varnos [i ]],
2630
- value , valtype , & isnull );
2631
-
2632
2633
}
2633
- }
2634
- else
2635
- {
2636
- for (i = 0 ; i < row -> nfields ; i ++ )
2634
+ else
2637
2635
{
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;
2642
2638
}
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 );
2643
2644
}
2644
2645
2645
2646
return ;
0 commit comments