From 8bb3c8fe5413103c30ba8d1bcb3a1f8e46bddf3d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 30 Apr 2001 20:05:40 +0000 Subject: [PATCH] exec_move_row() should be more forgiving of tuples with a different number of columns than it was expecting, for reasons that are now documented in the code... --- src/pl/plpgsql/src/pl_exec.c | 73 ++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 7a65b6512d..566bae7016 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.40 2001/03/22 06:16:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.41 2001/04/30 20:05:40 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -2569,8 +2569,7 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate, /* ---------- - * 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 @@ -2579,12 +2578,6 @@ exec_move_row(PLpgSQL_execstate * estate, 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 @@ -2605,41 +2598,49 @@ exec_move_row(PLpgSQL_execstate * estate, 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)) - { - if (row->nfields != tup->t_data->t_natts) - { - elog(ERROR, "query didn't return correct # of attributes for %s", - row->refname); - } - - for (i = 0; i < row->nfields; i++) - { - 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); - - } - } + t_natts = tup->t_data->t_natts; else - { - for (i = 0; i < row->nfields; i++) - { - bool nullval = true; + t_natts = 0; - exec_assign_value(estate, estate->datums[row->varnos[i]], - (Datum) 0, 0, &nullval); + for (i = 0; i < row->nfields; i++) + { + PLpgSQL_var *var; + Datum value; + bool isnull; + Oid valtype; + + var = (PLpgSQL_var *) (estate->datums[row->varnos[i]]); + if (i < t_natts) + { + value = SPI_getbinval(tup, tupdesc, i + 1, &isnull); } + else + { + 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;