mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
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.
This commit is contained in:
parent
063ec6cf82
commit
d22e47dba8
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.180.2.5 2007/04/19 16:33:32 tgl Exp $
|
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.180.2.6 2008/09/01 22:30:48 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -4103,13 +4103,27 @@ exec_move_row(PLpgSQL_execstate *estate,
|
|||||||
if (rec != NULL)
|
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))
|
if (HeapTupleIsValid(tup))
|
||||||
tup = heap_copytuple(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)
|
if (tupdesc)
|
||||||
tupdesc = CreateTupleDescCopy(tupdesc);
|
tupdesc = CreateTupleDescCopy(tupdesc);
|
||||||
|
|
||||||
|
/* Free the old value ... */
|
||||||
if (rec->freetup)
|
if (rec->freetup)
|
||||||
{
|
{
|
||||||
heap_freetuple(rec->tup);
|
heap_freetuple(rec->tup);
|
||||||
@ -4121,24 +4135,12 @@ exec_move_row(PLpgSQL_execstate *estate,
|
|||||||
rec->freetupdesc = false;
|
rec->freetupdesc = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ... and install the new */
|
||||||
if (HeapTupleIsValid(tup))
|
if (HeapTupleIsValid(tup))
|
||||||
{
|
{
|
||||||
rec->tup = tup;
|
rec->tup = tup;
|
||||||
rec->freetup = true;
|
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
|
else
|
||||||
rec->tup = NULL;
|
rec->tup = NULL;
|
||||||
|
|
||||||
@ -4170,6 +4172,7 @@ exec_move_row(PLpgSQL_execstate *estate,
|
|||||||
*/
|
*/
|
||||||
if (row != NULL)
|
if (row != NULL)
|
||||||
{
|
{
|
||||||
|
int td_natts = tupdesc ? tupdesc->natts : 0;
|
||||||
int t_natts;
|
int t_natts;
|
||||||
int fnum;
|
int fnum;
|
||||||
int anum;
|
int anum;
|
||||||
@ -4192,12 +4195,18 @@ exec_move_row(PLpgSQL_execstate *estate,
|
|||||||
|
|
||||||
var = (PLpgSQL_var *) (estate->datums[row->varnos[fnum]]);
|
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 */
|
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);
|
valtype = SPI_gettypeid(tupdesc, anum + 1);
|
||||||
anum++;
|
anum++;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user