summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2008-09-01 22:30:55 +0000
committerTom Lane2008-09-01 22:30:55 +0000
commit74da120713d15f8fb06c65f92111db6654ecfe2e (patch)
tree97124413a97809fb54c9fa184d0431aca067db36
parenta76e18518067c50d9f9648f83461c8fe86416b8f (diff)
Fix plpgsql's exec_move_row() to supply valid type OIDs to exec_assign_value()
whenever possible, as per bug report from Oleg Serov. While at it, reorder the operations in the RECORD case to avoid possible palloc failure while the variable update is only partly complete. Back-patch as far as 8.1. Although the code of the particular function is similar in 8.0, 8.0's support for composite fields in rows is sufficiently broken elsewhere that it doesn't seem worth fixing this.
-rw-r--r--src/pl/plpgsql/src/pl_exec.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 6bc97eaa5c4..a3e87674492 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.154.2.6 2007/02/08 18:37:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.154.2.7 2008/09/01 22:30:55 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -3915,13 +3915,27 @@ exec_move_row(PLpgSQL_execstate *estate,
if (rec != NULL)
{
/*
- * copy input first, just in case it is pointing at variable's value
+ * Copy input first, just in case it is pointing at variable's value
*/
if (HeapTupleIsValid(tup))
tup = heap_copytuple(tup);
+ else if (tupdesc)
+ {
+ /* If we have a tupdesc but no data, form an all-nulls tuple */
+ char *nulls;
+
+ nulls = (char *) palloc(tupdesc->natts * sizeof(char));
+ memset(nulls, 'n', tupdesc->natts * sizeof(char));
+
+ tup = heap_formtuple(tupdesc, NULL, nulls);
+
+ pfree(nulls);
+ }
+
if (tupdesc)
tupdesc = CreateTupleDescCopy(tupdesc);
+ /* Free the old value ... */
if (rec->freetup)
{
heap_freetuple(rec->tup);
@@ -3933,24 +3947,12 @@ exec_move_row(PLpgSQL_execstate *estate,
rec->freetupdesc = false;
}
+ /* ... and install the new */
if (HeapTupleIsValid(tup))
{
rec->tup = tup;
rec->freetup = true;
}
- else if (tupdesc)
- {
- /* If we have a tupdesc but no data, form an all-nulls tuple */
- char *nulls;
-
- nulls = (char *) palloc(tupdesc->natts * sizeof(char));
- memset(nulls, 'n', tupdesc->natts * sizeof(char));
-
- rec->tup = heap_formtuple(tupdesc, NULL, nulls);
- rec->freetup = true;
-
- pfree(nulls);
- }
else
rec->tup = NULL;
@@ -3982,6 +3984,7 @@ exec_move_row(PLpgSQL_execstate *estate,
*/
if (row != NULL)
{
+ int td_natts = tupdesc ? tupdesc->natts : 0;
int t_natts;
int fnum;
int anum;
@@ -4004,12 +4007,18 @@ exec_move_row(PLpgSQL_execstate *estate,
var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
- while (anum < t_natts && tupdesc->attrs[anum]->attisdropped)
+ while (anum < td_natts && tupdesc->attrs[anum]->attisdropped)
anum++; /* skip dropped column in tuple */
- if (anum < t_natts)
+ if (anum < td_natts)
{
- value = SPI_getbinval(tup, tupdesc, anum + 1, &isnull);
+ if (anum < t_natts)
+ value = SPI_getbinval(tup, tupdesc, anum + 1, &isnull);
+ else
+ {
+ value = (Datum) 0;
+ isnull = true;
+ }
valtype = SPI_gettypeid(tupdesc, anum + 1);
anum++;
}