diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 71d48d4574..531bd7c73a 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -2489,9 +2489,6 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo, ResultRelInfo *resultRelInfo = buffer->resultRelInfo; TupleTableSlot **slots = buffer->slots; - /* Set es_result_relation_info to the ResultRelInfo we're flushing. */ - estate->es_result_relation_info = resultRelInfo; - /* * Print error context information correctly, if one of the operations * below fail. @@ -2524,7 +2521,8 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo, cstate->cur_lineno = buffer->linenos[i]; recheckIndexes = - ExecInsertIndexTuples(buffer->slots[i], estate, false, NULL, + ExecInsertIndexTuples(resultRelInfo, + buffer->slots[i], estate, false, NULL, NIL); ExecARInsertTriggers(estate, resultRelInfo, slots[i], recheckIndexes, @@ -2839,8 +2837,6 @@ CopyFrom(CopyState cstate) ExecOpenIndices(resultRelInfo, false); - estate->es_result_relation_info = resultRelInfo; - /* * Set up a ModifyTableState so we can let FDW(s) init themselves for * foreign-table result relation(s). @@ -3108,11 +3104,6 @@ CopyFrom(CopyState cstate) prevResultRelInfo = resultRelInfo; } - /* - * For ExecInsertIndexTuples() to work on the partition's indexes - */ - estate->es_result_relation_info = resultRelInfo; - /* * If we're capturing transition tuples, we might need to convert * from the partition rowtype to root rowtype. @@ -3217,7 +3208,8 @@ CopyFrom(CopyState cstate) /* Compute stored generated columns */ if (resultRelInfo->ri_RelationDesc->rd_att->constr && resultRelInfo->ri_RelationDesc->rd_att->constr->has_generated_stored) - ExecComputeStoredGenerated(estate, myslot, CMD_INSERT); + ExecComputeStoredGenerated(resultRelInfo, estate, myslot, + CMD_INSERT); /* * If the target is a plain table, check the constraints of @@ -3288,7 +3280,8 @@ CopyFrom(CopyState cstate) myslot, mycid, ti_options, bistate); if (resultRelInfo->ri_NumIndices > 0) - recheckIndexes = ExecInsertIndexTuples(myslot, + recheckIndexes = ExecInsertIndexTuples(resultRelInfo, + myslot, estate, false, NULL, diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 80fedad5e0..511f015a86 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1820,7 +1820,6 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged, resultRelInfo = resultRelInfos; foreach(cell, rels) { - estate->es_result_relation_info = resultRelInfo; ExecBSTruncateTriggers(estate, resultRelInfo); resultRelInfo++; } @@ -1950,7 +1949,6 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged, resultRelInfo = resultRelInfos; foreach(cell, rels) { - estate->es_result_relation_info = resultRelInfo; ExecASTruncateTriggers(estate, resultRelInfo); resultRelInfo++; } diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c index 1862af621b..c6b5bcba7b 100644 --- a/src/backend/executor/execIndexing.c +++ b/src/backend/executor/execIndexing.c @@ -270,7 +270,8 @@ ExecCloseIndices(ResultRelInfo *resultRelInfo) * ---------------------------------------------------------------- */ List * -ExecInsertIndexTuples(TupleTableSlot *slot, +ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, + TupleTableSlot *slot, EState *estate, bool noDupErr, bool *specConflict, @@ -278,7 +279,6 @@ ExecInsertIndexTuples(TupleTableSlot *slot, { ItemPointer tupleid = &slot->tts_tid; List *result = NIL; - ResultRelInfo *resultRelInfo; int i; int numIndices; RelationPtr relationDescs; @@ -293,7 +293,6 @@ ExecInsertIndexTuples(TupleTableSlot *slot, /* * Get information from the result relation info structure. */ - resultRelInfo = estate->es_result_relation_info; numIndices = resultRelInfo->ri_NumIndices; relationDescs = resultRelInfo->ri_IndexRelationDescs; indexInfoArray = resultRelInfo->ri_IndexRelationInfo; @@ -479,11 +478,10 @@ ExecInsertIndexTuples(TupleTableSlot *slot, * ---------------------------------------------------------------- */ bool -ExecCheckIndexConstraints(TupleTableSlot *slot, +ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, List *arbiterIndexes) { - ResultRelInfo *resultRelInfo; int i; int numIndices; RelationPtr relationDescs; @@ -501,7 +499,6 @@ ExecCheckIndexConstraints(TupleTableSlot *slot, /* * Get information from the result relation info structure. */ - resultRelInfo = estate->es_result_relation_info; numIndices = resultRelInfo->ri_NumIndices; relationDescs = resultRelInfo->ri_IndexRelationDescs; indexInfoArray = resultRelInfo->ri_IndexRelationInfo; diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 783eecbc13..293f53d07c 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -827,9 +827,6 @@ InitPlan(QueryDesc *queryDesc, int eflags) estate->es_plannedstmt = plannedstmt; - /* es_result_relation_info is NULL except when within ModifyTable */ - estate->es_result_relation_info = NULL; - /* * Next, build the ExecRowMark array from the PlanRowMark(s), if any. */ @@ -2694,7 +2691,6 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree) * subplans themselves are initialized. */ parentestate->es_result_relations = NULL; - /* es_result_relation_info must NOT be copied */ /* es_trig_target_relations must NOT be copied */ rcestate->es_top_eflags = parentestate->es_top_eflags; rcestate->es_instrument = parentestate->es_instrument; diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c index b29db7bf4f..01d26881e7 100644 --- a/src/backend/executor/execReplication.c +++ b/src/backend/executor/execReplication.c @@ -404,10 +404,10 @@ retry: * Caller is responsible for opening the indexes. */ void -ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) +ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo, + EState *estate, TupleTableSlot *slot) { bool skip_tuple = false; - ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; /* For now we support only tables. */ @@ -430,7 +430,8 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) /* Compute stored generated columns */ if (rel->rd_att->constr && rel->rd_att->constr->has_generated_stored) - ExecComputeStoredGenerated(estate, slot, CMD_INSERT); + ExecComputeStoredGenerated(resultRelInfo, estate, slot, + CMD_INSERT); /* Check the constraints of the tuple */ if (rel->rd_att->constr) @@ -442,7 +443,8 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot); if (resultRelInfo->ri_NumIndices > 0) - recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, + recheckIndexes = ExecInsertIndexTuples(resultRelInfo, + slot, estate, false, NULL, NIL); /* AFTER ROW INSERT Triggers */ @@ -466,11 +468,11 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) * Caller is responsible for opening the indexes. */ void -ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, +ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo, + EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot) { bool skip_tuple = false; - ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; ItemPointer tid = &(searchslot->tts_tid); @@ -496,7 +498,8 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, /* Compute stored generated columns */ if (rel->rd_att->constr && rel->rd_att->constr->has_generated_stored) - ExecComputeStoredGenerated(estate, slot, CMD_UPDATE); + ExecComputeStoredGenerated(resultRelInfo, estate, slot, + CMD_UPDATE); /* Check the constraints of the tuple */ if (rel->rd_att->constr) @@ -508,7 +511,8 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, &update_indexes); if (resultRelInfo->ri_NumIndices > 0 && update_indexes) - recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, + recheckIndexes = ExecInsertIndexTuples(resultRelInfo, + slot, estate, false, NULL, NIL); /* AFTER ROW UPDATE Triggers */ @@ -527,11 +531,11 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, * Caller is responsible for opening the indexes. */ void -ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, +ExecSimpleRelationDelete(ResultRelInfo *resultRelInfo, + EState *estate, EPQState *epqstate, TupleTableSlot *searchslot) { bool skip_tuple = false; - ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; ItemPointer tid = &searchslot->tts_tid; diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 6d8c112e2f..071a0007eb 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -125,7 +125,6 @@ CreateExecutorState(void) estate->es_result_relations = NULL; estate->es_opened_result_relations = NIL; - estate->es_result_relation_info = NULL; estate->es_tuple_routing_result_relations = NIL; estate->es_trig_target_relations = NIL; diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c index b3f7012e38..6782a2dcd2 100644 --- a/src/backend/executor/nodeModifyTable.c +++ b/src/backend/executor/nodeModifyTable.c @@ -70,7 +70,8 @@ static TupleTableSlot *ExecPrepareTupleRouting(ModifyTableState *mtstate, EState *estate, PartitionTupleRouting *proute, ResultRelInfo *targetRelInfo, - TupleTableSlot *slot); + TupleTableSlot *slot, + ResultRelInfo **partRelInfo); static ResultRelInfo *getTargetResultRelInfo(ModifyTableState *node); static void ExecSetupChildParentMapForSubplan(ModifyTableState *mtstate); static TupleConversionMap *tupconv_map_for_subplan(ModifyTableState *node, @@ -246,9 +247,10 @@ ExecCheckTIDVisible(EState *estate, * Compute stored generated columns for a tuple */ void -ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype) +ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, + EState *estate, TupleTableSlot *slot, + CmdType cmdtype) { - ResultRelInfo *resultRelInfo = estate->es_result_relation_info; Relation rel = resultRelInfo->ri_RelationDesc; TupleDesc tupdesc = RelationGetDescr(rel); int natts = tupdesc->natts; @@ -366,32 +368,48 @@ ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype * ExecInsert * * For INSERT, we have to insert the tuple into the target relation - * and insert appropriate tuples into the index relations. + * (or partition thereof) and insert appropriate tuples into the index + * relations. * * Returns RETURNING result if any, otherwise NULL. + * + * This may change the currently active tuple conversion map in + * mtstate->mt_transition_capture, so the callers must take care to + * save the previous value to avoid losing track of it. * ---------------------------------------------------------------- */ static TupleTableSlot * ExecInsert(ModifyTableState *mtstate, + ResultRelInfo *resultRelInfo, TupleTableSlot *slot, TupleTableSlot *planSlot, EState *estate, bool canSetTag) { - ResultRelInfo *resultRelInfo; Relation resultRelationDesc; List *recheckIndexes = NIL; TupleTableSlot *result = NULL; TransitionCaptureState *ar_insert_trig_tcs; ModifyTable *node = (ModifyTable *) mtstate->ps.plan; OnConflictAction onconflict = node->onConflictAction; + PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing; + + /* + * If the input result relation is a partitioned table, find the leaf + * partition to insert the tuple into. + */ + if (proute) + { + ResultRelInfo *partRelInfo; + + slot = ExecPrepareTupleRouting(mtstate, estate, proute, + resultRelInfo, slot, + &partRelInfo); + resultRelInfo = partRelInfo; + } ExecMaterializeSlot(slot); - /* - * get information on the (current) result relation - */ - resultRelInfo = estate->es_result_relation_info; resultRelationDesc = resultRelInfo->ri_RelationDesc; /* @@ -424,7 +442,8 @@ ExecInsert(ModifyTableState *mtstate, */ if (resultRelationDesc->rd_att->constr && resultRelationDesc->rd_att->constr->has_generated_stored) - ExecComputeStoredGenerated(estate, slot, CMD_INSERT); + ExecComputeStoredGenerated(resultRelInfo, estate, slot, + CMD_INSERT); /* * insert into foreign table: let the FDW do it @@ -459,7 +478,8 @@ ExecInsert(ModifyTableState *mtstate, */ if (resultRelationDesc->rd_att->constr && resultRelationDesc->rd_att->constr->has_generated_stored) - ExecComputeStoredGenerated(estate, slot, CMD_INSERT); + ExecComputeStoredGenerated(resultRelInfo, estate, slot, + CMD_INSERT); /* * Check any RLS WITH CHECK policies. @@ -521,8 +541,8 @@ ExecInsert(ModifyTableState *mtstate, */ vlock: specConflict = false; - if (!ExecCheckIndexConstraints(slot, estate, &conflictTid, - arbiterIndexes)) + if (!ExecCheckIndexConstraints(resultRelInfo, slot, estate, + &conflictTid, arbiterIndexes)) { /* committed conflict tuple found */ if (onconflict == ONCONFLICT_UPDATE) @@ -582,7 +602,8 @@ ExecInsert(ModifyTableState *mtstate, specToken); /* insert index entries for tuple */ - recheckIndexes = ExecInsertIndexTuples(slot, estate, true, + recheckIndexes = ExecInsertIndexTuples(resultRelInfo, + slot, estate, true, &specConflict, arbiterIndexes); @@ -621,8 +642,9 @@ ExecInsert(ModifyTableState *mtstate, /* insert index entries for tuple */ if (resultRelInfo->ri_NumIndices > 0) - recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, - NIL); + recheckIndexes = ExecInsertIndexTuples(resultRelInfo, + slot, estate, false, + NULL, NIL); } } @@ -707,6 +729,7 @@ ExecInsert(ModifyTableState *mtstate, */ static TupleTableSlot * ExecDelete(ModifyTableState *mtstate, + ResultRelInfo *resultRelInfo, ItemPointer tupleid, HeapTuple oldtuple, TupleTableSlot *planSlot, @@ -718,8 +741,7 @@ ExecDelete(ModifyTableState *mtstate, bool *tupleDeleted, TupleTableSlot **epqreturnslot) { - ResultRelInfo *resultRelInfo; - Relation resultRelationDesc; + Relation resultRelationDesc = resultRelInfo->ri_RelationDesc; TM_Result result; TM_FailureData tmfd; TupleTableSlot *slot = NULL; @@ -728,12 +750,6 @@ ExecDelete(ModifyTableState *mtstate, if (tupleDeleted) *tupleDeleted = false; - /* - * get information on the (current) result relation - */ - resultRelInfo = estate->es_result_relation_info; - resultRelationDesc = resultRelInfo->ri_RelationDesc; - /* BEFORE ROW DELETE Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_delete_before_row) @@ -1067,6 +1083,7 @@ ldelete:; */ static TupleTableSlot * ExecUpdate(ModifyTableState *mtstate, + ResultRelInfo *resultRelInfo, ItemPointer tupleid, HeapTuple oldtuple, TupleTableSlot *slot, @@ -1075,12 +1092,10 @@ ExecUpdate(ModifyTableState *mtstate, EState *estate, bool canSetTag) { - ResultRelInfo *resultRelInfo; - Relation resultRelationDesc; + Relation resultRelationDesc = resultRelInfo->ri_RelationDesc; TM_Result result; TM_FailureData tmfd; List *recheckIndexes = NIL; - TupleConversionMap *saved_tcs_map = NULL; /* * abort the operation if not running transactions @@ -1090,12 +1105,6 @@ ExecUpdate(ModifyTableState *mtstate, ExecMaterializeSlot(slot); - /* - * get information on the (current) result relation - */ - resultRelInfo = estate->es_result_relation_info; - resultRelationDesc = resultRelInfo->ri_RelationDesc; - /* BEFORE ROW UPDATE Triggers */ if (resultRelInfo->ri_TrigDesc && resultRelInfo->ri_TrigDesc->trig_update_before_row) @@ -1120,7 +1129,8 @@ ExecUpdate(ModifyTableState *mtstate, */ if (resultRelationDesc->rd_att->constr && resultRelationDesc->rd_att->constr->has_generated_stored) - ExecComputeStoredGenerated(estate, slot, CMD_UPDATE); + ExecComputeStoredGenerated(resultRelInfo, estate, slot, + CMD_UPDATE); /* * update in foreign table: let the FDW do it @@ -1157,7 +1167,8 @@ ExecUpdate(ModifyTableState *mtstate, */ if (resultRelationDesc->rd_att->constr && resultRelationDesc->rd_att->constr->has_generated_stored) - ExecComputeStoredGenerated(estate, slot, CMD_UPDATE); + ExecComputeStoredGenerated(resultRelInfo, estate, slot, + CMD_UPDATE); /* * Check any RLS UPDATE WITH CHECK policies @@ -1207,6 +1218,7 @@ lreplace:; PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing; int map_index; TupleConversionMap *tupconv_map; + TupleConversionMap *saved_tcs_map = NULL; /* * Disallow an INSERT ON CONFLICT DO UPDATE that causes the @@ -1232,9 +1244,12 @@ lreplace:; * Row movement, part 1. Delete the tuple, but skip RETURNING * processing. We want to return rows from INSERT. */ - ExecDelete(mtstate, tupleid, oldtuple, planSlot, epqstate, - estate, false, false /* canSetTag */ , - true /* changingPart */ , &tuple_deleted, &epqslot); + ExecDelete(mtstate, resultRelInfo, tupleid, oldtuple, planSlot, + epqstate, estate, + false, /* processReturning */ + false, /* canSetTag */ + true, /* changingPart */ + &tuple_deleted, &epqslot); /* * For some reason if DELETE didn't happen (e.g. trigger prevented @@ -1274,16 +1289,6 @@ lreplace:; } } - /* - * Updates set the transition capture map only when a new subplan - * is chosen. But for inserts, it is set for each row. So after - * INSERT, we need to revert back to the map created for UPDATE; - * otherwise the next UPDATE will incorrectly use the one created - * for INSERT. So first save the one created for UPDATE. - */ - if (mtstate->mt_transition_capture) - saved_tcs_map = mtstate->mt_transition_capture->tcs_map; - /* * resultRelInfo is one of the per-subplan resultRelInfos. So we * should convert the tuple into root's tuple descriptor, since @@ -1301,18 +1306,18 @@ lreplace:; mtstate->mt_root_tuple_slot); /* - * Prepare for tuple routing, making it look like we're inserting - * into the root. + * ExecInsert() may scribble on mtstate->mt_transition_capture, so + * save the currently active map. */ + if (mtstate->mt_transition_capture) + saved_tcs_map = mtstate->mt_transition_capture->tcs_map; + + /* Tuple routing starts from the root table. */ Assert(mtstate->rootResultRelInfo != NULL); - slot = ExecPrepareTupleRouting(mtstate, estate, proute, - mtstate->rootResultRelInfo, slot); + ret_slot = ExecInsert(mtstate, mtstate->rootResultRelInfo, slot, + planSlot, estate, canSetTag); - ret_slot = ExecInsert(mtstate, slot, planSlot, - estate, canSetTag); - - /* Revert ExecPrepareTupleRouting's node change. */ - estate->es_result_relation_info = resultRelInfo; + /* Clear the INSERT's tuple and restore the saved map. */ if (mtstate->mt_transition_capture) { mtstate->mt_transition_capture->tcs_original_insert_tuple = NULL; @@ -1476,7 +1481,9 @@ lreplace:; /* insert index entries for tuple if necessary */ if (resultRelInfo->ri_NumIndices > 0 && update_indexes) - recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, NIL); + recheckIndexes = ExecInsertIndexTuples(resultRelInfo, + slot, estate, false, + NULL, NIL); } if (canSetTag) @@ -1715,7 +1722,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate, */ /* Execute UPDATE with projection */ - *returning = ExecUpdate(mtstate, conflictTid, NULL, + *returning = ExecUpdate(mtstate, resultRelInfo, conflictTid, NULL, resultRelInfo->ri_onConflict->oc_ProjSlot, planSlot, &mtstate->mt_epqstate, mtstate->ps.state, @@ -1872,19 +1879,19 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate) * ExecPrepareTupleRouting --- prepare for routing one tuple * * Determine the partition in which the tuple in slot is to be inserted, - * and modify mtstate and estate to prepare for it. + * and return its ResultRelInfo in *partRelInfo. The return value is + * a slot holding the tuple of the partition rowtype. * - * Caller must revert the estate changes after executing the insertion! - * In mtstate, transition capture changes may also need to be reverted. - * - * Returns a slot holding the tuple of the partition rowtype. + * This also sets the transition table information in mtstate based on the + * selected partition. */ static TupleTableSlot * ExecPrepareTupleRouting(ModifyTableState *mtstate, EState *estate, PartitionTupleRouting *proute, ResultRelInfo *targetRelInfo, - TupleTableSlot *slot) + TupleTableSlot *slot, + ResultRelInfo **partRelInfo) { ResultRelInfo *partrel; PartitionRoutingInfo *partrouteinfo; @@ -1901,11 +1908,6 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, partrouteinfo = partrel->ri_PartitionInfo; Assert(partrouteinfo != NULL); - /* - * Make it look like we are inserting into the partition. - */ - estate->es_result_relation_info = partrel; - /* * If we're capturing transition tuples, we might need to convert from the * partition rowtype to root partitioned table's rowtype. @@ -1950,6 +1952,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate, slot = execute_attr_map_slot(map->attrMap, slot, new_slot); } + *partRelInfo = partrel; return slot; } @@ -2016,10 +2019,8 @@ static TupleTableSlot * ExecModifyTable(PlanState *pstate) { ModifyTableState *node = castNode(ModifyTableState, pstate); - PartitionTupleRouting *proute = node->mt_partition_tuple_routing; EState *estate = node->ps.state; CmdType operation = node->operation; - ResultRelInfo *saved_resultRelInfo; ResultRelInfo *resultRelInfo; PlanState *subplanstate; JunkFilter *junkfilter; @@ -2067,17 +2068,6 @@ ExecModifyTable(PlanState *pstate) subplanstate = node->mt_plans[node->mt_whichplan]; junkfilter = resultRelInfo->ri_junkFilter; - /* - * es_result_relation_info must point to the currently active result - * relation while we are within this ModifyTable node. Even though - * ModifyTable nodes can't be nested statically, they can be nested - * dynamically (since our subplan could include a reference to a modifying - * CTE). So we have to save and restore the caller's value. - */ - saved_resultRelInfo = estate->es_result_relation_info; - - estate->es_result_relation_info = resultRelInfo; - /* * Fetch rows from subplan(s), and execute the required table modification * for each row. @@ -2111,7 +2101,6 @@ ExecModifyTable(PlanState *pstate) resultRelInfo++; subplanstate = node->mt_plans[node->mt_whichplan]; junkfilter = resultRelInfo->ri_junkFilter; - 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. */ @@ -2156,7 +2145,6 @@ ExecModifyTable(PlanState *pstate) */ slot = ExecProcessReturning(resultRelInfo, NULL, planSlot); - estate->es_result_relation_info = saved_resultRelInfo; return slot; } @@ -2239,25 +2227,21 @@ ExecModifyTable(PlanState *pstate) switch (operation) { case CMD_INSERT: - /* Prepare for tuple routing if needed. */ - if (proute) - slot = ExecPrepareTupleRouting(node, estate, proute, - resultRelInfo, slot); - slot = ExecInsert(node, slot, planSlot, + slot = ExecInsert(node, resultRelInfo, slot, planSlot, estate, node->canSetTag); - /* Revert ExecPrepareTupleRouting's state change. */ - if (proute) - estate->es_result_relation_info = resultRelInfo; break; case CMD_UPDATE: - slot = ExecUpdate(node, tupleid, oldtuple, slot, planSlot, - &node->mt_epqstate, estate, node->canSetTag); + slot = ExecUpdate(node, resultRelInfo, tupleid, oldtuple, slot, + planSlot, &node->mt_epqstate, estate, + node->canSetTag); break; case CMD_DELETE: - slot = ExecDelete(node, tupleid, oldtuple, planSlot, - &node->mt_epqstate, estate, - true, node->canSetTag, - false /* changingPart */ , NULL, NULL); + slot = ExecDelete(node, resultRelInfo, tupleid, oldtuple, + planSlot, &node->mt_epqstate, estate, + true, /* processReturning */ + node->canSetTag, + false, /* changingPart */ + NULL, NULL); break; default: elog(ERROR, "unknown operation"); @@ -2269,15 +2253,9 @@ ExecModifyTable(PlanState *pstate) * the work on next call. */ if (slot) - { - estate->es_result_relation_info = saved_resultRelInfo; return slot; - } } - /* Restore es_result_relation_info before exiting */ - estate->es_result_relation_info = saved_resultRelInfo; - /* * We're done, but fire AFTER STATEMENT triggers before exiting. */ @@ -2298,7 +2276,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) ModifyTableState *mtstate; CmdType operation = node->operation; int nplans = list_length(node->plans); - ResultRelInfo *saved_resultRelInfo; ResultRelInfo *resultRelInfo; Plan *subplan; ListCell *l, @@ -2346,14 +2323,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) * call ExecInitNode on each of the plans to be executed and save the * results into the array "mt_plans". This is also a convenient place to * verify that the proposed target relations are valid and open their - * indexes for insertion of new index entries. Note we *must* set - * estate->es_result_relation_info correctly while we initialize each - * sub-plan; external modules such as FDWs may depend on that (see - * contrib/postgres_fdw/postgres_fdw.c: postgresBeginDirectModify() as one - * example). + * indexes for insertion of new index entries. */ - saved_resultRelInfo = estate->es_result_relation_info; - resultRelInfo = mtstate->resultRelInfo; i = 0; forboth(l, node->resultRelations, l1, node->plans) @@ -2400,7 +2371,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) update_tuple_routing_needed = true; /* Now init the plan for this result rel */ - estate->es_result_relation_info = resultRelInfo; mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags); mtstate->mt_scans[i] = ExecInitExtraTupleSlot(mtstate->ps.state, ExecGetResultType(mtstate->mt_plans[i]), @@ -2424,8 +2394,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags) i++; } - estate->es_result_relation_info = saved_resultRelInfo; - /* Get the target relation */ rel = (getTargetResultRelInfo(mtstate))->ri_RelationDesc; diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 8d5d9e05b3..4f32dc74c8 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -1174,7 +1174,6 @@ apply_handle_insert(StringInfo s) &TTSOpsVirtual); resultRelInfo = makeNode(ResultRelInfo); InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); - estate->es_result_relation_info = resultRelInfo; /* Input functions may need an active snapshot, so get one */ PushActiveSnapshot(GetTransactionSnapshot()); @@ -1214,7 +1213,7 @@ apply_handle_insert_internal(ResultRelInfo *relinfo, ExecOpenIndices(relinfo, false); /* Do the insert. */ - ExecSimpleRelationInsert(estate, remoteslot); + ExecSimpleRelationInsert(relinfo, estate, remoteslot); /* Cleanup. */ ExecCloseIndices(relinfo); @@ -1300,7 +1299,6 @@ apply_handle_update(StringInfo s) &TTSOpsVirtual); resultRelInfo = makeNode(ResultRelInfo); InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); - estate->es_result_relation_info = resultRelInfo; /* * Populate updatedCols so that per-column triggers can fire. This could @@ -1392,7 +1390,8 @@ apply_handle_update_internal(ResultRelInfo *relinfo, EvalPlanQualSetSlot(&epqstate, remoteslot); /* Do the actual update. */ - ExecSimpleRelationUpdate(estate, &epqstate, localslot, remoteslot); + ExecSimpleRelationUpdate(relinfo, estate, &epqstate, localslot, + remoteslot); } else { @@ -1455,7 +1454,6 @@ apply_handle_delete(StringInfo s) &TTSOpsVirtual); resultRelInfo = makeNode(ResultRelInfo); InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); - estate->es_result_relation_info = resultRelInfo; PushActiveSnapshot(GetTransactionSnapshot()); @@ -1508,7 +1506,7 @@ apply_handle_delete_internal(ResultRelInfo *relinfo, EState *estate, EvalPlanQualSetSlot(&epqstate, localslot); /* Do the actual delete. */ - ExecSimpleRelationDelete(estate, &epqstate, localslot); + ExecSimpleRelationDelete(relinfo, estate, &epqstate, localslot); } else { @@ -1616,7 +1614,6 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo, } MemoryContextSwitchTo(oldctx); - estate->es_result_relation_info = partrelinfo; switch (operation) { case CMD_INSERT: @@ -1697,8 +1694,8 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo, ExecOpenIndices(partrelinfo, false); EvalPlanQualSetSlot(&epqstate, remoteslot_part); - ExecSimpleRelationUpdate(estate, &epqstate, localslot, - remoteslot_part); + ExecSimpleRelationUpdate(partrelinfo, estate, &epqstate, + localslot, remoteslot_part); ExecCloseIndices(partrelinfo); EvalPlanQualEnd(&epqstate); } @@ -1739,7 +1736,6 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo, Assert(partrelinfo_new != partrelinfo); /* DELETE old tuple found in the old partition. */ - estate->es_result_relation_info = partrelinfo; apply_handle_delete_internal(partrelinfo, estate, localslot, &relmapentry->remoterel); @@ -1771,7 +1767,6 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo, slot_getallattrs(remoteslot); } MemoryContextSwitchTo(oldctx); - estate->es_result_relation_info = partrelinfo_new; apply_handle_insert_internal(partrelinfo_new, estate, remoteslot_part); } diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index c283bf1454..b7978cd22e 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -576,10 +576,14 @@ extern TupleTableSlot *ExecGetReturningSlot(EState *estate, ResultRelInfo *relIn */ extern void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative); extern void ExecCloseIndices(ResultRelInfo *resultRelInfo); -extern List *ExecInsertIndexTuples(TupleTableSlot *slot, EState *estate, bool noDupErr, +extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, + TupleTableSlot *slot, EState *estate, + bool noDupErr, bool *specConflict, List *arbiterIndexes); -extern bool ExecCheckIndexConstraints(TupleTableSlot *slot, EState *estate, - ItemPointer conflictTid, List *arbiterIndexes); +extern bool ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, + TupleTableSlot *slot, + EState *estate, ItemPointer conflictTid, + List *arbiterIndexes); extern void check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, @@ -596,10 +600,13 @@ extern bool RelationFindReplTupleByIndex(Relation rel, Oid idxoid, extern bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, TupleTableSlot *searchslot, TupleTableSlot *outslot); -extern void ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot); -extern void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, +extern void ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo, + EState *estate, TupleTableSlot *slot); +extern void ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo, + EState *estate, EPQState *epqstate, TupleTableSlot *searchslot, TupleTableSlot *slot); -extern void ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, +extern void ExecSimpleRelationDelete(ResultRelInfo *resultRelInfo, + EState *estate, EPQState *epqstate, TupleTableSlot *searchslot); extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd); diff --git a/src/include/executor/nodeModifyTable.h b/src/include/executor/nodeModifyTable.h index 4ec4ebdabc..46a2dc9511 100644 --- a/src/include/executor/nodeModifyTable.h +++ b/src/include/executor/nodeModifyTable.h @@ -15,7 +15,9 @@ #include "nodes/execnodes.h" -extern void ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype); +extern void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo, + EState *estate, TupleTableSlot *slot, + CmdType cmdtype); extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags); extern void ExecEndModifyTable(ModifyTableState *node); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index d9b09c5920..b7e9e5d539 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -525,7 +525,6 @@ typedef struct EState List *es_opened_result_relations; /* List of non-NULL entries in * es_result_relations in no * specific order */ - ResultRelInfo *es_result_relation_info; /* currently active array elt */ PartitionDirectory es_partition_directory; /* for PartitionDesc lookup */ diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out index eb9d45be5e..da50ee3b67 100644 --- a/src/test/regress/expected/insert.out +++ b/src/test/regress/expected/insert.out @@ -818,9 +818,7 @@ drop role regress_coldesc_role; drop table inserttest3; drop table brtrigpartcon; drop function brtrigpartcon1trigf(); --- check that "do nothing" BR triggers work with tuple-routing (this checks --- that estate->es_result_relation_info is appropriately set/reset for each --- routed tuple) +-- check that "do nothing" BR triggers work with tuple-routing create table donothingbrtrig_test (a int, b text) partition by list (a); create table donothingbrtrig_test1 (b text, a int); create table donothingbrtrig_test2 (c text, b text, a int); diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql index ffd4aacbc4..963faa1614 100644 --- a/src/test/regress/sql/insert.sql +++ b/src/test/regress/sql/insert.sql @@ -542,9 +542,7 @@ drop table inserttest3; drop table brtrigpartcon; drop function brtrigpartcon1trigf(); --- check that "do nothing" BR triggers work with tuple-routing (this checks --- that estate->es_result_relation_info is appropriately set/reset for each --- routed tuple) +-- check that "do nothing" BR triggers work with tuple-routing create table donothingbrtrig_test (a int, b text) partition by list (a); create table donothingbrtrig_test1 (b text, a int); create table donothingbrtrig_test2 (c text, b text, a int);