1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-25 21:42:33 +03:00

Prevent ExecInsert() and ExecUpdate() from scribbling on the result tuple

slot of the topmost plan node when a trigger returns a modified tuple.
These appear to be the only places where a plan node's caller did not
treat the result slot as read-only, which is an assumption that nodeUnique
makes as of 8.1.  Fixes trigger-vs-DISTINCT bug reported by Frank van Vugt.
This commit is contained in:
Tom Lane 2005-11-14 17:43:13 +00:00
parent f82df77c9d
commit 431178ae67
3 changed files with 40 additions and 10 deletions

View File

@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.256 2005/10/15 02:49:16 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.256.2.1 2005/11/14 17:43:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -582,7 +582,8 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
* initialize the executor "tuple" table. We need slots for all the plan
* nodes, plus possibly output slots for the junkfilter(s). At this point
* we aren't sure if we need junkfilters, so just add slots for them
* unconditionally.
* unconditionally. Also, if it's not a SELECT, set up a slot for use
* for trigger output tuples.
*/
{
int nSlots = ExecCountSlotsNode(plan);
@ -591,7 +592,14 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
nSlots += list_length(parseTree->resultRelations);
else
nSlots += 1;
if (operation != CMD_SELECT)
nSlots++;
estate->es_tupleTable = ExecCreateTupleTable(nSlots);
if (operation != CMD_SELECT)
estate->es_trig_tuple_slot =
ExecAllocTableSlot(estate->es_tupleTable);
}
/* mark EvalPlanQual not active */
@ -1399,12 +1407,19 @@ ExecInsert(TupleTableSlot *slot,
if (newtuple != tuple) /* modified by Trigger(s) */
{
/*
* Insert modified tuple into tuple table slot, replacing the
* original. We assume that it was allocated in per-tuple memory
* Put the modified tuple into a slot for convenience of routines
* below. We assume the tuple was allocated in per-tuple memory
* context, and therefore will go away by itself. The tuple table
* slot should not try to clear it.
*/
ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
TupleTableSlot *newslot = estate->es_trig_tuple_slot;
if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
ExecSetSlotDescriptor(newslot,
slot->tts_tupleDescriptor,
false);
ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
slot = newslot;
tuple = newtuple;
}
}
@ -1600,12 +1615,19 @@ ExecUpdate(TupleTableSlot *slot,
if (newtuple != tuple) /* modified by Trigger(s) */
{
/*
* Insert modified tuple into tuple table slot, replacing the
* original. We assume that it was allocated in per-tuple memory
* Put the modified tuple into a slot for convenience of routines
* below. We assume the tuple was allocated in per-tuple memory
* context, and therefore will go away by itself. The tuple table
* slot should not try to clear it.
*/
ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
TupleTableSlot *newslot = estate->es_trig_tuple_slot;
if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
ExecSetSlotDescriptor(newslot,
slot->tts_tupleDescriptor,
false);
ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
slot = newslot;
tuple = newtuple;
}
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.126 2005/10/15 02:49:16 momjian Exp $
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.126.2.1 2005/11/14 17:43:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -187,6 +187,8 @@ CreateExecutorState(void)
estate->es_junkFilter = NULL;
estate->es_trig_tuple_slot = NULL;
estate->es_into_relation_descriptor = NULL;
estate->es_into_relation_use_wal = false;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.139 2005/10/15 02:49:45 momjian Exp $
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.139.2.1 2005/11/14 17:43:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -341,6 +341,12 @@ typedef struct EState
bool *es_evTupleNull; /* local array of EPQ status */
HeapTuple *es_evTuple; /* shared array of EPQ substitute tuples */
bool es_useEvalPlan; /* evaluating EPQ tuples? */
/*
* this field added at end of struct to avoid post-release ABI breakage
* in 8.1 series. It'll be in a more logical place in 8.2.
*/
TupleTableSlot *es_trig_tuple_slot; /* for trigger output tuples */
} EState;