aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c155
1 files changed, 88 insertions, 67 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 431a70a6ff9..60d0056930b 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -40,7 +40,7 @@ void RelationBuildTriggers(Relation relation);
void FreeTriggerDesc(Relation relation);
static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
-static HeapTuple GetTupleForTrigger(Relation relation, ItemPointer tid,
+static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
bool before);
extern GlobalMemory CacheCxt;
@@ -77,7 +77,7 @@ CreateTrigger(CreateTrigStmt *stmt)
if (!RelationIsValid(rel))
elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
- RelationSetLockForWrite(rel);
+ LockRelation(rel, AccessExclusiveLock);
TRIGGER_CLEAR_TYPE(tgtype);
if (stmt->before)
@@ -114,7 +114,7 @@ CreateTrigger(CreateTrigStmt *stmt)
/* Scan pg_trigger */
tgrel = heap_openr(TriggerRelationName);
- RelationSetLockForWrite(tgrel);
+ LockRelation(tgrel, AccessExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@@ -211,7 +211,7 @@ CreateTrigger(CreateTrigStmt *stmt)
CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
CatalogCloseIndices(Num_pg_trigger_indices, idescs);
pfree(tuple);
- RelationUnsetLockForWrite(tgrel);
+ UnlockRelation(tgrel, AccessExclusiveLock);
heap_close(tgrel);
pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
@@ -227,7 +227,7 @@ CreateTrigger(CreateTrigStmt *stmt)
pgrel = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
RelationInvalidateHeapTuple(pgrel, tuple);
- heap_replace(pgrel, &tuple->t_self, tuple);
+ heap_replace(pgrel, &tuple->t_self, tuple, NULL);
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
@@ -267,10 +267,10 @@ DropTrigger(DropTrigStmt *stmt)
if (!RelationIsValid(rel))
elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
- RelationSetLockForWrite(rel);
+ LockRelation(rel, AccessExclusiveLock);
tgrel = heap_openr(TriggerRelationName);
- RelationSetLockForWrite(tgrel);
+ LockRelation(tgrel, AccessExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@@ -280,7 +280,7 @@ DropTrigger(DropTrigStmt *stmt)
if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
{
- heap_delete(tgrel, &tuple->t_self);
+ heap_delete(tgrel, &tuple->t_self, NULL);
tgfound++;
}
else
@@ -293,7 +293,7 @@ DropTrigger(DropTrigStmt *stmt)
elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
tgfound, stmt->trigname, stmt->relname);
heap_endscan(tgscan);
- RelationUnsetLockForWrite(tgrel);
+ UnlockRelation(tgrel, AccessExclusiveLock);
heap_close(tgrel);
tuple = SearchSysCacheTupleCopy(RELNAME,
@@ -306,7 +306,7 @@ DropTrigger(DropTrigStmt *stmt)
pgrel = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
RelationInvalidateHeapTuple(pgrel, tuple);
- heap_replace(pgrel, &tuple->t_self, tuple);
+ heap_replace(pgrel, &tuple->t_self, tuple, NULL);
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
@@ -333,17 +333,17 @@ RelationRemoveTriggers(Relation rel)
HeapTuple tup;
tgrel = heap_openr(TriggerRelationName);
- RelationSetLockForWrite(tgrel);
+ LockRelation(tgrel, AccessExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
- heap_delete(tgrel, &tup->t_self);
+ heap_delete(tgrel, &tup->t_self, NULL);
heap_endscan(tgscan);
- RelationUnsetLockForWrite(tgrel);
+ UnlockRelation(tgrel, AccessExclusiveLock);
heap_close(tgrel);
}
@@ -376,7 +376,6 @@ RelationBuildTriggers(Relation relation)
ObjectIdGetDatum(RelationGetRelid(relation)));
tgrel = heap_openr(TriggerRelationName);
- RelationSetLockForRead(tgrel);
irel = index_openr(TriggerRelidIndex);
sd = index_beginscan(irel, false, 1, &skey);
@@ -450,7 +449,6 @@ RelationBuildTriggers(Relation relation)
index_endscan(sd);
pfree(sd);
index_close(irel);
- RelationUnsetLockForRead(tgrel);
heap_close(tgrel);
/* Build trigdesc */
@@ -657,16 +655,17 @@ ExecARInsertTriggers(Relation rel, HeapTuple trigtuple)
}
bool
-ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
+ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
{
- TriggerData *SaveTriggerData;
- int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
- Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
- HeapTuple trigtuple;
- HeapTuple newtuple = NULL;
- int i;
-
- trigtuple = GetTupleForTrigger(rel, tupleid, true);
+ Relation rel = estate->es_result_relation_info->ri_RelationDesc;
+ TriggerData *SaveTriggerData;
+ int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
+ Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
+ HeapTuple trigtuple;
+ HeapTuple newtuple = NULL;
+ int i;
+
+ trigtuple = GetTupleForTrigger(estate, tupleid, true);
if (trigtuple == NULL)
return false;
@@ -692,15 +691,16 @@ ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
}
void
-ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
+ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
{
+ Relation rel = estate->es_result_relation_info->ri_RelationDesc;
TriggerData *SaveTriggerData;
int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE];
Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE];
HeapTuple trigtuple;
int i;
- trigtuple = GetTupleForTrigger(rel, tupleid, false);
+ trigtuple = GetTupleForTrigger(estate, tupleid, false);
Assert(trigtuple != NULL);
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
@@ -722,17 +722,18 @@ ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
}
HeapTuple
-ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
+ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
{
- TriggerData *SaveTriggerData;
- int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
- Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
- HeapTuple trigtuple;
- HeapTuple oldtuple;
- HeapTuple intuple = newtuple;
- int i;
-
- trigtuple = GetTupleForTrigger(rel, tupleid, true);
+ Relation rel = estate->es_result_relation_info->ri_RelationDesc;
+ TriggerData *SaveTriggerData;
+ int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
+ Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
+ HeapTuple trigtuple;
+ HeapTuple oldtuple;
+ HeapTuple intuple = newtuple;
+ int i;
+
+ trigtuple = GetTupleForTrigger(estate, tupleid, true);
if (trigtuple == NULL)
return NULL;
@@ -759,15 +760,16 @@ ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
}
void
-ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
+ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
{
+ Relation rel = estate->es_result_relation_info->ri_RelationDesc;
TriggerData *SaveTriggerData;
int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE];
Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE];
HeapTuple trigtuple;
int i;
- trigtuple = GetTupleForTrigger(rel, tupleid, false);
+ trigtuple = GetTupleForTrigger(estate, tupleid, false);
Assert(trigtuple != NULL);
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
@@ -789,48 +791,67 @@ ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
}
static HeapTuple
-GetTupleForTrigger(Relation relation, ItemPointer tid, bool before)
+GetTupleForTrigger(EState *estate, ItemPointer tid, bool before)
{
- ItemId lp;
+ Relation relation = estate->es_result_relation_info->ri_RelationDesc;
HeapTupleData tuple;
HeapTuple result;
- PageHeader dp;
- Buffer b;
+ Buffer buffer;
- b = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
+ if (before)
+ {
+ int test;
+
+ /*
+ * mark tuple for update
+ */
+ tuple.t_self = *tid;
+ test = heap_mark4update(relation, &tuple, &buffer);
+ switch (test)
+ {
+ case HeapTupleSelfUpdated:
+ ReleaseBuffer(buffer);
+ return(NULL);
- if (!BufferIsValid(b))
- elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
+ case HeapTupleMayBeUpdated:
+ break;
- dp = (PageHeader) BufferGetPage(b);
- lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+ case HeapTupleUpdated:
+ ReleaseBuffer(buffer);
+ if (XactIsoLevel == XACT_SERIALIZED)
+ elog(ERROR, "Serialize access failed due to concurrent update");
+ else
+ elog(ERROR, "Isolation level %u is not supported", XactIsoLevel);
+ return(NULL);
- Assert(ItemIdIsUsed(lp));
+ default:
+ ReleaseBuffer(buffer);
+ elog(ERROR, "Unknown status %u from heap_mark4update", test);
+ return(NULL);
+ }
+ }
+ else
+ {
+ PageHeader dp;
+ ItemId lp;
- tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
- tuple.t_len = ItemIdGetLength(lp);
- tuple.t_self = *tid;
+ buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
- if (before)
- {
- if (TupleUpdatedByCurXactAndCmd(&tuple))
- {
- elog(NOTICE, "GetTupleForTrigger: Non-functional delete/update");
- ReleaseBuffer(b);
- return NULL;
- }
+ if (!BufferIsValid(buffer))
+ elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
- HeapTupleSatisfies(&tuple, relation, b, dp,
- false, 0, (ScanKey) NULL);
- if (!tuple.t_data)
- {
- ReleaseBuffer(b);
- elog(ERROR, "GetTupleForTrigger: (am)invalid tid");
- }
+ dp = (PageHeader) BufferGetPage(buffer);
+ lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+
+ Assert(ItemIdIsUsed(lp));
+
+ tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
+ tuple.t_len = ItemIdGetLength(lp);
+ tuple.t_self = *tid;
}
result = heap_copytuple(&tuple);
- ReleaseBuffer(b);
+ ReleaseBuffer(buffer);
return result;
}