diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index 354fbe4b4b..93c313dee6 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -335,13 +335,16 @@ handle_streamed_transaction(LogicalRepMsgType action, StringInfo s) } /* - * Executor state preparation for evaluation of constraint expressions, - * indexes and triggers. + * Prepares an EState containing just enough information for the caller to + * use the executor for evaluating the target relation's constraints, update + * indexes, and fire any AFTER triggers. * - * This is based on similar code in copy.c + * A ResultRelInfo for the relation to be passed to executor routines is + * returned in *resultRelInfo. */ static EState * -create_estate_for_relation(LogicalRepRelMapEntry *rel) +create_estate_for_relation(LogicalRepRelMapEntry *rel, + ResultRelInfo **resultRelInfo) { EState *estate; RangeTblEntry *rte; @@ -355,6 +358,9 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel) rte->rellockmode = AccessShareLock; ExecInitRangeTable(estate, list_make1(rte)); + *resultRelInfo = makeNode(ResultRelInfo); + ExecInitResultRelation(estate, *resultRelInfo, 1); + estate->es_output_cid = GetCurrentCommandId(true); /* Prepare to catch AFTER triggers. */ @@ -363,6 +369,19 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel) return estate; } +/* Winds down the executor created in create_estate_for_relation(). */ +static void +close_estate(EState *estate) +{ + /* Handle any queued AFTER triggers. */ + AfterTriggerEndQuery(estate); + + /* Cleanup. */ + ExecResetTupleTable(estate->es_tupleTable, false); + ExecCloseRangeTableRelations(estate); + FreeExecutorState(estate); +} + /* * Executes default values for columns for which we can't map to remote * relation columns. @@ -1168,12 +1187,10 @@ apply_handle_insert(StringInfo s) } /* Initialize the executor state. */ - estate = create_estate_for_relation(rel); + estate = create_estate_for_relation(rel, &resultRelInfo); remoteslot = ExecInitExtraTupleSlot(estate, RelationGetDescr(rel->localrel), &TTSOpsVirtual); - resultRelInfo = makeNode(ResultRelInfo); - InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); /* Input functions may need an active snapshot, so get one */ PushActiveSnapshot(GetTransactionSnapshot()); @@ -1194,11 +1211,7 @@ apply_handle_insert(StringInfo s) PopActiveSnapshot(); - /* Handle queued AFTER triggers. */ - AfterTriggerEndQuery(estate); - - ExecResetTupleTable(estate->es_tupleTable, false); - FreeExecutorState(estate); + close_estate(estate); logicalrep_rel_close(rel, NoLock); @@ -1293,12 +1306,10 @@ apply_handle_update(StringInfo s) check_relation_updatable(rel); /* Initialize the executor state. */ - estate = create_estate_for_relation(rel); + estate = create_estate_for_relation(rel, &resultRelInfo); remoteslot = ExecInitExtraTupleSlot(estate, RelationGetDescr(rel->localrel), &TTSOpsVirtual); - resultRelInfo = makeNode(ResultRelInfo); - InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); /* * Populate updatedCols so that per-column triggers can fire, and so @@ -1345,11 +1356,7 @@ apply_handle_update(StringInfo s) PopActiveSnapshot(); - /* Handle queued AFTER triggers. */ - AfterTriggerEndQuery(estate); - - ExecResetTupleTable(estate->es_tupleTable, false); - FreeExecutorState(estate); + close_estate(estate); logicalrep_rel_close(rel, NoLock); @@ -1450,12 +1457,10 @@ apply_handle_delete(StringInfo s) check_relation_updatable(rel); /* Initialize the executor state. */ - estate = create_estate_for_relation(rel); + estate = create_estate_for_relation(rel, &resultRelInfo); remoteslot = ExecInitExtraTupleSlot(estate, RelationGetDescr(rel->localrel), &TTSOpsVirtual); - resultRelInfo = makeNode(ResultRelInfo); - InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); PushActiveSnapshot(GetTransactionSnapshot()); @@ -1474,11 +1479,7 @@ apply_handle_delete(StringInfo s) PopActiveSnapshot(); - /* Handle queued AFTER triggers. */ - AfterTriggerEndQuery(estate); - - ExecResetTupleTable(estate->es_tupleTable, false); - FreeExecutorState(estate); + close_estate(estate); logicalrep_rel_close(rel, NoLock);