|
47 | 47 | #include "storage/lmgr.h" |
48 | 48 | #include "utils/acl.h" |
49 | 49 | #include "utils/builtins.h" |
| 50 | +#include "utils/datum.h" |
50 | 51 | #include "utils/fmgroids.h" |
51 | 52 | #include "utils/guc_hooks.h" |
52 | 53 | #include "utils/inval.h" |
53 | 54 | #include "utils/lsyscache.h" |
54 | 55 | #include "utils/memutils.h" |
55 | 56 | #include "utils/plancache.h" |
| 57 | +#include "utils/rangetypes.h" |
56 | 58 | #include "utils/rel.h" |
57 | 59 | #include "utils/snapmgr.h" |
58 | 60 | #include "utils/syscache.h" |
@@ -2649,6 +2651,7 @@ ExecBSDeleteTriggers(EState *estate, ResultRelInfo *relinfo) |
2649 | 2651 | LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | |
2650 | 2652 | TRIGGER_EVENT_BEFORE; |
2651 | 2653 | LocTriggerData.tg_relation = relinfo->ri_RelationDesc; |
| 2654 | + LocTriggerData.tg_temporal = relinfo->ri_forPortionOf; |
2652 | 2655 | for (i = 0; i < trigdesc->numtriggers; i++) |
2653 | 2656 | { |
2654 | 2657 | Trigger *trigger = &trigdesc->triggers[i]; |
@@ -2757,6 +2760,7 @@ ExecBRDeleteTriggers(EState *estate, EPQState *epqstate, |
2757 | 2760 | TRIGGER_EVENT_ROW | |
2758 | 2761 | TRIGGER_EVENT_BEFORE; |
2759 | 2762 | LocTriggerData.tg_relation = relinfo->ri_RelationDesc; |
| 2763 | + LocTriggerData.tg_temporal = relinfo->ri_forPortionOf; |
2760 | 2764 | for (i = 0; i < trigdesc->numtriggers; i++) |
2761 | 2765 | { |
2762 | 2766 | HeapTuple newtuple; |
@@ -2858,6 +2862,7 @@ ExecIRDeleteTriggers(EState *estate, ResultRelInfo *relinfo, |
2858 | 2862 | TRIGGER_EVENT_ROW | |
2859 | 2863 | TRIGGER_EVENT_INSTEAD; |
2860 | 2864 | LocTriggerData.tg_relation = relinfo->ri_RelationDesc; |
| 2865 | + LocTriggerData.tg_temporal = relinfo->ri_forPortionOf; |
2861 | 2866 |
|
2862 | 2867 | ExecForceStoreHeapTuple(trigtuple, slot, false); |
2863 | 2868 |
|
@@ -2921,6 +2926,7 @@ ExecBSUpdateTriggers(EState *estate, ResultRelInfo *relinfo) |
2921 | 2926 | TRIGGER_EVENT_BEFORE; |
2922 | 2927 | LocTriggerData.tg_relation = relinfo->ri_RelationDesc; |
2923 | 2928 | LocTriggerData.tg_updatedcols = updatedCols; |
| 2929 | + LocTriggerData.tg_temporal = relinfo->ri_forPortionOf; |
2924 | 2930 | for (i = 0; i < trigdesc->numtriggers; i++) |
2925 | 2931 | { |
2926 | 2932 | Trigger *trigger = &trigdesc->triggers[i]; |
@@ -3064,6 +3070,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, |
3064 | 3070 | TRIGGER_EVENT_ROW | |
3065 | 3071 | TRIGGER_EVENT_BEFORE; |
3066 | 3072 | LocTriggerData.tg_relation = relinfo->ri_RelationDesc; |
| 3073 | + LocTriggerData.tg_temporal = relinfo->ri_forPortionOf; |
3067 | 3074 | updatedCols = ExecGetAllUpdatedCols(relinfo, estate); |
3068 | 3075 | LocTriggerData.tg_updatedcols = updatedCols; |
3069 | 3076 | for (i = 0; i < trigdesc->numtriggers; i++) |
@@ -3226,6 +3233,7 @@ ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo, |
3226 | 3233 | TRIGGER_EVENT_ROW | |
3227 | 3234 | TRIGGER_EVENT_INSTEAD; |
3228 | 3235 | LocTriggerData.tg_relation = relinfo->ri_RelationDesc; |
| 3236 | + LocTriggerData.tg_temporal = relinfo->ri_forPortionOf; |
3229 | 3237 |
|
3230 | 3238 | ExecForceStoreHeapTuple(trigtuple, oldslot, false); |
3231 | 3239 |
|
@@ -3697,6 +3705,7 @@ typedef struct AfterTriggerSharedData |
3697 | 3705 | Oid ats_relid; /* the relation it's on */ |
3698 | 3706 | Oid ats_rolid; /* role to execute the trigger */ |
3699 | 3707 | CommandId ats_firing_id; /* ID for firing cycle */ |
| 3708 | + ForPortionOfState *for_portion_of; /* the FOR PORTION OF clause */ |
3700 | 3709 | struct AfterTriggersTableData *ats_table; /* transition table access */ |
3701 | 3710 | Bitmapset *ats_modifiedcols; /* modified columns */ |
3702 | 3711 | } AfterTriggerSharedData; |
@@ -3970,6 +3979,7 @@ static SetConstraintState SetConstraintStateCreate(int numalloc); |
3970 | 3979 | static SetConstraintState SetConstraintStateCopy(SetConstraintState origstate); |
3971 | 3980 | static SetConstraintState SetConstraintStateAddItem(SetConstraintState state, |
3972 | 3981 | Oid tgoid, bool tgisdeferred); |
| 3982 | +static ForPortionOfState *CopyForPortionOfState(ForPortionOfState *src); |
3973 | 3983 | static void cancel_prior_stmt_triggers(Oid relid, CmdType cmdType, int tgevent); |
3974 | 3984 |
|
3975 | 3985 |
|
@@ -4177,6 +4187,7 @@ afterTriggerAddEvent(AfterTriggerEventList *events, |
4177 | 4187 | newshared->ats_event == evtshared->ats_event && |
4178 | 4188 | newshared->ats_firing_id == 0 && |
4179 | 4189 | newshared->ats_table == evtshared->ats_table && |
| 4190 | + newshared->for_portion_of == evtshared->for_portion_of && |
4180 | 4191 | newshared->ats_relid == evtshared->ats_relid && |
4181 | 4192 | newshared->ats_rolid == evtshared->ats_rolid && |
4182 | 4193 | bms_equal(newshared->ats_modifiedcols, |
@@ -4553,6 +4564,9 @@ AfterTriggerExecute(EState *estate, |
4553 | 4564 | LocTriggerData.tg_relation = rel; |
4554 | 4565 | if (TRIGGER_FOR_UPDATE(LocTriggerData.tg_trigger->tgtype)) |
4555 | 4566 | LocTriggerData.tg_updatedcols = evtshared->ats_modifiedcols; |
| 4567 | + if (TRIGGER_FOR_UPDATE(LocTriggerData.tg_trigger->tgtype) || |
| 4568 | + TRIGGER_FOR_DELETE(LocTriggerData.tg_trigger->tgtype)) |
| 4569 | + LocTriggerData.tg_temporal = evtshared->for_portion_of; |
4556 | 4570 |
|
4557 | 4571 | MemoryContextReset(per_tuple_context); |
4558 | 4572 |
|
@@ -6102,6 +6116,42 @@ AfterTriggerPendingOnRel(Oid relid) |
6102 | 6116 | return false; |
6103 | 6117 | } |
6104 | 6118 |
|
| 6119 | +/* ---------- |
| 6120 | + * ForPortionOfState() |
| 6121 | + * |
| 6122 | + * Copys a ForPortionOfState into the current memory context. |
| 6123 | + */ |
| 6124 | +static ForPortionOfState * |
| 6125 | +CopyForPortionOfState(ForPortionOfState *src) |
| 6126 | +{ |
| 6127 | + ForPortionOfState *dst = NULL; |
| 6128 | + |
| 6129 | + if (src) |
| 6130 | + { |
| 6131 | + MemoryContext oldctx; |
| 6132 | + RangeType *r; |
| 6133 | + TypeCacheEntry *typcache; |
| 6134 | + |
| 6135 | + /* |
| 6136 | + * Need to lift the FOR PORTION OF details into a higher memory |
| 6137 | + * context because cascading foreign key update/deletes can cause |
| 6138 | + * triggers to fire triggers, and the AfterTriggerEvents will outlive |
| 6139 | + * the FPO details of the original query. |
| 6140 | + */ |
| 6141 | + oldctx = MemoryContextSwitchTo(TopTransactionContext); |
| 6142 | + dst = makeNode(ForPortionOfState); |
| 6143 | + dst->fp_rangeName = pstrdup(src->fp_rangeName); |
| 6144 | + dst->fp_rangeType = src->fp_rangeType; |
| 6145 | + dst->fp_rangeAttno = src->fp_rangeAttno; |
| 6146 | + |
| 6147 | + r = DatumGetRangeTypeP(src->fp_targetRange); |
| 6148 | + typcache = lookup_type_cache(RangeTypeGetOid(r), TYPECACHE_RANGE_INFO); |
| 6149 | + dst->fp_targetRange = datumCopy(src->fp_targetRange, typcache->typbyval, typcache->typlen); |
| 6150 | + MemoryContextSwitchTo(oldctx); |
| 6151 | + } |
| 6152 | + return dst; |
| 6153 | +} |
| 6154 | + |
6105 | 6155 | /* ---------- |
6106 | 6156 | * AfterTriggerSaveEvent() |
6107 | 6157 | * |
@@ -6518,6 +6568,7 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo, |
6518 | 6568 | else |
6519 | 6569 | new_shared.ats_table = NULL; |
6520 | 6570 | new_shared.ats_modifiedcols = modifiedCols; |
| 6571 | + new_shared.for_portion_of = CopyForPortionOfState(relinfo->ri_forPortionOf); |
6521 | 6572 |
|
6522 | 6573 | afterTriggerAddEvent(&afterTriggers.query_stack[afterTriggers.query_depth].events, |
6523 | 6574 | &new_event, &new_shared); |
|
0 commit comments