diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 4265687afa4d..60320440fc56 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -511,16 +511,18 @@ brininsertcleanup(Relation index, IndexInfo *indexInfo) BrinInsertState *bistate = (BrinInsertState *) indexInfo->ii_AmCache; /* bail out if cache not initialized */ - if (indexInfo->ii_AmCache == NULL) + if (bistate == NULL) return; + /* do this first to avoid dangling pointer if we fail partway through */ + indexInfo->ii_AmCache = NULL; + /* * Clean up the revmap. Note that the brinDesc has already been cleaned up * as part of its own memory context. */ brinRevmapTerminate(bistate->bis_rmAccess); - bistate->bis_rmAccess = NULL; - bistate->bis_desc = NULL; + pfree(bistate); } /* diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c index 7c87f012c30a..742f3f8c08da 100644 --- a/src/backend/executor/execIndexing.c +++ b/src/backend/executor/execIndexing.c @@ -181,6 +181,9 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative) if (len == 0) return; + /* This Assert will fail if ExecOpenIndices is called twice */ + Assert(resultRelInfo->ri_IndexRelationDescs == NULL); + /* * allocate space for result arrays */ @@ -246,19 +249,23 @@ ExecCloseIndices(ResultRelInfo *resultRelInfo) for (i = 0; i < numIndices; i++) { - if (indexDescs[i] == NULL) - continue; /* shouldn't happen? */ + /* This Assert will fail if ExecCloseIndices is called twice */ + Assert(indexDescs[i] != NULL); /* Give the index a chance to do some post-insert cleanup */ index_insert_cleanup(indexDescs[i], indexInfos[i]); /* Drop lock acquired by ExecOpenIndices */ index_close(indexDescs[i], RowExclusiveLock); + + /* Mark the index as closed */ + indexDescs[i] = NULL; } /* - * XXX should free indexInfo array here too? Currently we assume that - * such stuff will be cleaned up automatically in FreeExecutorState. + * We don't attempt to free the IndexInfo data structures or the arrays, + * instead assuming that such stuff will be cleaned up automatically in + * FreeExecutorState. */ } diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c index f09ab41c6058..a79c80e656cf 100644 --- a/src/backend/replication/logical/worker.c +++ b/src/backend/replication/logical/worker.c @@ -2454,8 +2454,13 @@ apply_handle_insert(StringInfo s) apply_handle_tuple_routing(edata, remoteslot, NULL, CMD_INSERT); else - apply_handle_insert_internal(edata, edata->targetRelInfo, - remoteslot); + { + ResultRelInfo *relinfo = edata->targetRelInfo; + + ExecOpenIndices(relinfo, true); + apply_handle_insert_internal(edata, relinfo, remoteslot); + ExecCloseIndices(relinfo); + } finish_edata(edata); @@ -2482,16 +2487,13 @@ apply_handle_insert_internal(ApplyExecutionData *edata, { EState *estate = edata->estate; - /* We must open indexes here. */ - ExecOpenIndices(relinfo, true); + /* Caller will not have done this bit. */ + Assert(relinfo->ri_onConflictArbiterIndexes == NIL); InitConflictIndexes(relinfo); /* Do the insert. */ TargetPrivilegesCheck(relinfo->ri_RelationDesc, ACL_INSERT); ExecSimpleRelationInsert(relinfo, estate, remoteslot); - - /* Cleanup. */ - ExecCloseIndices(relinfo); } /* @@ -2816,8 +2818,14 @@ apply_handle_delete(StringInfo s) apply_handle_tuple_routing(edata, remoteslot, NULL, CMD_DELETE); else - apply_handle_delete_internal(edata, edata->targetRelInfo, + { + ResultRelInfo *relinfo = edata->targetRelInfo; + + ExecOpenIndices(relinfo, false); + apply_handle_delete_internal(edata, relinfo, remoteslot, rel->localindexoid); + ExecCloseIndices(relinfo); + } finish_edata(edata); @@ -2851,7 +2859,6 @@ apply_handle_delete_internal(ApplyExecutionData *edata, bool found; EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1, NIL); - ExecOpenIndices(relinfo, false); found = FindReplTupleInLocalRel(edata, localrel, remoterel, localindexoid, remoteslot, &localslot); @@ -2892,7 +2899,6 @@ apply_handle_delete_internal(ApplyExecutionData *edata, } /* Cleanup. */ - ExecCloseIndices(relinfo); EvalPlanQualEnd(&epqstate); } @@ -3131,7 +3137,6 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, * work already done above to find the local tuple in the * partition. */ - ExecOpenIndices(partrelinfo, true); InitConflictIndexes(partrelinfo); EvalPlanQualSetSlot(&epqstate, remoteslot_part); @@ -3181,8 +3186,6 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, get_namespace_name(RelationGetNamespace(partrel_new)), RelationGetRelationName(partrel_new)); - ExecOpenIndices(partrelinfo, false); - /* DELETE old tuple found in the old partition. */ EvalPlanQualSetSlot(&epqstate, localslot); TargetPrivilegesCheck(partrelinfo->ri_RelationDesc, ACL_DELETE); @@ -3217,7 +3220,6 @@ apply_handle_tuple_routing(ApplyExecutionData *edata, remoteslot_part); } - ExecCloseIndices(partrelinfo); EvalPlanQualEnd(&epqstate); } break; diff --git a/src/test/subscription/t/013_partition.pl b/src/test/subscription/t/013_partition.pl index 14a3beae6e46..c1f3ef781b98 100644 --- a/src/test/subscription/t/013_partition.pl +++ b/src/test/subscription/t/013_partition.pl @@ -49,6 +49,9 @@ $node_subscriber1->safe_psql('postgres', "CREATE TABLE tab1 (c text, a int PRIMARY KEY, b text) PARTITION BY LIST (a)" ); +$node_subscriber1->safe_psql('postgres', + "CREATE INDEX ON tab1 USING brin (c)" +); $node_subscriber1->safe_psql('postgres', "CREATE TABLE tab1_1 (b text, c text DEFAULT 'sub1_tab1', a int NOT NULL)" );