diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 18cf23296f..e3c1539a1e 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -367,21 +367,21 @@ aminsert (Relation indexRelation, within an SQL statement, it can allocate space in indexInfo->ii_Context and store a pointer to the data in indexInfo->ii_AmCache (which will be NULL - initially). After the index insertions complete, the memory will be freed - automatically. If additional cleanup is required (e.g. if the cache contains - buffers and tuple descriptors), the AM may define an optional function - aminsertcleanup, called before the memory is released. + initially). If resources other than memory have to be released after + index insertions, aminsertcleanup may be provided, + which will be called before the memory is released. void -aminsertcleanup (IndexInfo *indexInfo); +aminsertcleanup (Relation indexRelation, + IndexInfo *indexInfo); Clean up state that was maintained across successive inserts in indexInfo->ii_AmCache. This is useful if the data - requires additional cleanup steps, and simply releasing the memory is not - sufficient. + requires additional cleanup steps (e.g., releasing pinned buffers), and + simply releasing the memory is not sufficient. diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c index 4f708bba65..bf28400dd8 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -500,11 +500,13 @@ brininsert(Relation idxRel, Datum *values, bool *nulls, * Callback to clean up the BrinInsertState once all tuple inserts are done. */ void -brininsertcleanup(IndexInfo *indexInfo) +brininsertcleanup(Relation index, IndexInfo *indexInfo) { BrinInsertState *bistate = (BrinInsertState *) indexInfo->ii_AmCache; - Assert(bistate); + /* bail out if cache not initialized */ + if (indexInfo->ii_AmCache == NULL) + return; /* * Clean up the revmap. Note that the brinDesc has already been cleaned up diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index 7510159fc8..dcd04b813d 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -242,10 +242,9 @@ index_insert_cleanup(Relation indexRelation, IndexInfo *indexInfo) { RELATION_CHECKS; - Assert(indexInfo); - if (indexRelation->rd_indam->aminsertcleanup && indexInfo->ii_AmCache) - indexRelation->rd_indam->aminsertcleanup(indexInfo); + if (indexRelation->rd_indam->aminsertcleanup) + indexRelation->rd_indam->aminsertcleanup(indexRelation, indexInfo); } /* diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 9b7ef71d6f..5a8568c55c 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3402,6 +3402,9 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot) /* Done with tuplesort object */ tuplesort_end(state.tuplesort); + /* Make sure to release resources cached in indexInfo (if needed). */ + index_insert_cleanup(indexRelation, indexInfo); + elog(DEBUG2, "validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples", state.htups, state.itups, state.tups_inserted); diff --git a/src/backend/commands/constraint.c b/src/backend/commands/constraint.c index 94d491b754..f7dc42f745 100644 --- a/src/backend/commands/constraint.c +++ b/src/backend/commands/constraint.c @@ -174,6 +174,9 @@ unique_key_recheck(PG_FUNCTION_ARGS) index_insert(indexRel, values, isnull, &checktid, trigdata->tg_relation, UNIQUE_CHECK_EXISTING, false, indexInfo); + + /* Cleanup cache possibly initialized by index_insert. */ + index_insert_cleanup(indexRel, indexInfo); } else { diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h index 00300dd720..f25c9d58a7 100644 --- a/src/include/access/amapi.h +++ b/src/include/access/amapi.h @@ -114,7 +114,8 @@ typedef bool (*aminsert_function) (Relation indexRelation, struct IndexInfo *indexInfo); /* cleanup after insert */ -typedef void (*aminsertcleanup_function) (struct IndexInfo *indexInfo); +typedef void (*aminsertcleanup_function) (Relation indexRelation, + struct IndexInfo *indexInfo); /* bulk delete */ typedef IndexBulkDeleteResult *(*ambulkdelete_function) (IndexVacuumInfo *info, diff --git a/src/include/access/brin_internal.h b/src/include/access/brin_internal.h index 1c7eabe604..a5a9772621 100644 --- a/src/include/access/brin_internal.h +++ b/src/include/access/brin_internal.h @@ -96,7 +96,7 @@ extern bool brininsert(Relation idxRel, Datum *values, bool *nulls, IndexUniqueCheck checkUnique, bool indexUnchanged, struct IndexInfo *indexInfo); -extern void brininsertcleanup(struct IndexInfo *indexInfo); +extern void brininsertcleanup(Relation index, struct IndexInfo *indexInfo); extern IndexScanDesc brinbeginscan(Relation r, int nkeys, int norderbys); extern int64 bringetbitmap(IndexScanDesc scan, TIDBitmap *tbm); extern void brinrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, diff --git a/src/test/regress/expected/brin.out b/src/test/regress/expected/brin.out index 2662bb6ed4..d6779d8c7d 100644 --- a/src/test/regress/expected/brin.out +++ b/src/test/regress/expected/brin.out @@ -575,6 +575,7 @@ DROP TABLE brintest_unlogged; -- test that the insert optimization works if no rows end up inserted CREATE TABLE brin_insert_optimization (a int); INSERT INTO brin_insert_optimization VALUES (1); -CREATE INDEX ON brin_insert_optimization USING brin (a); +CREATE INDEX brin_insert_optimization_idx ON brin_insert_optimization USING brin (a); UPDATE brin_insert_optimization SET a = a; +REINDEX INDEX CONCURRENTLY brin_insert_optimization_idx; DROP TABLE brin_insert_optimization; diff --git a/src/test/regress/sql/brin.sql b/src/test/regress/sql/brin.sql index 0d3beabb3d..695cfad4be 100644 --- a/src/test/regress/sql/brin.sql +++ b/src/test/regress/sql/brin.sql @@ -519,6 +519,7 @@ DROP TABLE brintest_unlogged; -- test that the insert optimization works if no rows end up inserted CREATE TABLE brin_insert_optimization (a int); INSERT INTO brin_insert_optimization VALUES (1); -CREATE INDEX ON brin_insert_optimization USING brin (a); +CREATE INDEX brin_insert_optimization_idx ON brin_insert_optimization USING brin (a); UPDATE brin_insert_optimization SET a = a; +REINDEX INDEX CONCURRENTLY brin_insert_optimization_idx; DROP TABLE brin_insert_optimization;