aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeModifyTable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeModifyTable.c')
-rw-r--r--src/backend/executor/nodeModifyTable.c57
1 files changed, 37 insertions, 20 deletions
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index d78e868154e..7b5214c9996 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -342,6 +342,9 @@ ExecInsert(ModifyTableState *mtstate,
mtstate->mt_transition_capture->tcs_map = NULL;
}
}
+ if (mtstate->mt_oc_transition_capture != NULL)
+ mtstate->mt_oc_transition_capture->tcs_map =
+ mtstate->mt_transition_tupconv_maps[leaf_part_index];
/*
* We might need to convert from the parent rowtype to the partition
@@ -1157,6 +1160,8 @@ lreplace:;
/* AFTER ROW UPDATE Triggers */
ExecARUpdateTriggers(estate, resultRelInfo, tupleid, oldtuple, tuple,
recheckIndexes,
+ mtstate->operation == CMD_INSERT ?
+ mtstate->mt_oc_transition_capture :
mtstate->mt_transition_capture);
list_free(recheckIndexes);
@@ -1443,7 +1448,7 @@ fireASTriggers(ModifyTableState *node)
if (node->mt_onconflict == ONCONFLICT_UPDATE)
ExecASUpdateTriggers(node->ps.state,
resultRelInfo,
- node->mt_transition_capture);
+ node->mt_oc_transition_capture);
ExecASInsertTriggers(node->ps.state, resultRelInfo,
node->mt_transition_capture);
break;
@@ -1473,14 +1478,24 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
/* Check for transition tables on the directly targeted relation. */
mtstate->mt_transition_capture =
- MakeTransitionCaptureState(targetRelInfo->ri_TrigDesc);
+ MakeTransitionCaptureState(targetRelInfo->ri_TrigDesc,
+ RelationGetRelid(targetRelInfo->ri_RelationDesc),
+ mtstate->operation);
+ if (mtstate->operation == CMD_INSERT &&
+ mtstate->mt_onconflict == ONCONFLICT_UPDATE)
+ mtstate->mt_oc_transition_capture =
+ MakeTransitionCaptureState(targetRelInfo->ri_TrigDesc,
+ RelationGetRelid(targetRelInfo->ri_RelationDesc),
+ CMD_UPDATE);
/*
* If we found that we need to collect transition tuples then we may also
* need tuple conversion maps for any children that have TupleDescs that
- * aren't compatible with the tuplestores.
+ * aren't compatible with the tuplestores. (We can share these maps
+ * between the regular and ON CONFLICT cases.)
*/
- if (mtstate->mt_transition_capture != NULL)
+ if (mtstate->mt_transition_capture != NULL ||
+ mtstate->mt_oc_transition_capture != NULL)
{
ResultRelInfo *resultRelInfos;
int numResultRelInfos;
@@ -1521,10 +1536,12 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
/*
* Install the conversion map for the first plan for UPDATE and DELETE
* operations. It will be advanced each time we switch to the next
- * plan. (INSERT operations set it every time.)
+ * plan. (INSERT operations set it every time, so we need not update
+ * mtstate->mt_oc_transition_capture here.)
*/
- mtstate->mt_transition_capture->tcs_map =
- mtstate->mt_transition_tupconv_maps[0];
+ if (mtstate->mt_transition_capture)
+ mtstate->mt_transition_capture->tcs_map =
+ mtstate->mt_transition_tupconv_maps[0];
}
}
@@ -1628,13 +1645,19 @@ ExecModifyTable(PlanState *pstate)
estate->es_result_relation_info = resultRelInfo;
EvalPlanQualSetPlan(&node->mt_epqstate, subplanstate->plan,
node->mt_arowmarks[node->mt_whichplan]);
+ /* Prepare to convert transition tuples from this child. */
if (node->mt_transition_capture != NULL)
{
- /* Prepare to convert transition tuples from this child. */
Assert(node->mt_transition_tupconv_maps != NULL);
node->mt_transition_capture->tcs_map =
node->mt_transition_tupconv_maps[node->mt_whichplan];
}
+ if (node->mt_oc_transition_capture != NULL)
+ {
+ Assert(node->mt_transition_tupconv_maps != NULL);
+ node->mt_oc_transition_capture->tcs_map =
+ node->mt_transition_tupconv_maps[node->mt_whichplan];
+ }
continue;
}
else
@@ -1933,8 +1956,12 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
mtstate->mt_partition_tuple_slot = partition_tuple_slot;
}
- /* Build state for collecting transition tuples */
- ExecSetupTransitionCaptureState(mtstate, estate);
+ /*
+ * Build state for collecting transition tuples. This requires having a
+ * valid trigger query context, so skip it in explain-only mode.
+ */
+ if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
+ ExecSetupTransitionCaptureState(mtstate, estate);
/*
* Initialize any WITH CHECK OPTION constraints if needed.
@@ -2318,16 +2345,6 @@ ExecEndModifyTable(ModifyTableState *node)
int i;
/*
- * Free transition tables, unless this query is being run in
- * EXEC_FLAG_SKIP_TRIGGERS mode, which means that it may have queued AFTER
- * triggers that won't be run till later. In that case we'll just leak
- * the transition tables till end of (sub)transaction.
- */
- if (node->mt_transition_capture != NULL &&
- !(node->ps.state->es_top_eflags & EXEC_FLAG_SKIP_TRIGGERS))
- DestroyTransitionCaptureState(node->mt_transition_capture);
-
- /*
* Allow any FDWs to shut down
*/
for (i = 0; i < node->mt_nplans; i++)