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

Commit 76ce39e

Browse files
committed
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.
1 parent 08ee64e commit 76ce39e

File tree

3 files changed

+36
-10
lines changed

3 files changed

+36
-10
lines changed

src/backend/executor/execMain.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.256 2005/10/15 02:49:16 momjian Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.257 2005/11/14 17:42:54 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -582,7 +582,8 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
582582
* initialize the executor "tuple" table. We need slots for all the plan
583583
* nodes, plus possibly output slots for the junkfilter(s). At this point
584584
* we aren't sure if we need junkfilters, so just add slots for them
585-
* unconditionally.
585+
* unconditionally. Also, if it's not a SELECT, set up a slot for use
586+
* for trigger output tuples.
586587
*/
587588
{
588589
int nSlots = ExecCountSlotsNode(plan);
@@ -591,7 +592,14 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
591592
nSlots += list_length(parseTree->resultRelations);
592593
else
593594
nSlots += 1;
595+
if (operation != CMD_SELECT)
596+
nSlots++;
597+
594598
estate->es_tupleTable = ExecCreateTupleTable(nSlots);
599+
600+
if (operation != CMD_SELECT)
601+
estate->es_trig_tuple_slot =
602+
ExecAllocTableSlot(estate->es_tupleTable);
595603
}
596604

597605
/* mark EvalPlanQual not active */
@@ -1399,12 +1407,19 @@ ExecInsert(TupleTableSlot *slot,
13991407
if (newtuple != tuple) /* modified by Trigger(s) */
14001408
{
14011409
/*
1402-
* Insert modified tuple into tuple table slot, replacing the
1403-
* original. We assume that it was allocated in per-tuple memory
1410+
* Put the modified tuple into a slot for convenience of routines
1411+
* below. We assume the tuple was allocated in per-tuple memory
14041412
* context, and therefore will go away by itself. The tuple table
14051413
* slot should not try to clear it.
14061414
*/
1407-
ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
1415+
TupleTableSlot *newslot = estate->es_trig_tuple_slot;
1416+
1417+
if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
1418+
ExecSetSlotDescriptor(newslot,
1419+
slot->tts_tupleDescriptor,
1420+
false);
1421+
ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
1422+
slot = newslot;
14081423
tuple = newtuple;
14091424
}
14101425
}
@@ -1600,12 +1615,19 @@ ExecUpdate(TupleTableSlot *slot,
16001615
if (newtuple != tuple) /* modified by Trigger(s) */
16011616
{
16021617
/*
1603-
* Insert modified tuple into tuple table slot, replacing the
1604-
* original. We assume that it was allocated in per-tuple memory
1618+
* Put the modified tuple into a slot for convenience of routines
1619+
* below. We assume the tuple was allocated in per-tuple memory
16051620
* context, and therefore will go away by itself. The tuple table
16061621
* slot should not try to clear it.
16071622
*/
1608-
ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
1623+
TupleTableSlot *newslot = estate->es_trig_tuple_slot;
1624+
1625+
if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
1626+
ExecSetSlotDescriptor(newslot,
1627+
slot->tts_tupleDescriptor,
1628+
false);
1629+
ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
1630+
slot = newslot;
16091631
tuple = newtuple;
16101632
}
16111633
}

src/backend/executor/execUtils.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.126 2005/10/15 02:49:16 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.127 2005/11/14 17:42:54 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -187,6 +187,8 @@ CreateExecutorState(void)
187187

188188
estate->es_junkFilter = NULL;
189189

190+
estate->es_trig_tuple_slot = NULL;
191+
190192
estate->es_into_relation_descriptor = NULL;
191193
estate->es_into_relation_use_wal = false;
192194

src/include/nodes/execnodes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.139 2005/10/15 02:49:45 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.140 2005/11/14 17:42:55 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -304,6 +304,8 @@ typedef struct EState
304304
ResultRelInfo *es_result_relation_info; /* currently active array elt */
305305
JunkFilter *es_junkFilter; /* currently active junk filter */
306306

307+
TupleTableSlot *es_trig_tuple_slot; /* for trigger output tuples */
308+
307309
Relation es_into_relation_descriptor; /* for SELECT INTO */
308310
bool es_into_relation_use_wal;
309311

0 commit comments

Comments
 (0)