diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml index 56dfec80e6..942eb0c128 100644 --- a/doc/src/sgml/trigger.sgml +++ b/doc/src/sgml/trigger.sgml @@ -1,5 +1,5 @@ @@ -256,6 +256,8 @@ typedef struct TriggerData HeapTuple tg_trigtuple; HeapTuple tg_newtuple; Trigger *tg_trigger; + Buffer tg_trigtuplebuf; + Buffer tg_newtuplebuf; } TriggerData; @@ -427,6 +429,27 @@ typedef struct Trigger + + + tg_trigtuplebuf + + + The buffer containing tg_trigtuple, or InvalidBuffer if there + is no such tuple or it is not stored in a disk buffer. + + + + + + tg_newtuplebuf + + + The buffer containing tg_newtuple, or InvalidBuffer if there + is no such tuple or it is not stored in a disk buffer. + + + + diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 3616275858..4593327d35 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.137 2004/10/22 17:20:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.138 2004/10/30 20:52:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -4256,6 +4256,8 @@ validateForeignKeyConstraint(FkConstraint *fkconstraint, trigdata.tg_trigtuple = tuple; trigdata.tg_newtuple = NULL; trigdata.tg_trigger = &trig; + trigdata.tg_trigtuplebuf = scan->rs_cbuf; + trigdata.tg_newtuplebuf = InvalidBuffer; fcinfo.context = (Node *) &trigdata; diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 7b1bdddf0b..a477fc8469 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.173 2004/10/21 21:33:59 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.174 2004/10/30 20:52:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1192,8 +1192,10 @@ ExecBSInsertTriggers(EState *estate, ResultRelInfo *relinfo) LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; - LocTriggerData.tg_newtuple = NULL; LocTriggerData.tg_trigtuple = NULL; + LocTriggerData.tg_newtuple = NULL; + LocTriggerData.tg_trigtuplebuf = InvalidBuffer; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; @@ -1246,6 +1248,7 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; LocTriggerData.tg_newtuple = NULL; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; @@ -1253,6 +1256,7 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo, if (!trigger->tgenabled) continue; LocTriggerData.tg_trigtuple = oldtuple = newtuple; + LocTriggerData.tg_trigtuplebuf = InvalidBuffer; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, relinfo->ri_TrigFunctions + tgindx[i], @@ -1305,8 +1309,10 @@ ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo) LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; - LocTriggerData.tg_newtuple = NULL; LocTriggerData.tg_trigtuple = NULL; + LocTriggerData.tg_newtuple = NULL; + LocTriggerData.tg_trigtuplebuf = InvalidBuffer; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; @@ -1365,6 +1371,7 @@ ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; LocTriggerData.tg_newtuple = NULL; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; @@ -1372,6 +1379,7 @@ ExecBRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, if (!trigger->tgenabled) continue; LocTriggerData.tg_trigtuple = trigtuple; + LocTriggerData.tg_trigtuplebuf = InvalidBuffer; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, relinfo->ri_TrigFunctions + tgindx[i], @@ -1434,8 +1442,10 @@ ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo) LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_BEFORE; LocTriggerData.tg_relation = relinfo->ri_RelationDesc; - LocTriggerData.tg_newtuple = NULL; LocTriggerData.tg_trigtuple = NULL; + LocTriggerData.tg_newtuple = NULL; + LocTriggerData.tg_trigtuplebuf = InvalidBuffer; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; for (i = 0; i < ntrigs; i++) { Trigger *trigger = &trigdesc->triggers[tgindx[i]]; @@ -1509,6 +1519,8 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, continue; LocTriggerData.tg_trigtuple = trigtuple; LocTriggerData.tg_newtuple = oldtuple = newtuple; + LocTriggerData.tg_trigtuplebuf = InvalidBuffer; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; LocTriggerData.tg_trigger = trigger; newtuple = ExecCallTriggerFunc(&LocTriggerData, relinfo->ri_TrigFunctions + tgindx[i], @@ -1896,8 +1908,8 @@ AfterTriggerExecute(AfterTriggerEvent event, HeapTupleData oldtuple; HeapTupleData newtuple; HeapTuple rettuple; - Buffer oldbuffer; - Buffer newbuffer; + Buffer oldbuffer = InvalidBuffer; + Buffer newbuffer = InvalidBuffer; int tgindx; /* @@ -1942,16 +1954,22 @@ AfterTriggerExecute(AfterTriggerEvent event, case TRIGGER_EVENT_INSERT: LocTriggerData.tg_trigtuple = &newtuple; LocTriggerData.tg_newtuple = NULL; + LocTriggerData.tg_trigtuplebuf = newbuffer; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; break; case TRIGGER_EVENT_UPDATE: LocTriggerData.tg_trigtuple = &oldtuple; LocTriggerData.tg_newtuple = &newtuple; + LocTriggerData.tg_trigtuplebuf = oldbuffer; + LocTriggerData.tg_newtuplebuf = newbuffer; break; case TRIGGER_EVENT_DELETE: LocTriggerData.tg_trigtuple = &oldtuple; LocTriggerData.tg_newtuple = NULL; + LocTriggerData.tg_trigtuplebuf = oldbuffer; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; break; } @@ -1970,9 +1988,9 @@ AfterTriggerExecute(AfterTriggerEvent event, /* * Release buffers */ - if (ItemPointerIsValid(&(event->ate_oldctid))) + if (oldbuffer != InvalidBuffer) ReleaseBuffer(oldbuffer); - if (ItemPointerIsValid(&(event->ate_newctid))) + if (newbuffer != InvalidBuffer) ReleaseBuffer(newbuffer); } @@ -2916,6 +2934,14 @@ AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger, LocTriggerData.tg_trigtuple = oldtup; LocTriggerData.tg_newtuple = newtup; LocTriggerData.tg_trigger = trigger; + /* + * We do not currently know which buffers the passed tuples + * are in, but it does not matter because RI_FKey_keyequal_upd + * does not care. We could expand the API of this function + * if it becomes necessary to set these fields accurately. + */ + LocTriggerData.tg_trigtuplebuf = InvalidBuffer; + LocTriggerData.tg_newtuplebuf = InvalidBuffer; if (RI_FKey_keyequal_upd(&LocTriggerData)) { diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index b195e24339..a727aee1c0 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -17,7 +17,7 @@ * * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.74 2004/10/15 22:40:11 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.75 2004/10/30 20:52:59 tgl Exp $ * * ---------- */ @@ -186,6 +186,7 @@ RI_FKey_check(PG_FUNCTION_ARGS) Relation pk_rel; HeapTuple new_row; HeapTuple old_row; + Buffer new_row_buf; RI_QueryKey qkey; void *qplan; int i; @@ -213,35 +214,30 @@ RI_FKey_check(PG_FUNCTION_ARGS) { old_row = trigdata->tg_trigtuple; new_row = trigdata->tg_newtuple; + new_row_buf = trigdata->tg_newtuplebuf; } else { old_row = NULL; new_row = trigdata->tg_trigtuple; + new_row_buf = trigdata->tg_trigtuplebuf; } /* * We should not even consider checking the row if it is no longer * valid since it was either deleted (doesn't matter) or updated (in * which case it'll be checked with its final values). - * - * We do not know what buffer the new_row is in, but it doesn't matter - * since it's not possible for a hint-bit update to occur here (the - * new_row could only contain our own XID, and we haven't yet committed - * or aborted...) */ - if (new_row) + Assert(new_row_buf != InvalidBuffer); + if (!HeapTupleSatisfiesItself(new_row->t_data, new_row_buf)) { - if (!HeapTupleSatisfiesItself(new_row->t_data, InvalidBuffer)) - { - heap_close(pk_rel, RowShareLock); - return PointerGetDatum(NULL); - } + heap_close(pk_rel, RowShareLock); + return PointerGetDatum(NULL); } /* ---------- * SQL3 11.9 - * Gereral rules 2) a): + * General rules 2) a): * If Rf and Rt are empty (no columns to compare given) * constraint is true if 0 < (SELECT COUNT(*) FROM T) * diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index 7d5569018a..a271a2a3ea 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.49 2004/09/10 18:40:06 tgl Exp $ + * $PostgreSQL: pgsql/src/include/commands/trigger.h,v 1.50 2004/10/30 20:53:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,6 +34,8 @@ typedef struct TriggerData HeapTuple tg_trigtuple; HeapTuple tg_newtuple; Trigger *tg_trigger; + Buffer tg_trigtuplebuf; + Buffer tg_newtuplebuf; } TriggerData; /* TriggerEvent bit flags */