}
else
{
- if (!table_fetch_row_version(relation, tid, SnapshotAny, oldslot, NULL))
- elog(ERROR, "couldn't fetch tuple");
+ if (!table_fetch_row_version(relation, tid, estate->es_snapshot, oldslot, NULL))
+ {
+ /*
+ * If the tuple is not visible to the current snapshot, it has to
+ * be one that we followed via EPQ. In that case, it needs to have
+ * been modified by an already committed transaction, otherwise
+ * we'd not get here. So get a new snapshot, and try to fetch it
+ * using that.
+ * PBORKED: ZBORKED: Better approach?
+ */
+ if (!table_fetch_row_version(relation, tid, GetLatestSnapshot(), oldslot, NULL))
+ elog(PANIC, "couldn't fetch tuple");
+ }
}
return true;
typedef struct AfterTriggerEventData
{
TriggerFlags ate_flags; /* status bits and offset to shared data */
+ CommandId ate_cid1;
ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
+ CommandId ate_cid2;
ItemPointerData ate_ctid2; /* new updated tuple */
} AfterTriggerEventData;
typedef struct AfterTriggerEventDataOneCtid
{
TriggerFlags ate_flags; /* status bits and offset to shared data */
+ CommandId ate_cid1;
ItemPointerData ate_ctid1; /* inserted, deleted, or old updated tuple */
} AfterTriggerEventDataOneCtid;
break;
default:
-
- if (ItemPointerIsValid(&(event->ate_ctid1)))
{
- LocTriggerData.tg_trigslot = ExecTriggerGetOldSlot(estate, rel);
- if (!table_fetch_row_version(rel, &(event->ate_ctid1), SnapshotAny, LocTriggerData.tg_trigslot, NULL))
- elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
- LocTriggerData.tg_trigtuple = ExecFetchSlotHeapTuple(LocTriggerData.tg_trigslot, false, NULL);
+ Assert(ActiveSnapshotSet());
+ if (ItemPointerIsValid(&(event->ate_ctid1)))
+ {
+ Snapshot snap = GetActiveSnapshot();
+ CommandId saved_cid = snap->curcid;
- }
- else
- {
- LocTriggerData.tg_trigtuple = NULL;
- }
+ snap->curcid = event->ate_cid1;
- /* don't touch ctid2 if not there */
- if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
- AFTER_TRIGGER_2CTID &&
- ItemPointerIsValid(&(event->ate_ctid2)))
- {
- LocTriggerData.tg_newslot = ExecTriggerGetNewSlot(estate, rel);
- if (!table_fetch_row_version(rel, &(event->ate_ctid2), SnapshotAny, LocTriggerData.tg_newslot, NULL))
- elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
- LocTriggerData.tg_newtuple = ExecFetchSlotHeapTuple(LocTriggerData.tg_newslot, false, NULL);
- }
- else
- {
- LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_trigslot = ExecTriggerGetOldSlot(estate, rel);
+ if (!table_fetch_row_version(rel, &(event->ate_ctid1), snap, LocTriggerData.tg_trigslot, NULL))
+ elog(ERROR, "failed to fetch tuple1 for AFTER trigger");
+ LocTriggerData.tg_trigtuple = ExecFetchSlotHeapTuple(LocTriggerData.tg_trigslot, false, NULL);
+ snap->curcid = saved_cid;
+ }
+ else
+ {
+ LocTriggerData.tg_trigtuple = NULL;
+ }
+
+ /* don't touch ctid2 if not there */
+ if ((event->ate_flags & AFTER_TRIGGER_TUP_BITS) ==
+ AFTER_TRIGGER_2CTID &&
+ ItemPointerIsValid(&(event->ate_ctid2)))
+ {
+ Snapshot snap = GetActiveSnapshot();
+ CommandId saved_cid = snap->curcid;
+
+ snap->curcid = event->ate_cid2;
+
+ LocTriggerData.tg_newslot = ExecTriggerGetNewSlot(estate, rel);
+ if (!table_fetch_row_version(rel, &(event->ate_ctid2), snap, LocTriggerData.tg_newslot, NULL))
+ elog(ERROR, "failed to fetch tuple2 for AFTER trigger");
+ LocTriggerData.tg_newtuple = ExecFetchSlotHeapTuple(LocTriggerData.tg_newslot, false, NULL);
+
+ snap->curcid = saved_cid;
+ }
+ else
+ {
+ LocTriggerData.tg_newtuple = NULL;
+ }
}
}
Assert(oldslot == NULL);
Assert(newslot != NULL);
ItemPointerCopy(&(newslot->tts_tid), &(new_event.ate_ctid1));
+ new_event.ate_cid1 = estate->es_output_cid + 1;
ItemPointerSetInvalid(&(new_event.ate_ctid2));
+ new_event.ate_cid2 = InvalidCommandId;
}
else
{
Assert(oldslot == NULL);
Assert(newslot == NULL);
ItemPointerSetInvalid(&(new_event.ate_ctid1));
+ new_event.ate_cid1 = InvalidCommandId;
ItemPointerSetInvalid(&(new_event.ate_ctid2));
+ new_event.ate_cid2 = InvalidCommandId;
cancel_prior_stmt_triggers(RelationGetRelid(rel),
CMD_INSERT, event);
}
Assert(oldslot != NULL);
Assert(newslot == NULL);
ItemPointerCopy(&(oldslot->tts_tid), &(new_event.ate_ctid1));
+ new_event.ate_cid1 = estate->es_snapshot->curcid;
ItemPointerSetInvalid(&(new_event.ate_ctid2));
+ new_event.ate_cid2 = InvalidCommandId;
}
else
{
Assert(oldslot == NULL);
Assert(newslot == NULL);
ItemPointerSetInvalid(&(new_event.ate_ctid1));
+ new_event.ate_cid1 = InvalidCommandId;
ItemPointerSetInvalid(&(new_event.ate_ctid2));
+ new_event.ate_cid2 = InvalidCommandId;
cancel_prior_stmt_triggers(RelationGetRelid(rel),
CMD_DELETE, event);
}
Assert(oldslot != NULL);
Assert(newslot != NULL);
ItemPointerCopy(&(oldslot->tts_tid), &(new_event.ate_ctid1));
+ new_event.ate_cid1 = estate->es_snapshot->curcid;
ItemPointerCopy(&(newslot->tts_tid), &(new_event.ate_ctid2));
+ new_event.ate_cid2 = estate->es_output_cid + 1;
}
else
{
Assert(oldslot == NULL);
Assert(newslot == NULL);
ItemPointerSetInvalid(&(new_event.ate_ctid1));
+ new_event.ate_cid1 = InvalidCommandId;
ItemPointerSetInvalid(&(new_event.ate_ctid2));
+ new_event.ate_cid2 = InvalidCommandId;
cancel_prior_stmt_triggers(RelationGetRelid(rel),
CMD_UPDATE, event);
}
Assert(oldslot == NULL);
Assert(newslot == NULL);
ItemPointerSetInvalid(&(new_event.ate_ctid1));
+ new_event.ate_cid1 = InvalidCommandId;
ItemPointerSetInvalid(&(new_event.ate_ctid2));
+ new_event.ate_cid2 = InvalidCommandId;
break;
default:
elog(ERROR, "invalid after-trigger event code: %d", event);