mirror of
https://github.com/postgres/postgres.git
synced 2025-09-11 00:12:06 +03:00
GetTupleForTrigger must use outer transaction's command counter for time
qual checking, not GetCurrentCommandId. Per test case from Steve Wolfe.
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.136 2002/10/21 19:55:49 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.136.2.1 2003/03/27 14:33:20 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@@ -40,9 +40,10 @@
|
|||||||
|
|
||||||
static void InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx);
|
static void InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx);
|
||||||
static HeapTuple GetTupleForTrigger(EState *estate,
|
static HeapTuple GetTupleForTrigger(EState *estate,
|
||||||
ResultRelInfo *relinfo,
|
ResultRelInfo *relinfo,
|
||||||
ItemPointer tid,
|
ItemPointer tid,
|
||||||
TupleTableSlot **newSlot);
|
CommandId cid,
|
||||||
|
TupleTableSlot **newSlot);
|
||||||
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
|
static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
|
||||||
FmgrInfo *finfo,
|
FmgrInfo *finfo,
|
||||||
MemoryContext per_tuple_context);
|
MemoryContext per_tuple_context);
|
||||||
@@ -1189,7 +1190,8 @@ ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
|
ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||||
ItemPointer tupleid)
|
ItemPointer tupleid,
|
||||||
|
CommandId cid)
|
||||||
{
|
{
|
||||||
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
|
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
|
||||||
int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
|
int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
|
||||||
@@ -1200,7 +1202,7 @@ ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
|
|||||||
TupleTableSlot *newSlot;
|
TupleTableSlot *newSlot;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
|
trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot);
|
||||||
if (trigtuple == NULL)
|
if (trigtuple == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1247,7 +1249,9 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
|
|||||||
if (trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
|
if (trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
|
||||||
{
|
{
|
||||||
HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
|
HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
|
||||||
tupleid, NULL);
|
tupleid,
|
||||||
|
(CommandId) 0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
|
DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
|
||||||
trigtuple, NULL);
|
trigtuple, NULL);
|
||||||
@@ -1257,7 +1261,8 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
|
|||||||
|
|
||||||
HeapTuple
|
HeapTuple
|
||||||
ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
||||||
ItemPointer tupleid, HeapTuple newtuple)
|
ItemPointer tupleid, HeapTuple newtuple,
|
||||||
|
CommandId cid)
|
||||||
{
|
{
|
||||||
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
|
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
|
||||||
int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
|
int ntrigs = trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
|
||||||
@@ -1269,7 +1274,7 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
|||||||
TupleTableSlot *newSlot;
|
TupleTableSlot *newSlot;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, &newSlot);
|
trigtuple = GetTupleForTrigger(estate, relinfo, tupleid, cid, &newSlot);
|
||||||
if (trigtuple == NULL)
|
if (trigtuple == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -1322,7 +1327,9 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
|||||||
if (trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
|
if (trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
|
||||||
{
|
{
|
||||||
HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
|
HeapTuple trigtuple = GetTupleForTrigger(estate, relinfo,
|
||||||
tupleid, NULL);
|
tupleid,
|
||||||
|
(CommandId) 0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
|
DeferredTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
|
||||||
trigtuple, newtuple);
|
trigtuple, newtuple);
|
||||||
@@ -1333,7 +1340,8 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
|
|||||||
|
|
||||||
static HeapTuple
|
static HeapTuple
|
||||||
GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
|
GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
|
||||||
ItemPointer tid, TupleTableSlot **newSlot)
|
ItemPointer tid, CommandId cid,
|
||||||
|
TupleTableSlot **newSlot)
|
||||||
{
|
{
|
||||||
Relation relation = relinfo->ri_RelationDesc;
|
Relation relation = relinfo->ri_RelationDesc;
|
||||||
HeapTupleData tuple;
|
HeapTupleData tuple;
|
||||||
@@ -1350,8 +1358,7 @@ GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
|
|||||||
*newSlot = NULL;
|
*newSlot = NULL;
|
||||||
tuple.t_self = *tid;
|
tuple.t_self = *tid;
|
||||||
ltrmark:;
|
ltrmark:;
|
||||||
test = heap_mark4update(relation, &tuple, &buffer,
|
test = heap_mark4update(relation, &tuple, &buffer, cid);
|
||||||
GetCurrentCommandId());
|
|
||||||
switch (test)
|
switch (test)
|
||||||
{
|
{
|
||||||
case HeapTupleSelfUpdated:
|
case HeapTupleSelfUpdated:
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.180.2.1 2003/01/23 05:10:56 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.180.2.2 2003/03/27 14:33:21 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@@ -1295,7 +1295,8 @@ ExecDelete(TupleTableSlot *slot,
|
|||||||
{
|
{
|
||||||
bool dodelete;
|
bool dodelete;
|
||||||
|
|
||||||
dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid);
|
dodelete = ExecBRDeleteTriggers(estate, resultRelInfo, tupleid,
|
||||||
|
estate->es_snapshot->curcid);
|
||||||
|
|
||||||
if (!dodelete) /* "do nothing" */
|
if (!dodelete) /* "do nothing" */
|
||||||
return;
|
return;
|
||||||
@@ -1406,7 +1407,8 @@ ExecUpdate(TupleTableSlot *slot,
|
|||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
|
||||||
newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
|
newtuple = ExecBRUpdateTriggers(estate, resultRelInfo,
|
||||||
tupleid, tuple);
|
tupleid, tuple,
|
||||||
|
estate->es_snapshot->curcid);
|
||||||
|
|
||||||
if (newtuple == NULL) /* "do nothing" */
|
if (newtuple == NULL) /* "do nothing" */
|
||||||
return;
|
return;
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: trigger.h,v 1.39 2002/10/14 16:51:30 tgl Exp $
|
* $Id: trigger.h,v 1.39.2.1 2003/03/27 14:33:21 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@@ -123,15 +123,17 @@ extern void ExecARInsertTriggers(EState *estate,
|
|||||||
ResultRelInfo *relinfo,
|
ResultRelInfo *relinfo,
|
||||||
HeapTuple trigtuple);
|
HeapTuple trigtuple);
|
||||||
extern bool ExecBRDeleteTriggers(EState *estate,
|
extern bool ExecBRDeleteTriggers(EState *estate,
|
||||||
ResultRelInfo *relinfo,
|
ResultRelInfo *relinfo,
|
||||||
ItemPointer tupleid);
|
ItemPointer tupleid,
|
||||||
|
CommandId cid);
|
||||||
extern void ExecARDeleteTriggers(EState *estate,
|
extern void ExecARDeleteTriggers(EState *estate,
|
||||||
ResultRelInfo *relinfo,
|
ResultRelInfo *relinfo,
|
||||||
ItemPointer tupleid);
|
ItemPointer tupleid);
|
||||||
extern HeapTuple ExecBRUpdateTriggers(EState *estate,
|
extern HeapTuple ExecBRUpdateTriggers(EState *estate,
|
||||||
ResultRelInfo *relinfo,
|
ResultRelInfo *relinfo,
|
||||||
ItemPointer tupleid,
|
ItemPointer tupleid,
|
||||||
HeapTuple newtuple);
|
HeapTuple newtuple,
|
||||||
|
CommandId cid);
|
||||||
extern void ExecARUpdateTriggers(EState *estate,
|
extern void ExecARUpdateTriggers(EState *estate,
|
||||||
ResultRelInfo *relinfo,
|
ResultRelInfo *relinfo,
|
||||||
ItemPointer tupleid,
|
ItemPointer tupleid,
|
||||||
|
Reference in New Issue
Block a user