Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit dd6edd5

Browse files
committed
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.
1 parent 76c39cf commit dd6edd5

File tree

1 file changed

+28
-19
lines changed

1 file changed

+28
-19
lines changed

src/pl/plpgsql/src/pl_exec.c

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.218 2008/08/29 13:02:33 petere Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.219 2008/09/01 22:30:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -4513,13 +4513,27 @@ exec_move_row(PLpgSQL_execstate *estate,
45134513
if (rec != NULL)
45144514
{
45154515
/*
4516-
* copy input first, just in case it is pointing at variable's value
4516+
* Copy input first, just in case it is pointing at variable's value
45174517
*/
45184518
if (HeapTupleIsValid(tup))
45194519
tup = heap_copytuple(tup);
4520+
else if (tupdesc)
4521+
{
4522+
/* If we have a tupdesc but no data, form an all-nulls tuple */
4523+
char *nulls;
4524+
4525+
nulls = (char *) palloc(tupdesc->natts * sizeof(char));
4526+
memset(nulls, 'n', tupdesc->natts * sizeof(char));
4527+
4528+
tup = heap_formtuple(tupdesc, NULL, nulls);
4529+
4530+
pfree(nulls);
4531+
}
4532+
45204533
if (tupdesc)
45214534
tupdesc = CreateTupleDescCopy(tupdesc);
45224535

4536+
/* Free the old value ... */
45234537
if (rec->freetup)
45244538
{
45254539
heap_freetuple(rec->tup);
@@ -4531,24 +4545,12 @@ exec_move_row(PLpgSQL_execstate *estate,
45314545
rec->freetupdesc = false;
45324546
}
45334547

4548+
/* ... and install the new */
45344549
if (HeapTupleIsValid(tup))
45354550
{
45364551
rec->tup = tup;
45374552
rec->freetup = true;
45384553
}
4539-
else if (tupdesc)
4540-
{
4541-
/* If we have a tupdesc but no data, form an all-nulls tuple */
4542-
char *nulls;
4543-
4544-
nulls = (char *) palloc(tupdesc->natts * sizeof(char));
4545-
memset(nulls, 'n', tupdesc->natts * sizeof(char));
4546-
4547-
rec->tup = heap_formtuple(tupdesc, NULL, nulls);
4548-
rec->freetup = true;
4549-
4550-
pfree(nulls);
4551-
}
45524554
else
45534555
rec->tup = NULL;
45544556

@@ -4568,7 +4570,7 @@ exec_move_row(PLpgSQL_execstate *estate,
45684570
* attributes of the tuple to the variables the row points to.
45694571
*
45704572
* NOTE: this code used to demand row->nfields ==
4571-
* HeapTupleHeaderGetNatts(tup->t_data, but that's wrong. The tuple might
4573+
* HeapTupleHeaderGetNatts(tup->t_data), but that's wrong. The tuple might
45724574
* have more fields than we expected if it's from an inheritance-child
45734575
* table of the current table, or it might have fewer if the table has had
45744576
* columns added by ALTER TABLE. Ignore extra columns and assume NULL for
@@ -4580,6 +4582,7 @@ exec_move_row(PLpgSQL_execstate *estate,
45804582
*/
45814583
if (row != NULL)
45824584
{
4585+
int td_natts = tupdesc ? tupdesc->natts : 0;
45834586
int t_natts;
45844587
int fnum;
45854588
int anum;
@@ -4602,12 +4605,18 @@ exec_move_row(PLpgSQL_execstate *estate,
46024605

46034606
var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
46044607

4605-
while (anum < t_natts && tupdesc->attrs[anum]->attisdropped)
4608+
while (anum < td_natts && tupdesc->attrs[anum]->attisdropped)
46064609
anum++; /* skip dropped column in tuple */
46074610

4608-
if (anum < t_natts)
4611+
if (anum < td_natts)
46094612
{
4610-
value = SPI_getbinval(tup, tupdesc, anum + 1, &isnull);
4613+
if (anum < t_natts)
4614+
value = SPI_getbinval(tup, tupdesc, anum + 1, &isnull);
4615+
else
4616+
{
4617+
value = (Datum) 0;
4618+
isnull = true;
4619+
}
46114620
valtype = SPI_gettypeid(tupdesc, anum + 1);
46124621
anum++;
46134622
}

0 commit comments

Comments
 (0)