mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Clean up API for ambulkdelete/amvacuumcleanup as per today's discussion.
This formulation requires every AM to provide amvacuumcleanup, unlike before, but it's surely a whole lot cleaner. Also, add an 'amstorage' column to pg_am so that we can get rid of hardwired knowledge in DefineOpClass().
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.1 2006/05/02 11:28:54 teodor Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.2 2006/05/02 22:25:10 tgl Exp $
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -474,17 +474,25 @@ ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint3
|
||||
|
||||
Datum
|
||||
ginbulkdelete(PG_FUNCTION_ARGS) {
|
||||
Relation index = (Relation) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
|
||||
void *callback_state = (void *) PG_GETARG_POINTER(2);
|
||||
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
|
||||
void *callback_state = (void *) PG_GETARG_POINTER(3);
|
||||
Relation index = info->index;
|
||||
BlockNumber blkno = GIN_ROOT_BLKNO;
|
||||
GinVacuumState gvs;
|
||||
Buffer buffer;
|
||||
BlockNumber rootOfPostingTree[ BLCKSZ/ (sizeof(IndexTupleData)+sizeof(ItemId)) ];
|
||||
uint32 nRoot;
|
||||
|
||||
/* first time through? */
|
||||
if (stats == NULL)
|
||||
stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||
/* we'll re-count the tuples each time */
|
||||
stats->num_index_tuples = 0;
|
||||
|
||||
gvs.index = index;
|
||||
gvs.result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||
gvs.result = stats;
|
||||
gvs.callback = callback;
|
||||
gvs.callback_state = callback_state;
|
||||
initGinState(&gvs.ginstate, index);
|
||||
@@ -564,9 +572,9 @@ ginbulkdelete(PG_FUNCTION_ARGS) {
|
||||
|
||||
Datum
|
||||
ginvacuumcleanup(PG_FUNCTION_ARGS) {
|
||||
Relation index = (Relation) PG_GETARG_POINTER(0);
|
||||
IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
|
||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);
|
||||
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||
Relation index = info->index;
|
||||
bool needLock = !RELATION_IS_LOCAL(index);
|
||||
BlockNumber npages,
|
||||
blkno;
|
||||
@@ -576,6 +584,15 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) {
|
||||
BlockNumber lastBlock = GIN_ROOT_BLKNO,
|
||||
lastFilledBlock = GIN_ROOT_BLKNO;
|
||||
|
||||
/* Set up all-zero stats if ginbulkdelete wasn't called */
|
||||
if (stats == NULL)
|
||||
stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||
/*
|
||||
* XXX we always report the heap tuple count as the number of index
|
||||
* entries. This is bogus if the index is partial, but it's real hard
|
||||
* to tell how many distinct heap entries are referenced by a GIN index.
|
||||
*/
|
||||
stats->num_index_tuples = info->num_heap_tuples;
|
||||
|
||||
if (info->vacuum_full) {
|
||||
LockRelation(index, AccessExclusiveLock);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.18 2006/03/31 23:32:05 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.19 2006/05/02 22:25:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -343,9 +343,9 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
|
||||
Datum
|
||||
gistvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
||||
IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
|
||||
GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(2);
|
||||
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||
GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||
Relation rel = info->index;
|
||||
BlockNumber npages,
|
||||
blkno;
|
||||
BlockNumber nFreePages,
|
||||
@@ -355,6 +355,19 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
lastFilledBlock = GIST_ROOT_BLKNO;
|
||||
bool needLock;
|
||||
|
||||
/* Set up all-zero stats if gistbulkdelete wasn't called */
|
||||
if (stats == NULL)
|
||||
{
|
||||
stats = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
|
||||
/* use heap's tuple count */
|
||||
Assert(info->num_heap_tuples >= 0);
|
||||
stats->std.num_index_tuples = info->num_heap_tuples;
|
||||
/*
|
||||
* XXX the above is wrong if index is partial. Would it be OK to
|
||||
* just return NULL, or is there work we must do below?
|
||||
*/
|
||||
}
|
||||
|
||||
/* gistVacuumUpdate may cause hard work */
|
||||
if (info->vacuum_full)
|
||||
{
|
||||
@@ -460,13 +473,6 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
if (info->vacuum_full)
|
||||
UnlockRelation(rel, AccessExclusiveLock);
|
||||
|
||||
/* if gistbulkdelete skipped the scan, use heap's tuple count */
|
||||
if (stats->std.num_index_tuples < 0)
|
||||
{
|
||||
Assert(info->num_heap_tuples >= 0);
|
||||
stats->std.num_index_tuples = info->num_heap_tuples;
|
||||
}
|
||||
|
||||
PG_RETURN_POINTER(stats);
|
||||
}
|
||||
|
||||
@@ -509,36 +515,22 @@ pushStackIfSplited(Page page, GistBDItem *stack)
|
||||
Datum
|
||||
gistbulkdelete(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
|
||||
void *callback_state = (void *) PG_GETARG_POINTER(2);
|
||||
GistBulkDeleteResult *result;
|
||||
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||
GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
|
||||
void *callback_state = (void *) PG_GETARG_POINTER(3);
|
||||
Relation rel = info->index;
|
||||
GistBDItem *stack,
|
||||
*ptr;
|
||||
bool needLock;
|
||||
|
||||
result = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
|
||||
/* first time through? */
|
||||
if (stats == NULL)
|
||||
stats = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
|
||||
/* we'll re-count the tuples each time */
|
||||
stats->std.num_index_tuples = 0;
|
||||
|
||||
/*
|
||||
* We can skip the scan entirely if there's nothing to delete (indicated
|
||||
* by callback_state == NULL) and the index isn't partial. For a partial
|
||||
* index we must scan in order to derive a trustworthy tuple count.
|
||||
*
|
||||
* XXX as of PG 8.2 this is dead code because GIST indexes are always
|
||||
* effectively partial ... but keep it anyway in case our null-handling
|
||||
* gets fixed.
|
||||
*/
|
||||
if (callback_state || vac_is_partial_index(rel))
|
||||
{
|
||||
stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
|
||||
stack->blkno = GIST_ROOT_BLKNO;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip scan and set flag for gistvacuumcleanup */
|
||||
stack = NULL;
|
||||
result->std.num_index_tuples = -1;
|
||||
}
|
||||
stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
|
||||
stack->blkno = GIST_ROOT_BLKNO;
|
||||
|
||||
while (stack)
|
||||
{
|
||||
@@ -601,11 +593,11 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
||||
i--;
|
||||
maxoff--;
|
||||
ntodelete++;
|
||||
result->std.tuples_removed += 1;
|
||||
stats->std.tuples_removed += 1;
|
||||
Assert(maxoff == PageGetMaxOffsetNumber(page));
|
||||
}
|
||||
else
|
||||
result->std.num_index_tuples += 1;
|
||||
stats->std.num_index_tuples += 1;
|
||||
}
|
||||
|
||||
if (ntodelete)
|
||||
@@ -658,7 +650,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
||||
stack->next = ptr;
|
||||
|
||||
if (GistTupleIsInvalid(idxtuple))
|
||||
result->needFullVacuum = true;
|
||||
stats->needFullVacuum = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,13 +663,5 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
||||
vacuum_delay_point();
|
||||
}
|
||||
|
||||
needLock = !RELATION_IS_LOCAL(rel);
|
||||
|
||||
if (needLock)
|
||||
LockRelationForExtension(rel, ExclusiveLock);
|
||||
result->std.num_pages = RelationGetNumberOfBlocks(rel);
|
||||
if (needLock)
|
||||
UnlockRelationForExtension(rel, ExclusiveLock);
|
||||
|
||||
PG_RETURN_POINTER(result);
|
||||
PG_RETURN_POINTER(stats);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.88 2006/03/24 04:32:12 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.89 2006/05/02 22:25:10 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* This file contains only the public interface routines.
|
||||
@@ -478,11 +478,11 @@ hashrestrpos(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
hashbulkdelete(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
|
||||
void *callback_state = (void *) PG_GETARG_POINTER(2);
|
||||
IndexBulkDeleteResult *result;
|
||||
BlockNumber num_pages;
|
||||
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
|
||||
void *callback_state = (void *) PG_GETARG_POINTER(3);
|
||||
Relation rel = info->index;
|
||||
double tuples_removed;
|
||||
double num_index_tuples;
|
||||
double orig_ntuples;
|
||||
@@ -517,18 +517,6 @@ hashbulkdelete(PG_FUNCTION_ARGS)
|
||||
cur_maxbucket = orig_maxbucket;
|
||||
|
||||
loop_top:
|
||||
|
||||
/*
|
||||
* If we don't have anything to delete, skip the scan, and report the
|
||||
* number of tuples shown in the metapage. (Unlike btree and gist,
|
||||
* we can trust this number even for a partial index.)
|
||||
*/
|
||||
if (!callback_state)
|
||||
{
|
||||
cur_bucket = cur_maxbucket + 1;
|
||||
num_index_tuples = local_metapage.hashm_ntuples;
|
||||
}
|
||||
|
||||
while (cur_bucket <= cur_maxbucket)
|
||||
{
|
||||
BlockNumber bucket_blkno;
|
||||
@@ -657,14 +645,37 @@ loop_top:
|
||||
_hash_wrtbuf(rel, metabuf);
|
||||
|
||||
/* return statistics */
|
||||
if (stats == NULL)
|
||||
stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||
stats->num_index_tuples = num_index_tuples;
|
||||
stats->tuples_removed += tuples_removed;
|
||||
/* hashvacuumcleanup will fill in num_pages */
|
||||
|
||||
PG_RETURN_POINTER(stats);
|
||||
}
|
||||
|
||||
/*
|
||||
* Post-VACUUM cleanup.
|
||||
*
|
||||
* Result: a palloc'd struct containing statistical info for VACUUM displays.
|
||||
*/
|
||||
Datum
|
||||
hashvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
{
|
||||
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||
Relation rel = info->index;
|
||||
BlockNumber num_pages;
|
||||
|
||||
/* If hashbulkdelete wasn't called, return NULL signifying no change */
|
||||
if (stats == NULL)
|
||||
PG_RETURN_POINTER(NULL);
|
||||
|
||||
/* update statistics */
|
||||
num_pages = RelationGetNumberOfBlocks(rel);
|
||||
stats->num_pages = num_pages;
|
||||
|
||||
result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||
result->num_pages = num_pages;
|
||||
result->num_index_tuples = num_index_tuples;
|
||||
result->tuples_removed = tuples_removed;
|
||||
|
||||
PG_RETURN_POINTER(result);
|
||||
PG_RETURN_POINTER(stats);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.91 2006/03/05 15:58:21 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.92 2006/05/02 22:25:10 tgl Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* index_open - open an index relation by relation OID
|
||||
@@ -684,19 +684,17 @@ index_getmulti(IndexScanDesc scan,
|
||||
*
|
||||
* callback routine tells whether a given main-heap tuple is
|
||||
* to be deleted
|
||||
*
|
||||
* if callback_state is NULL then there are no tuples to be deleted;
|
||||
* index AM can choose to avoid work in this case, but must still
|
||||
* follow the protocol of returning statistical info.
|
||||
*
|
||||
* return value is an optional palloc'd struct of statistics
|
||||
* ----------------
|
||||
*/
|
||||
IndexBulkDeleteResult *
|
||||
index_bulk_delete(Relation indexRelation,
|
||||
index_bulk_delete(IndexVacuumInfo *info,
|
||||
IndexBulkDeleteResult *stats,
|
||||
IndexBulkDeleteCallback callback,
|
||||
void *callback_state)
|
||||
{
|
||||
Relation indexRelation = info->index;
|
||||
FmgrInfo *procedure;
|
||||
IndexBulkDeleteResult *result;
|
||||
|
||||
@@ -704,8 +702,9 @@ index_bulk_delete(Relation indexRelation,
|
||||
GET_REL_PROCEDURE(ambulkdelete);
|
||||
|
||||
result = (IndexBulkDeleteResult *)
|
||||
DatumGetPointer(FunctionCall3(procedure,
|
||||
PointerGetDatum(indexRelation),
|
||||
DatumGetPointer(FunctionCall4(procedure,
|
||||
PointerGetDatum(info),
|
||||
PointerGetDatum(stats),
|
||||
PointerGetDatum((Pointer) callback),
|
||||
PointerGetDatum(callback_state)));
|
||||
|
||||
@@ -719,26 +718,20 @@ index_bulk_delete(Relation indexRelation,
|
||||
* ----------------
|
||||
*/
|
||||
IndexBulkDeleteResult *
|
||||
index_vacuum_cleanup(Relation indexRelation,
|
||||
IndexVacuumCleanupInfo *info,
|
||||
index_vacuum_cleanup(IndexVacuumInfo *info,
|
||||
IndexBulkDeleteResult *stats)
|
||||
{
|
||||
Relation indexRelation = info->index;
|
||||
FmgrInfo *procedure;
|
||||
IndexBulkDeleteResult *result;
|
||||
|
||||
RELATION_CHECKS;
|
||||
|
||||
/* It's okay for an index AM not to have a vacuumcleanup procedure */
|
||||
if (!RegProcedureIsValid(indexRelation->rd_am->amvacuumcleanup))
|
||||
return stats;
|
||||
|
||||
GET_REL_PROCEDURE(amvacuumcleanup);
|
||||
|
||||
result = (IndexBulkDeleteResult *)
|
||||
DatumGetPointer(FunctionCall3(procedure,
|
||||
PointerGetDatum(indexRelation),
|
||||
PointerGetDatum((Pointer) info),
|
||||
PointerGetDatum((Pointer) stats)));
|
||||
DatumGetPointer(FunctionCall2(procedure,
|
||||
PointerGetDatum(info),
|
||||
PointerGetDatum(stats)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.145 2006/04/25 22:46:05 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.146 2006/05/02 22:25:10 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -518,15 +518,15 @@ btrestrpos(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
btbulkdelete(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
|
||||
void *callback_state = (void *) PG_GETARG_POINTER(2);
|
||||
IndexBulkDeleteResult *result;
|
||||
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
|
||||
void *callback_state = (void *) PG_GETARG_POINTER(3);
|
||||
Relation rel = info->index;
|
||||
double tuples_removed = 0;
|
||||
OffsetNumber deletable[MaxOffsetNumber];
|
||||
int ndeletable;
|
||||
Buffer buf;
|
||||
BlockNumber num_pages;
|
||||
|
||||
/*
|
||||
* The outer loop iterates over index leaf pages, the inner over items on
|
||||
@@ -543,14 +543,8 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
* further to its right, which the indexscan will have no pin on.) We can
|
||||
* skip obtaining exclusive lock on empty pages though, since no indexscan
|
||||
* could be stopped on those.
|
||||
*
|
||||
* We can skip the scan entirely if there's nothing to delete (indicated
|
||||
* by callback_state == NULL).
|
||||
*/
|
||||
if (callback_state)
|
||||
buf = _bt_get_endpoint(rel, 0, false);
|
||||
else
|
||||
buf = InvalidBuffer;
|
||||
buf = _bt_get_endpoint(rel, 0, false);
|
||||
|
||||
if (BufferIsValid(buf)) /* check for empty index */
|
||||
{
|
||||
@@ -626,14 +620,12 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/* return statistics */
|
||||
num_pages = RelationGetNumberOfBlocks(rel);
|
||||
if (stats == NULL)
|
||||
stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||
stats->tuples_removed += tuples_removed;
|
||||
/* btvacuumcleanup will fill in num_pages and num_index_tuples */
|
||||
|
||||
result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||
result->num_pages = num_pages;
|
||||
/* btvacuumcleanup will fill in num_index_tuples */
|
||||
result->tuples_removed = tuples_removed;
|
||||
|
||||
PG_RETURN_POINTER(result);
|
||||
PG_RETURN_POINTER(stats);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -646,9 +638,9 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
||||
IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
|
||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);
|
||||
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||
Relation rel = info->index;
|
||||
BlockNumber num_pages;
|
||||
BlockNumber blkno;
|
||||
BlockNumber *freePages;
|
||||
@@ -660,7 +652,9 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||
MemoryContext oldcontext;
|
||||
bool needLock;
|
||||
|
||||
Assert(stats != NULL);
|
||||
/* Set up all-zero stats if btbulkdelete wasn't called */
|
||||
if (stats == NULL)
|
||||
stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||
|
||||
/*
|
||||
* First find out the number of pages in the index. We must acquire the
|
||||
|
||||
Reference in New Issue
Block a user