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:
parent
d3171dd64b
commit
e57345975c
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.121 2006/03/10 19:10:46 momjian Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.122 2006/05/02 22:25:09 tgl Exp $ -->
|
||||||
<!--
|
<!--
|
||||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
Documentation of the system catalogs, directed toward PostgreSQL developers
|
||||||
-->
|
-->
|
||||||
@ -394,6 +394,13 @@
|
|||||||
<entry>Does the access method support null index entries?</entry>
|
<entry>Does the access method support null index entries?</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><structfield>amstorage</structfield></entry>
|
||||||
|
<entry><type>bool</type></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>Can index storage data type differ from column data type?</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry><structfield>amconcurrent</structfield></entry>
|
<entry><structfield>amconcurrent</structfield></entry>
|
||||||
<entry><type>bool</type></entry>
|
<entry><type>bool</type></entry>
|
||||||
@ -401,6 +408,13 @@
|
|||||||
<entry>Does the access method support concurrent updates?</entry>
|
<entry>Does the access method support concurrent updates?</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><structfield>amclusterable</structfield></entry>
|
||||||
|
<entry><type>bool</type></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>Can an index of this type be CLUSTERed on?</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry><structfield>aminsert</structfield></entry>
|
<entry><structfield>aminsert</structfield></entry>
|
||||||
<entry><type>regproc</type></entry>
|
<entry><type>regproc</type></entry>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.9 2006/03/10 19:10:48 momjian Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.10 2006/05/02 22:25:09 tgl Exp $ -->
|
||||||
|
|
||||||
<chapter id="indexam">
|
<chapter id="indexam">
|
||||||
<title>Index Access Method Interface Definition</title>
|
<title>Index Access Method Interface Definition</title>
|
||||||
@ -184,44 +184,52 @@ aminsert (Relation indexRelation,
|
|||||||
<para>
|
<para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
IndexBulkDeleteResult *
|
IndexBulkDeleteResult *
|
||||||
ambulkdelete (Relation indexRelation,
|
ambulkdelete (IndexVacuumInfo *info,
|
||||||
|
IndexBulkDeleteResult *stats,
|
||||||
IndexBulkDeleteCallback callback,
|
IndexBulkDeleteCallback callback,
|
||||||
void *callback_state);
|
void *callback_state);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
Delete tuple(s) from the index. This is a <quote>bulk delete</> operation
|
Delete tuple(s) from the index. This is a <quote>bulk delete</> operation
|
||||||
that is intended to be implemented by scanning the whole index and checking
|
that is intended to be implemented by scanning the whole index and checking
|
||||||
each entry to see if it should be deleted.
|
each entry to see if it should be deleted.
|
||||||
The passed-in <literal>callback</> function may be called, in the style
|
The passed-in <literal>callback</> function must be called, in the style
|
||||||
<literal>callback(<replaceable>TID</>, callback_state) returns bool</literal>,
|
<literal>callback(<replaceable>TID</>, callback_state) returns bool</literal>,
|
||||||
to determine whether any particular index entry, as identified by its
|
to determine whether any particular index entry, as identified by its
|
||||||
referenced TID, is to be deleted. Must return either NULL or a palloc'd
|
referenced TID, is to be deleted. Must return either NULL or a palloc'd
|
||||||
struct containing statistics about the effects of the deletion operation.
|
struct containing statistics about the effects of the deletion operation.
|
||||||
|
It is OK to return NULL if no information needs to be passed on to
|
||||||
|
<function>amvacuumcleanup</>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If <literal>callback_state</> is NULL then no tuples are to be deleted.
|
Because of limited <varname>maintenance_work_mem</>,
|
||||||
The index AM may choose to optimize this case (eg by not scanning the
|
<function>ambulkdelete</> may need to be called more than once when many
|
||||||
index) but it is still expected to deliver accurate statistics.
|
tuples are to be deleted. The <literal>stats</> argument is the result
|
||||||
|
of the previous call for this index (it is NULL for the first call within a
|
||||||
|
<command>VACUUM</> operation). This allows the AM to accumulate statistics
|
||||||
|
across the whole operation. Typically, <function>ambulkdelete</> will
|
||||||
|
modify and return the same struct if the passed <literal>stats</> is not
|
||||||
|
null.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
IndexBulkDeleteResult *
|
IndexBulkDeleteResult *
|
||||||
amvacuumcleanup (Relation indexRelation,
|
amvacuumcleanup (IndexVacuumInfo *info,
|
||||||
IndexVacuumCleanupInfo *info,
|
|
||||||
IndexBulkDeleteResult *stats);
|
IndexBulkDeleteResult *stats);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
Clean up after a <command>VACUUM</command> operation (one or more
|
Clean up after a <command>VACUUM</command> operation (zero or more
|
||||||
<function>ambulkdelete</> calls). An index access method does not have
|
<function>ambulkdelete</> calls). This does not have to do anything
|
||||||
to provide this function (if so, the entry in <structname>pg_am</> must
|
beyond returning index statistics, but it may perform bulk cleanup
|
||||||
be zero). If it is provided, it is typically used for bulk cleanup
|
such as reclaiming empty index pages. <literal>stats</> is whatever the
|
||||||
such as reclaiming empty index pages. <literal>info</>
|
last <function>ambulkdelete</> call returned, or NULL if
|
||||||
provides some additional arguments such as a message level for statistical
|
<function>ambulkdelete</> was not called because no tuples needed to be
|
||||||
reports, and <literal>stats</> is whatever the last
|
deleted. If the result is not NULL it must be a palloc'd struct.
|
||||||
<function>ambulkdelete</> call returned. <function>amvacuumcleanup</>
|
The statistics it contains will be used to update <structname>pg_class</>,
|
||||||
may replace or modify this struct before returning it. If the result
|
and will be reported by <command>VACUUM</> if <literal>VERBOSE</> is given.
|
||||||
is not NULL it must be a palloc'd struct. The statistics it contains
|
It is OK to return NULL if the index was not changed at all during the
|
||||||
will be reported by <command>VACUUM</> if <literal>VERBOSE</> is given.
|
<command>VACUUM</command> operation, but otherwise correct stats should
|
||||||
|
be returned.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
Datum
|
||||||
ginbulkdelete(PG_FUNCTION_ARGS) {
|
ginbulkdelete(PG_FUNCTION_ARGS) {
|
||||||
Relation index = (Relation) PG_GETARG_POINTER(0);
|
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
|
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||||
void *callback_state = (void *) PG_GETARG_POINTER(2);
|
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
|
||||||
|
void *callback_state = (void *) PG_GETARG_POINTER(3);
|
||||||
|
Relation index = info->index;
|
||||||
BlockNumber blkno = GIN_ROOT_BLKNO;
|
BlockNumber blkno = GIN_ROOT_BLKNO;
|
||||||
GinVacuumState gvs;
|
GinVacuumState gvs;
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
BlockNumber rootOfPostingTree[ BLCKSZ/ (sizeof(IndexTupleData)+sizeof(ItemId)) ];
|
BlockNumber rootOfPostingTree[ BLCKSZ/ (sizeof(IndexTupleData)+sizeof(ItemId)) ];
|
||||||
uint32 nRoot;
|
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.index = index;
|
||||||
gvs.result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
gvs.result = stats;
|
||||||
gvs.callback = callback;
|
gvs.callback = callback;
|
||||||
gvs.callback_state = callback_state;
|
gvs.callback_state = callback_state;
|
||||||
initGinState(&gvs.ginstate, index);
|
initGinState(&gvs.ginstate, index);
|
||||||
@ -564,9 +572,9 @@ ginbulkdelete(PG_FUNCTION_ARGS) {
|
|||||||
|
|
||||||
Datum
|
Datum
|
||||||
ginvacuumcleanup(PG_FUNCTION_ARGS) {
|
ginvacuumcleanup(PG_FUNCTION_ARGS) {
|
||||||
Relation index = (Relation) PG_GETARG_POINTER(0);
|
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||||
IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
|
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);
|
Relation index = info->index;
|
||||||
bool needLock = !RELATION_IS_LOCAL(index);
|
bool needLock = !RELATION_IS_LOCAL(index);
|
||||||
BlockNumber npages,
|
BlockNumber npages,
|
||||||
blkno;
|
blkno;
|
||||||
@ -576,6 +584,15 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) {
|
|||||||
BlockNumber lastBlock = GIN_ROOT_BLKNO,
|
BlockNumber lastBlock = GIN_ROOT_BLKNO,
|
||||||
lastFilledBlock = 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) {
|
if (info->vacuum_full) {
|
||||||
LockRelation(index, AccessExclusiveLock);
|
LockRelation(index, AccessExclusiveLock);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
Datum
|
||||||
gistvacuumcleanup(PG_FUNCTION_ARGS)
|
gistvacuumcleanup(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||||
IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
|
GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||||
GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(2);
|
Relation rel = info->index;
|
||||||
BlockNumber npages,
|
BlockNumber npages,
|
||||||
blkno;
|
blkno;
|
||||||
BlockNumber nFreePages,
|
BlockNumber nFreePages,
|
||||||
@ -355,6 +355,19 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
lastFilledBlock = GIST_ROOT_BLKNO;
|
lastFilledBlock = GIST_ROOT_BLKNO;
|
||||||
bool needLock;
|
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 */
|
/* gistVacuumUpdate may cause hard work */
|
||||||
if (info->vacuum_full)
|
if (info->vacuum_full)
|
||||||
{
|
{
|
||||||
@ -460,13 +473,6 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
if (info->vacuum_full)
|
if (info->vacuum_full)
|
||||||
UnlockRelation(rel, AccessExclusiveLock);
|
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);
|
PG_RETURN_POINTER(stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,36 +515,22 @@ pushStackIfSplited(Page page, GistBDItem *stack)
|
|||||||
Datum
|
Datum
|
||||||
gistbulkdelete(PG_FUNCTION_ARGS)
|
gistbulkdelete(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
|
GistBulkDeleteResult *stats = (GistBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||||
void *callback_state = (void *) PG_GETARG_POINTER(2);
|
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
|
||||||
GistBulkDeleteResult *result;
|
void *callback_state = (void *) PG_GETARG_POINTER(3);
|
||||||
|
Relation rel = info->index;
|
||||||
GistBDItem *stack,
|
GistBDItem *stack,
|
||||||
*ptr;
|
*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;
|
||||||
|
|
||||||
/*
|
stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
|
||||||
* We can skip the scan entirely if there's nothing to delete (indicated
|
stack->blkno = GIST_ROOT_BLKNO;
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (stack)
|
while (stack)
|
||||||
{
|
{
|
||||||
@ -601,11 +593,11 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
i--;
|
i--;
|
||||||
maxoff--;
|
maxoff--;
|
||||||
ntodelete++;
|
ntodelete++;
|
||||||
result->std.tuples_removed += 1;
|
stats->std.tuples_removed += 1;
|
||||||
Assert(maxoff == PageGetMaxOffsetNumber(page));
|
Assert(maxoff == PageGetMaxOffsetNumber(page));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result->std.num_index_tuples += 1;
|
stats->std.num_index_tuples += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntodelete)
|
if (ntodelete)
|
||||||
@ -658,7 +650,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
stack->next = ptr;
|
stack->next = ptr;
|
||||||
|
|
||||||
if (GistTupleIsInvalid(idxtuple))
|
if (GistTupleIsInvalid(idxtuple))
|
||||||
result->needFullVacuum = true;
|
stats->needFullVacuum = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -671,13 +663,5 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
vacuum_delay_point();
|
vacuum_delay_point();
|
||||||
}
|
}
|
||||||
|
|
||||||
needLock = !RELATION_IS_LOCAL(rel);
|
PG_RETURN_POINTER(stats);
|
||||||
|
|
||||||
if (needLock)
|
|
||||||
LockRelationForExtension(rel, ExclusiveLock);
|
|
||||||
result->std.num_pages = RelationGetNumberOfBlocks(rel);
|
|
||||||
if (needLock)
|
|
||||||
UnlockRelationForExtension(rel, ExclusiveLock);
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* This file contains only the public interface routines.
|
* This file contains only the public interface routines.
|
||||||
@ -478,11 +478,11 @@ hashrestrpos(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
hashbulkdelete(PG_FUNCTION_ARGS)
|
hashbulkdelete(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
|
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||||
void *callback_state = (void *) PG_GETARG_POINTER(2);
|
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
|
||||||
IndexBulkDeleteResult *result;
|
void *callback_state = (void *) PG_GETARG_POINTER(3);
|
||||||
BlockNumber num_pages;
|
Relation rel = info->index;
|
||||||
double tuples_removed;
|
double tuples_removed;
|
||||||
double num_index_tuples;
|
double num_index_tuples;
|
||||||
double orig_ntuples;
|
double orig_ntuples;
|
||||||
@ -517,18 +517,6 @@ hashbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
cur_maxbucket = orig_maxbucket;
|
cur_maxbucket = orig_maxbucket;
|
||||||
|
|
||||||
loop_top:
|
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)
|
while (cur_bucket <= cur_maxbucket)
|
||||||
{
|
{
|
||||||
BlockNumber bucket_blkno;
|
BlockNumber bucket_blkno;
|
||||||
@ -657,14 +645,37 @@ loop_top:
|
|||||||
_hash_wrtbuf(rel, metabuf);
|
_hash_wrtbuf(rel, metabuf);
|
||||||
|
|
||||||
/* return statistics */
|
/* 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);
|
num_pages = RelationGetNumberOfBlocks(rel);
|
||||||
|
stats->num_pages = num_pages;
|
||||||
|
|
||||||
result = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
PG_RETURN_POINTER(stats);
|
||||||
result->num_pages = num_pages;
|
|
||||||
result->num_index_tuples = num_index_tuples;
|
|
||||||
result->tuples_removed = tuples_removed;
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* INTERFACE ROUTINES
|
||||||
* index_open - open an index relation by relation OID
|
* 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
|
* callback routine tells whether a given main-heap tuple is
|
||||||
* to be deleted
|
* 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
|
* return value is an optional palloc'd struct of statistics
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
IndexBulkDeleteResult *
|
IndexBulkDeleteResult *
|
||||||
index_bulk_delete(Relation indexRelation,
|
index_bulk_delete(IndexVacuumInfo *info,
|
||||||
|
IndexBulkDeleteResult *stats,
|
||||||
IndexBulkDeleteCallback callback,
|
IndexBulkDeleteCallback callback,
|
||||||
void *callback_state)
|
void *callback_state)
|
||||||
{
|
{
|
||||||
|
Relation indexRelation = info->index;
|
||||||
FmgrInfo *procedure;
|
FmgrInfo *procedure;
|
||||||
IndexBulkDeleteResult *result;
|
IndexBulkDeleteResult *result;
|
||||||
|
|
||||||
@ -704,8 +702,9 @@ index_bulk_delete(Relation indexRelation,
|
|||||||
GET_REL_PROCEDURE(ambulkdelete);
|
GET_REL_PROCEDURE(ambulkdelete);
|
||||||
|
|
||||||
result = (IndexBulkDeleteResult *)
|
result = (IndexBulkDeleteResult *)
|
||||||
DatumGetPointer(FunctionCall3(procedure,
|
DatumGetPointer(FunctionCall4(procedure,
|
||||||
PointerGetDatum(indexRelation),
|
PointerGetDatum(info),
|
||||||
|
PointerGetDatum(stats),
|
||||||
PointerGetDatum((Pointer) callback),
|
PointerGetDatum((Pointer) callback),
|
||||||
PointerGetDatum(callback_state)));
|
PointerGetDatum(callback_state)));
|
||||||
|
|
||||||
@ -719,26 +718,20 @@ index_bulk_delete(Relation indexRelation,
|
|||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
IndexBulkDeleteResult *
|
IndexBulkDeleteResult *
|
||||||
index_vacuum_cleanup(Relation indexRelation,
|
index_vacuum_cleanup(IndexVacuumInfo *info,
|
||||||
IndexVacuumCleanupInfo *info,
|
|
||||||
IndexBulkDeleteResult *stats)
|
IndexBulkDeleteResult *stats)
|
||||||
{
|
{
|
||||||
|
Relation indexRelation = info->index;
|
||||||
FmgrInfo *procedure;
|
FmgrInfo *procedure;
|
||||||
IndexBulkDeleteResult *result;
|
IndexBulkDeleteResult *result;
|
||||||
|
|
||||||
RELATION_CHECKS;
|
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);
|
GET_REL_PROCEDURE(amvacuumcleanup);
|
||||||
|
|
||||||
result = (IndexBulkDeleteResult *)
|
result = (IndexBulkDeleteResult *)
|
||||||
DatumGetPointer(FunctionCall3(procedure,
|
DatumGetPointer(FunctionCall2(procedure,
|
||||||
PointerGetDatum(indexRelation),
|
PointerGetDatum(info),
|
||||||
PointerGetDatum((Pointer) info),
|
PointerGetDatum(stats)));
|
||||||
PointerGetDatum((Pointer) stats)));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
Datum
|
||||||
btbulkdelete(PG_FUNCTION_ARGS)
|
btbulkdelete(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||||
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(1);
|
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||||
void *callback_state = (void *) PG_GETARG_POINTER(2);
|
IndexBulkDeleteCallback callback = (IndexBulkDeleteCallback) PG_GETARG_POINTER(2);
|
||||||
IndexBulkDeleteResult *result;
|
void *callback_state = (void *) PG_GETARG_POINTER(3);
|
||||||
|
Relation rel = info->index;
|
||||||
double tuples_removed = 0;
|
double tuples_removed = 0;
|
||||||
OffsetNumber deletable[MaxOffsetNumber];
|
OffsetNumber deletable[MaxOffsetNumber];
|
||||||
int ndeletable;
|
int ndeletable;
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
BlockNumber num_pages;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The outer loop iterates over index leaf pages, the inner over items on
|
* 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
|
* 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
|
* skip obtaining exclusive lock on empty pages though, since no indexscan
|
||||||
* could be stopped on those.
|
* 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);
|
||||||
buf = _bt_get_endpoint(rel, 0, false);
|
|
||||||
else
|
|
||||||
buf = InvalidBuffer;
|
|
||||||
|
|
||||||
if (BufferIsValid(buf)) /* check for empty index */
|
if (BufferIsValid(buf)) /* check for empty index */
|
||||||
{
|
{
|
||||||
@ -626,14 +620,12 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* return statistics */
|
/* 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));
|
PG_RETURN_POINTER(stats);
|
||||||
result->num_pages = num_pages;
|
|
||||||
/* btvacuumcleanup will fill in num_index_tuples */
|
|
||||||
result->tuples_removed = tuples_removed;
|
|
||||||
|
|
||||||
PG_RETURN_POINTER(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -646,9 +638,9 @@ btbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
btvacuumcleanup(PG_FUNCTION_ARGS)
|
btvacuumcleanup(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Relation rel = (Relation) PG_GETARG_POINTER(0);
|
IndexVacuumInfo *info = (IndexVacuumInfo *) PG_GETARG_POINTER(0);
|
||||||
IndexVacuumCleanupInfo *info = (IndexVacuumCleanupInfo *) PG_GETARG_POINTER(1);
|
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(1);
|
||||||
IndexBulkDeleteResult *stats = (IndexBulkDeleteResult *) PG_GETARG_POINTER(2);
|
Relation rel = info->index;
|
||||||
BlockNumber num_pages;
|
BlockNumber num_pages;
|
||||||
BlockNumber blkno;
|
BlockNumber blkno;
|
||||||
BlockNumber *freePages;
|
BlockNumber *freePages;
|
||||||
@ -660,7 +652,9 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
bool needLock;
|
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
|
* First find out the number of pages in the index. We must acquire the
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.146 2006/05/02 15:45:37 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.147 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -339,6 +339,12 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck)
|
|||||||
errmsg("cannot cluster on partial index \"%s\"",
|
errmsg("cannot cluster on partial index \"%s\"",
|
||||||
RelationGetRelationName(OldIndex))));
|
RelationGetRelationName(OldIndex))));
|
||||||
|
|
||||||
|
if (!OldIndex->rd_am->amclusterable)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("cannot cluster on index \"%s\" because access method does not support clustering",
|
||||||
|
RelationGetRelationName(OldIndex))));
|
||||||
|
|
||||||
if (!OldIndex->rd_am->amindexnulls)
|
if (!OldIndex->rd_am->amindexnulls)
|
||||||
{
|
{
|
||||||
AttrNumber colno;
|
AttrNumber colno;
|
||||||
@ -376,12 +382,6 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck)
|
|||||||
RelationGetRelationName(OldIndex))));
|
RelationGetRelationName(OldIndex))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OldIndex->rd_am->amclusterable)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
|
||||||
errmsg("cannot cluster on index \"%s\" because access method does not support clustering",
|
|
||||||
RelationGetRelationName(OldIndex))));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disallow clustering system relations. This will definitely NOT work
|
* Disallow clustering system relations. This will definitely NOT work
|
||||||
* for shared relations (we have no way to update pg_class rows in other
|
* for shared relations (we have no way to update pg_class rows in other
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.44 2006/05/02 11:28:54 teodor Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/opclasscmds.c,v 1.45 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -77,11 +77,13 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
|||||||
opclassoid; /* oid of opclass we create */
|
opclassoid; /* oid of opclass we create */
|
||||||
int numOperators, /* amstrategies value */
|
int numOperators, /* amstrategies value */
|
||||||
numProcs; /* amsupport value */
|
numProcs; /* amsupport value */
|
||||||
|
bool amstorage; /* amstorage flag */
|
||||||
List *operators; /* OpClassMember list for operators */
|
List *operators; /* OpClassMember list for operators */
|
||||||
List *procedures; /* OpClassMember list for support procs */
|
List *procedures; /* OpClassMember list for support procs */
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
|
Form_pg_am pg_am;
|
||||||
Datum values[Natts_pg_opclass];
|
Datum values[Natts_pg_opclass];
|
||||||
char nulls[Natts_pg_opclass];
|
char nulls[Natts_pg_opclass];
|
||||||
AclResult aclresult;
|
AclResult aclresult;
|
||||||
@ -111,8 +113,10 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
|||||||
stmt->amname)));
|
stmt->amname)));
|
||||||
|
|
||||||
amoid = HeapTupleGetOid(tup);
|
amoid = HeapTupleGetOid(tup);
|
||||||
numOperators = ((Form_pg_am) GETSTRUCT(tup))->amstrategies;
|
pg_am = (Form_pg_am) GETSTRUCT(tup);
|
||||||
numProcs = ((Form_pg_am) GETSTRUCT(tup))->amsupport;
|
numOperators = pg_am->amstrategies;
|
||||||
|
numProcs = pg_am->amsupport;
|
||||||
|
amstorage = pg_am->amstorage;
|
||||||
|
|
||||||
/* XXX Should we make any privilege check against the AM? */
|
/* XXX Should we make any privilege check against the AM? */
|
||||||
|
|
||||||
@ -270,19 +274,11 @@ DefineOpClass(CreateOpClassStmt *stmt)
|
|||||||
/* Just drop the spec if same as column datatype */
|
/* Just drop the spec if same as column datatype */
|
||||||
if (storageoid == typeoid)
|
if (storageoid == typeoid)
|
||||||
storageoid = InvalidOid;
|
storageoid = InvalidOid;
|
||||||
else
|
else if (!amstorage)
|
||||||
{
|
ereport(ERROR,
|
||||||
/*
|
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||||
* Currently, only GiST and GIN allows storagetype different from
|
errmsg("storage type may not be different from data type for access method \"%s\"",
|
||||||
* datatype. This hardcoded test should be eliminated in favor of
|
stmt->amname)));
|
||||||
* adding another boolean column to pg_am ...
|
|
||||||
*/
|
|
||||||
if (!(amoid == GIST_AM_OID || amoid == GIN_AM_OID))
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
||||||
errmsg("storage type may not be different from data type for access method \"%s\"",
|
|
||||||
stmt->amname)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
|
rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.327 2006/05/02 11:28:54 teodor Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.328 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -230,7 +230,6 @@ static void vacuum_index(VacPageList vacpagelist, Relation indrel,
|
|||||||
double num_tuples, int keep_tuples);
|
double num_tuples, int keep_tuples);
|
||||||
static void scan_index(Relation indrel, double num_tuples);
|
static void scan_index(Relation indrel, double num_tuples);
|
||||||
static bool tid_reaped(ItemPointer itemptr, void *state);
|
static bool tid_reaped(ItemPointer itemptr, void *state);
|
||||||
static bool dummy_tid_reaped(ItemPointer itemptr, void *state);
|
|
||||||
static void vac_update_fsm(Relation onerel, VacPageList fraged_pages,
|
static void vac_update_fsm(Relation onerel, VacPageList fraged_pages,
|
||||||
BlockNumber rel_pages);
|
BlockNumber rel_pages);
|
||||||
static VacPage copy_vac_page(VacPage vacpage);
|
static VacPage copy_vac_page(VacPage vacpage);
|
||||||
@ -2933,7 +2932,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* scan_index() -- scan one index relation to update statistic.
|
* scan_index() -- scan one index relation to update pg_class statistics.
|
||||||
*
|
*
|
||||||
* We use this when we have no deletions to do.
|
* We use this when we have no deletions to do.
|
||||||
*/
|
*/
|
||||||
@ -2941,25 +2940,17 @@ static void
|
|||||||
scan_index(Relation indrel, double num_tuples)
|
scan_index(Relation indrel, double num_tuples)
|
||||||
{
|
{
|
||||||
IndexBulkDeleteResult *stats;
|
IndexBulkDeleteResult *stats;
|
||||||
IndexVacuumCleanupInfo vcinfo;
|
IndexVacuumInfo ivinfo;
|
||||||
PGRUsage ru0;
|
PGRUsage ru0;
|
||||||
|
|
||||||
pg_rusage_init(&ru0);
|
pg_rusage_init(&ru0);
|
||||||
|
|
||||||
/*
|
ivinfo.index = indrel;
|
||||||
* Even though we're not planning to delete anything, we use the
|
ivinfo.vacuum_full = true;
|
||||||
* ambulkdelete call, because (a) the scan happens within the index AM for
|
ivinfo.message_level = elevel;
|
||||||
* more speed, and (b) it may want to pass private statistics to the
|
ivinfo.num_heap_tuples = num_tuples;
|
||||||
* amvacuumcleanup call.
|
|
||||||
*/
|
|
||||||
stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL);
|
|
||||||
|
|
||||||
/* Do post-VACUUM cleanup, even though we deleted nothing */
|
stats = index_vacuum_cleanup(&ivinfo, NULL);
|
||||||
vcinfo.vacuum_full = true;
|
|
||||||
vcinfo.message_level = elevel;
|
|
||||||
vcinfo.num_heap_tuples = num_tuples;
|
|
||||||
|
|
||||||
stats = index_vacuum_cleanup(indrel, &vcinfo, stats);
|
|
||||||
|
|
||||||
if (!stats)
|
if (!stats)
|
||||||
return;
|
return;
|
||||||
@ -2982,16 +2973,7 @@ scan_index(Relation indrel, double num_tuples)
|
|||||||
/*
|
/*
|
||||||
* Check for tuple count mismatch. If the index is partial, then it's OK
|
* Check for tuple count mismatch. If the index is partial, then it's OK
|
||||||
* for it to have fewer tuples than the heap; else we got trouble.
|
* for it to have fewer tuples than the heap; else we got trouble.
|
||||||
*
|
|
||||||
* XXX Hack. Since GIN stores every pointer to heap several times and
|
|
||||||
* counting num_index_tuples during vacuum is very comlpex and slow
|
|
||||||
* we just copy num_tuples to num_index_tuples as upper limit to avoid
|
|
||||||
* WARNING and optimizer mistakes.
|
|
||||||
*/
|
*/
|
||||||
if ( indrel->rd_rel->relam == GIN_AM_OID )
|
|
||||||
{
|
|
||||||
stats->num_index_tuples = num_tuples;
|
|
||||||
} else
|
|
||||||
if (stats->num_index_tuples != num_tuples)
|
if (stats->num_index_tuples != num_tuples)
|
||||||
{
|
{
|
||||||
if (stats->num_index_tuples > num_tuples ||
|
if (stats->num_index_tuples > num_tuples ||
|
||||||
@ -3023,20 +3005,21 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
|
|||||||
double num_tuples, int keep_tuples)
|
double num_tuples, int keep_tuples)
|
||||||
{
|
{
|
||||||
IndexBulkDeleteResult *stats;
|
IndexBulkDeleteResult *stats;
|
||||||
IndexVacuumCleanupInfo vcinfo;
|
IndexVacuumInfo ivinfo;
|
||||||
PGRUsage ru0;
|
PGRUsage ru0;
|
||||||
|
|
||||||
pg_rusage_init(&ru0);
|
pg_rusage_init(&ru0);
|
||||||
|
|
||||||
|
ivinfo.index = indrel;
|
||||||
|
ivinfo.vacuum_full = true;
|
||||||
|
ivinfo.message_level = elevel;
|
||||||
|
ivinfo.num_heap_tuples = num_tuples + keep_tuples;
|
||||||
|
|
||||||
/* Do bulk deletion */
|
/* Do bulk deletion */
|
||||||
stats = index_bulk_delete(indrel, tid_reaped, (void *) vacpagelist);
|
stats = index_bulk_delete(&ivinfo, NULL, tid_reaped, (void *) vacpagelist);
|
||||||
|
|
||||||
/* Do post-VACUUM cleanup */
|
/* Do post-VACUUM cleanup */
|
||||||
vcinfo.vacuum_full = true;
|
stats = index_vacuum_cleanup(&ivinfo, stats);
|
||||||
vcinfo.message_level = elevel;
|
|
||||||
vcinfo.num_heap_tuples = num_tuples + keep_tuples;
|
|
||||||
|
|
||||||
stats = index_vacuum_cleanup(indrel, &vcinfo, stats);
|
|
||||||
|
|
||||||
if (!stats)
|
if (!stats)
|
||||||
return;
|
return;
|
||||||
@ -3061,16 +3044,7 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
|
|||||||
/*
|
/*
|
||||||
* Check for tuple count mismatch. If the index is partial, then it's OK
|
* Check for tuple count mismatch. If the index is partial, then it's OK
|
||||||
* for it to have fewer tuples than the heap; else we got trouble.
|
* for it to have fewer tuples than the heap; else we got trouble.
|
||||||
*
|
|
||||||
* XXX Hack. Since GIN stores every pointer to heap several times and
|
|
||||||
* counting num_index_tuples during vacuum is very comlpex and slow
|
|
||||||
* we just copy num_tuples to num_index_tuples as upper limit to avoid
|
|
||||||
* WARNING and optimizer mistakes.
|
|
||||||
*/
|
*/
|
||||||
if ( indrel->rd_rel->relam == GIN_AM_OID )
|
|
||||||
{
|
|
||||||
stats->num_index_tuples = num_tuples;
|
|
||||||
} else
|
|
||||||
if (stats->num_index_tuples != num_tuples + keep_tuples)
|
if (stats->num_index_tuples != num_tuples + keep_tuples)
|
||||||
{
|
{
|
||||||
if (stats->num_index_tuples > num_tuples + keep_tuples ||
|
if (stats->num_index_tuples > num_tuples + keep_tuples ||
|
||||||
@ -3137,15 +3111,6 @@ tid_reaped(ItemPointer itemptr, void *state)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Dummy version for scan_index.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
dummy_tid_reaped(ItemPointer itemptr, void *state)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the shared Free Space Map with the info we now have about
|
* Update the shared Free Space Map with the info we now have about
|
||||||
* free space in the relation, discarding any old info the map may have.
|
* free space in the relation, discarding any old info the map may have.
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.69 2006/03/31 23:32:06 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.70 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -96,11 +96,12 @@ static TransactionId FreezeLimit;
|
|||||||
static void lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
static void lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
||||||
Relation *Irel, int nindexes);
|
Relation *Irel, int nindexes);
|
||||||
static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats);
|
static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats);
|
||||||
static void lazy_scan_index(Relation indrel, LVRelStats *vacrelstats);
|
|
||||||
static void lazy_vacuum_index(Relation indrel,
|
static void lazy_vacuum_index(Relation indrel,
|
||||||
double *index_tups_vacuumed,
|
IndexBulkDeleteResult **stats,
|
||||||
BlockNumber *index_pages_removed,
|
LVRelStats *vacrelstats);
|
||||||
LVRelStats *vacrelstats);
|
static void lazy_cleanup_index(Relation indrel,
|
||||||
|
IndexBulkDeleteResult *stats,
|
||||||
|
LVRelStats *vacrelstats);
|
||||||
static int lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
|
static int lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
|
||||||
int tupindex, LVRelStats *vacrelstats);
|
int tupindex, LVRelStats *vacrelstats);
|
||||||
static void lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats);
|
static void lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats);
|
||||||
@ -112,7 +113,6 @@ static void lazy_record_dead_tuple(LVRelStats *vacrelstats,
|
|||||||
static void lazy_record_free_space(LVRelStats *vacrelstats,
|
static void lazy_record_free_space(LVRelStats *vacrelstats,
|
||||||
BlockNumber page, Size avail);
|
BlockNumber page, Size avail);
|
||||||
static bool lazy_tid_reaped(ItemPointer itemptr, void *state);
|
static bool lazy_tid_reaped(ItemPointer itemptr, void *state);
|
||||||
static bool dummy_tid_reaped(ItemPointer itemptr, void *state);
|
|
||||||
static void lazy_update_fsm(Relation onerel, LVRelStats *vacrelstats);
|
static void lazy_update_fsm(Relation onerel, LVRelStats *vacrelstats);
|
||||||
static int vac_cmp_itemptr(const void *left, const void *right);
|
static int vac_cmp_itemptr(const void *left, const void *right);
|
||||||
static int vac_cmp_page_spaces(const void *left, const void *right);
|
static int vac_cmp_page_spaces(const void *left, const void *right);
|
||||||
@ -207,9 +207,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
tups_vacuumed,
|
tups_vacuumed,
|
||||||
nkeep,
|
nkeep,
|
||||||
nunused;
|
nunused;
|
||||||
double *index_tups_vacuumed;
|
IndexBulkDeleteResult **indstats;
|
||||||
BlockNumber *index_pages_removed;
|
|
||||||
bool did_vacuum_index = false;
|
|
||||||
int i;
|
int i;
|
||||||
PGRUsage ru0;
|
PGRUsage ru0;
|
||||||
|
|
||||||
@ -224,15 +222,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
empty_pages = 0;
|
empty_pages = 0;
|
||||||
num_tuples = tups_vacuumed = nkeep = nunused = 0;
|
num_tuples = tups_vacuumed = nkeep = nunused = 0;
|
||||||
|
|
||||||
/*
|
indstats = (IndexBulkDeleteResult **)
|
||||||
* Because index vacuuming is done in multiple passes, we have to keep
|
palloc0(nindexes * sizeof(IndexBulkDeleteResult *));
|
||||||
* track of the total number of rows and pages removed from each index.
|
|
||||||
* index_tups_vacuumed[i] is the number removed so far from the i'th
|
|
||||||
* index. (For partial indexes this could well be different from
|
|
||||||
* tups_vacuumed.) Likewise for index_pages_removed[i].
|
|
||||||
*/
|
|
||||||
index_tups_vacuumed = (double *) palloc0(nindexes * sizeof(double));
|
|
||||||
index_pages_removed = (BlockNumber *) palloc0(nindexes * sizeof(BlockNumber));
|
|
||||||
|
|
||||||
nblocks = RelationGetNumberOfBlocks(onerel);
|
nblocks = RelationGetNumberOfBlocks(onerel);
|
||||||
vacrelstats->rel_pages = nblocks;
|
vacrelstats->rel_pages = nblocks;
|
||||||
@ -263,10 +254,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
/* Remove index entries */
|
/* Remove index entries */
|
||||||
for (i = 0; i < nindexes; i++)
|
for (i = 0; i < nindexes; i++)
|
||||||
lazy_vacuum_index(Irel[i],
|
lazy_vacuum_index(Irel[i],
|
||||||
&index_tups_vacuumed[i],
|
&indstats[i],
|
||||||
&index_pages_removed[i],
|
|
||||||
vacrelstats);
|
vacrelstats);
|
||||||
did_vacuum_index = true;
|
|
||||||
/* Remove tuples from heap */
|
/* Remove tuples from heap */
|
||||||
lazy_vacuum_heap(onerel, vacrelstats);
|
lazy_vacuum_heap(onerel, vacrelstats);
|
||||||
/* Forget the now-vacuumed tuples, and press on */
|
/* Forget the now-vacuumed tuples, and press on */
|
||||||
@ -454,18 +443,15 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
|
|||||||
/* Remove index entries */
|
/* Remove index entries */
|
||||||
for (i = 0; i < nindexes; i++)
|
for (i = 0; i < nindexes; i++)
|
||||||
lazy_vacuum_index(Irel[i],
|
lazy_vacuum_index(Irel[i],
|
||||||
&index_tups_vacuumed[i],
|
&indstats[i],
|
||||||
&index_pages_removed[i],
|
|
||||||
vacrelstats);
|
vacrelstats);
|
||||||
/* Remove tuples from heap */
|
/* Remove tuples from heap */
|
||||||
lazy_vacuum_heap(onerel, vacrelstats);
|
lazy_vacuum_heap(onerel, vacrelstats);
|
||||||
}
|
}
|
||||||
else if (!did_vacuum_index)
|
|
||||||
{
|
/* Do post-vacuum cleanup and statistics update for each index */
|
||||||
/* Must do post-vacuum cleanup and statistics update anyway */
|
for (i = 0; i < nindexes; i++)
|
||||||
for (i = 0; i < nindexes; i++)
|
lazy_cleanup_index(Irel[i], indstats[i], vacrelstats);
|
||||||
lazy_scan_index(Irel[i], vacrelstats);
|
|
||||||
}
|
|
||||||
|
|
||||||
ereport(elevel,
|
ereport(elevel,
|
||||||
(errmsg("\"%s\": found %.0f removable, %.0f nonremovable row versions in %u pages",
|
(errmsg("\"%s\": found %.0f removable, %.0f nonremovable row versions in %u pages",
|
||||||
@ -590,94 +576,18 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
|
|||||||
return tupindex;
|
return tupindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* lazy_scan_index() -- scan one index relation to update pg_class statistic.
|
|
||||||
*
|
|
||||||
* We use this when we have no deletions to do.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
lazy_scan_index(Relation indrel, LVRelStats *vacrelstats)
|
|
||||||
{
|
|
||||||
IndexBulkDeleteResult *stats;
|
|
||||||
IndexVacuumCleanupInfo vcinfo;
|
|
||||||
PGRUsage ru0;
|
|
||||||
|
|
||||||
pg_rusage_init(&ru0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Acquire appropriate type of lock on index: must be exclusive if index
|
|
||||||
* AM isn't concurrent-safe.
|
|
||||||
*/
|
|
||||||
if (indrel->rd_am->amconcurrent)
|
|
||||||
LockRelation(indrel, RowExclusiveLock);
|
|
||||||
else
|
|
||||||
LockRelation(indrel, AccessExclusiveLock);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Even though we're not planning to delete anything, we use the
|
|
||||||
* ambulkdelete call, because (a) the scan happens within the index AM for
|
|
||||||
* more speed, and (b) it may want to pass private statistics to the
|
|
||||||
* amvacuumcleanup call.
|
|
||||||
*/
|
|
||||||
stats = index_bulk_delete(indrel, dummy_tid_reaped, NULL);
|
|
||||||
|
|
||||||
/* Do post-VACUUM cleanup, even though we deleted nothing */
|
|
||||||
vcinfo.vacuum_full = false;
|
|
||||||
vcinfo.message_level = elevel;
|
|
||||||
vcinfo.num_heap_tuples = vacrelstats->rel_tuples;
|
|
||||||
|
|
||||||
stats = index_vacuum_cleanup(indrel, &vcinfo, stats);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Release lock acquired above.
|
|
||||||
*/
|
|
||||||
if (indrel->rd_am->amconcurrent)
|
|
||||||
UnlockRelation(indrel, RowExclusiveLock);
|
|
||||||
else
|
|
||||||
UnlockRelation(indrel, AccessExclusiveLock);
|
|
||||||
|
|
||||||
if (!stats)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* now update statistics in pg_class */
|
|
||||||
vac_update_relstats(RelationGetRelid(indrel),
|
|
||||||
stats->num_pages,
|
|
||||||
stats->num_index_tuples,
|
|
||||||
false);
|
|
||||||
|
|
||||||
ereport(elevel,
|
|
||||||
(errmsg("index \"%s\" now contains %.0f row versions in %u pages",
|
|
||||||
RelationGetRelationName(indrel),
|
|
||||||
stats->num_index_tuples,
|
|
||||||
stats->num_pages),
|
|
||||||
errdetail("%u index pages have been deleted, %u are currently reusable.\n"
|
|
||||||
"%s.",
|
|
||||||
stats->pages_deleted, stats->pages_free,
|
|
||||||
pg_rusage_show(&ru0))));
|
|
||||||
|
|
||||||
pfree(stats);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* lazy_vacuum_index() -- vacuum one index relation.
|
* lazy_vacuum_index() -- vacuum one index relation.
|
||||||
*
|
*
|
||||||
* Delete all the index entries pointing to tuples listed in
|
* Delete all the index entries pointing to tuples listed in
|
||||||
* vacrelstats->dead_tuples.
|
* vacrelstats->dead_tuples, and update running statistics.
|
||||||
*
|
|
||||||
* Increment *index_tups_vacuumed by the number of index entries
|
|
||||||
* removed, and *index_pages_removed by the number of pages removed.
|
|
||||||
*
|
|
||||||
* Finally, we arrange to update the index relation's statistics in
|
|
||||||
* pg_class.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
lazy_vacuum_index(Relation indrel,
|
lazy_vacuum_index(Relation indrel,
|
||||||
double *index_tups_vacuumed,
|
IndexBulkDeleteResult **stats,
|
||||||
BlockNumber *index_pages_removed,
|
|
||||||
LVRelStats *vacrelstats)
|
LVRelStats *vacrelstats)
|
||||||
{
|
{
|
||||||
IndexBulkDeleteResult *stats;
|
IndexVacuumInfo ivinfo;
|
||||||
IndexVacuumCleanupInfo vcinfo;
|
|
||||||
PGRUsage ru0;
|
PGRUsage ru0;
|
||||||
|
|
||||||
pg_rusage_init(&ru0);
|
pg_rusage_init(&ru0);
|
||||||
@ -691,17 +601,59 @@ lazy_vacuum_index(Relation indrel,
|
|||||||
else
|
else
|
||||||
LockRelation(indrel, AccessExclusiveLock);
|
LockRelation(indrel, AccessExclusiveLock);
|
||||||
|
|
||||||
/* Do bulk deletion */
|
ivinfo.index = indrel;
|
||||||
stats = index_bulk_delete(indrel, lazy_tid_reaped, (void *) vacrelstats);
|
ivinfo.vacuum_full = false;
|
||||||
|
ivinfo.message_level = elevel;
|
||||||
/* Do post-VACUUM cleanup */
|
|
||||||
vcinfo.vacuum_full = false;
|
|
||||||
vcinfo.message_level = elevel;
|
|
||||||
/* We don't yet know rel_tuples, so pass -1 */
|
/* We don't yet know rel_tuples, so pass -1 */
|
||||||
/* index_bulk_delete can't have skipped scan anyway ... */
|
ivinfo.num_heap_tuples = -1;
|
||||||
vcinfo.num_heap_tuples = -1;
|
|
||||||
|
|
||||||
stats = index_vacuum_cleanup(indrel, &vcinfo, stats);
|
/* Do bulk deletion */
|
||||||
|
*stats = index_bulk_delete(&ivinfo, *stats,
|
||||||
|
lazy_tid_reaped, (void *) vacrelstats);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Release lock acquired above.
|
||||||
|
*/
|
||||||
|
if (indrel->rd_am->amconcurrent)
|
||||||
|
UnlockRelation(indrel, RowExclusiveLock);
|
||||||
|
else
|
||||||
|
UnlockRelation(indrel, AccessExclusiveLock);
|
||||||
|
|
||||||
|
ereport(elevel,
|
||||||
|
(errmsg("scanned index \"%s\" to remove %d row versions",
|
||||||
|
RelationGetRelationName(indrel),
|
||||||
|
vacrelstats->num_dead_tuples),
|
||||||
|
errdetail("%s.", pg_rusage_show(&ru0))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lazy_cleanup_index() -- do post-vacuum cleanup for one index relation.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
lazy_cleanup_index(Relation indrel,
|
||||||
|
IndexBulkDeleteResult *stats,
|
||||||
|
LVRelStats *vacrelstats)
|
||||||
|
{
|
||||||
|
IndexVacuumInfo ivinfo;
|
||||||
|
PGRUsage ru0;
|
||||||
|
|
||||||
|
pg_rusage_init(&ru0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Acquire appropriate type of lock on index: must be exclusive if index
|
||||||
|
* AM isn't concurrent-safe.
|
||||||
|
*/
|
||||||
|
if (indrel->rd_am->amconcurrent)
|
||||||
|
LockRelation(indrel, RowExclusiveLock);
|
||||||
|
else
|
||||||
|
LockRelation(indrel, AccessExclusiveLock);
|
||||||
|
|
||||||
|
ivinfo.index = indrel;
|
||||||
|
ivinfo.vacuum_full = false;
|
||||||
|
ivinfo.message_level = elevel;
|
||||||
|
ivinfo.num_heap_tuples = vacrelstats->rel_tuples;
|
||||||
|
|
||||||
|
stats = index_vacuum_cleanup(&ivinfo, stats);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release lock acquired above.
|
* Release lock acquired above.
|
||||||
@ -714,10 +666,6 @@ lazy_vacuum_index(Relation indrel,
|
|||||||
if (!stats)
|
if (!stats)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* accumulate total removed over multiple index-cleaning cycles */
|
|
||||||
*index_tups_vacuumed += stats->tuples_removed;
|
|
||||||
*index_pages_removed += stats->pages_removed;
|
|
||||||
|
|
||||||
/* now update statistics in pg_class */
|
/* now update statistics in pg_class */
|
||||||
vac_update_relstats(RelationGetRelid(indrel),
|
vac_update_relstats(RelationGetRelid(indrel),
|
||||||
stats->num_pages,
|
stats->num_pages,
|
||||||
@ -1134,15 +1082,6 @@ lazy_tid_reaped(ItemPointer itemptr, void *state)
|
|||||||
return (res != NULL);
|
return (res != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Dummy version for lazy_scan_index.
|
|
||||||
*/
|
|
||||||
static bool
|
|
||||||
dummy_tid_reaped(ItemPointer itemptr, void *state)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update the shared Free Space Map with the info we now have about
|
* Update the shared Free Space Map with the info we now have about
|
||||||
* free space in the relation, discarding any old info the map may have.
|
* free space in the relation, discarding any old info the map may have.
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.58 2006/03/05 15:58:53 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.59 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -21,13 +21,29 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Struct for statistics returned by bulk-delete operation
|
* Struct for input arguments passed to ambulkdelete and amvacuumcleanup
|
||||||
*
|
*
|
||||||
* This is now also passed to the index AM's vacuum-cleanup operation,
|
* Note that num_heap_tuples will not be valid during ambulkdelete,
|
||||||
* if it has one, which can modify the results as needed. Note that
|
* only amvacuumcleanup.
|
||||||
* an index AM could choose to have bulk-delete return a larger struct
|
*/
|
||||||
* of which this is just the first field; this provides a way for bulk-delete
|
typedef struct IndexVacuumInfo
|
||||||
* to communicate additional private data to vacuum-cleanup.
|
{
|
||||||
|
Relation index; /* the index being vacuumed */
|
||||||
|
bool vacuum_full; /* VACUUM FULL (we have exclusive lock) */
|
||||||
|
int message_level; /* ereport level for progress messages */
|
||||||
|
double num_heap_tuples; /* tuples remaining in heap */
|
||||||
|
} IndexVacuumInfo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Struct for statistics returned by ambulkdelete and amvacuumcleanup
|
||||||
|
*
|
||||||
|
* This struct is normally allocated by the first ambulkdelete call and then
|
||||||
|
* passed along through subsequent ones until amvacuumcleanup; however,
|
||||||
|
* amvacuumcleanup must be prepared to allocate it in the case where no
|
||||||
|
* ambulkdelete calls were made (because no tuples needed deletion).
|
||||||
|
* Note that an index AM could choose to return a larger struct
|
||||||
|
* of which this is just the first field; this provides a way for ambulkdelete
|
||||||
|
* to communicate additional private data to amvacuumcleanup.
|
||||||
*
|
*
|
||||||
* Note: pages_removed is the amount by which the index physically shrank,
|
* Note: pages_removed is the amount by which the index physically shrank,
|
||||||
* if any (ie the change in its total size on disk). pages_deleted and
|
* if any (ie the change in its total size on disk). pages_deleted and
|
||||||
@ -36,9 +52,9 @@
|
|||||||
typedef struct IndexBulkDeleteResult
|
typedef struct IndexBulkDeleteResult
|
||||||
{
|
{
|
||||||
BlockNumber num_pages; /* pages remaining in index */
|
BlockNumber num_pages; /* pages remaining in index */
|
||||||
BlockNumber pages_removed; /* # removed by bulk-delete operation */
|
BlockNumber pages_removed; /* # removed during vacuum operation */
|
||||||
double num_index_tuples; /* tuples remaining */
|
double num_index_tuples; /* tuples remaining */
|
||||||
double tuples_removed; /* # removed by bulk-delete operation */
|
double tuples_removed; /* # removed during vacuum operation */
|
||||||
BlockNumber pages_deleted; /* # unused pages in index */
|
BlockNumber pages_deleted; /* # unused pages in index */
|
||||||
BlockNumber pages_free; /* # pages available for reuse */
|
BlockNumber pages_free; /* # pages available for reuse */
|
||||||
} IndexBulkDeleteResult;
|
} IndexBulkDeleteResult;
|
||||||
@ -46,14 +62,6 @@ typedef struct IndexBulkDeleteResult
|
|||||||
/* Typedef for callback function to determine if a tuple is bulk-deletable */
|
/* Typedef for callback function to determine if a tuple is bulk-deletable */
|
||||||
typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
|
typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
|
||||||
|
|
||||||
/* Struct for additional arguments passed to vacuum-cleanup operation */
|
|
||||||
typedef struct IndexVacuumCleanupInfo
|
|
||||||
{
|
|
||||||
bool vacuum_full; /* VACUUM FULL (we have exclusive lock) */
|
|
||||||
int message_level; /* ereport level for progress messages */
|
|
||||||
double num_heap_tuples; /* tuples remaining in heap */
|
|
||||||
} IndexVacuumCleanupInfo;
|
|
||||||
|
|
||||||
/* Struct for heap-or-index scans of system tables */
|
/* Struct for heap-or-index scans of system tables */
|
||||||
typedef struct SysScanDescData
|
typedef struct SysScanDescData
|
||||||
{
|
{
|
||||||
@ -98,11 +106,11 @@ extern bool index_getmulti(IndexScanDesc scan,
|
|||||||
ItemPointer tids, int32 max_tids,
|
ItemPointer tids, int32 max_tids,
|
||||||
int32 *returned_tids);
|
int32 *returned_tids);
|
||||||
|
|
||||||
extern IndexBulkDeleteResult *index_bulk_delete(Relation indexRelation,
|
extern IndexBulkDeleteResult *index_bulk_delete(IndexVacuumInfo *info,
|
||||||
|
IndexBulkDeleteResult *stats,
|
||||||
IndexBulkDeleteCallback callback,
|
IndexBulkDeleteCallback callback,
|
||||||
void *callback_state);
|
void *callback_state);
|
||||||
extern IndexBulkDeleteResult *index_vacuum_cleanup(Relation indexRelation,
|
extern IndexBulkDeleteResult *index_vacuum_cleanup(IndexVacuumInfo *info,
|
||||||
IndexVacuumCleanupInfo *info,
|
|
||||||
IndexBulkDeleteResult *stats);
|
IndexBulkDeleteResult *stats);
|
||||||
extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
|
extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
|
||||||
uint16 procnum);
|
uint16 procnum);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.68 2006/03/31 23:32:06 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.69 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* modeled after Margo Seltzer's hash implementation for unix.
|
* modeled after Margo Seltzer's hash implementation for unix.
|
||||||
@ -233,6 +233,7 @@ extern Datum hashendscan(PG_FUNCTION_ARGS);
|
|||||||
extern Datum hashmarkpos(PG_FUNCTION_ARGS);
|
extern Datum hashmarkpos(PG_FUNCTION_ARGS);
|
||||||
extern Datum hashrestrpos(PG_FUNCTION_ARGS);
|
extern Datum hashrestrpos(PG_FUNCTION_ARGS);
|
||||||
extern Datum hashbulkdelete(PG_FUNCTION_ARGS);
|
extern Datum hashbulkdelete(PG_FUNCTION_ARGS);
|
||||||
|
extern Datum hashvacuumcleanup(PG_FUNCTION_ARGS);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Datatype-specific hash functions in hashfunc.c.
|
* Datatype-specific hash functions in hashfunc.c.
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.330 2006/05/02 15:23:16 teodor Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.331 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 200605022
|
#define CATALOG_VERSION_NO 200605023
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.41 2006/05/02 11:28:55 teodor Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.42 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* the genbki.sh script reads this file and generates .bki
|
* the genbki.sh script reads this file and generates .bki
|
||||||
@ -50,6 +50,7 @@ CATALOG(pg_am,2601)
|
|||||||
bool amcanmulticol; /* does AM support multi-column indexes? */
|
bool amcanmulticol; /* does AM support multi-column indexes? */
|
||||||
bool amoptionalkey; /* can query omit key for the first column? */
|
bool amoptionalkey; /* can query omit key for the first column? */
|
||||||
bool amindexnulls; /* does AM support NULL index entries? */
|
bool amindexnulls; /* does AM support NULL index entries? */
|
||||||
|
bool amstorage; /* can storage type differ from column type? */
|
||||||
bool amconcurrent; /* does AM support concurrent updates? */
|
bool amconcurrent; /* does AM support concurrent updates? */
|
||||||
bool amclusterable; /* does AM support cluster command? */
|
bool amclusterable; /* does AM support cluster command? */
|
||||||
regproc aminsert; /* "insert this tuple" function */
|
regproc aminsert; /* "insert this tuple" function */
|
||||||
@ -77,7 +78,7 @@ typedef FormData_pg_am *Form_pg_am;
|
|||||||
* compiler constants for pg_am
|
* compiler constants for pg_am
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
#define Natts_pg_am 22
|
#define Natts_pg_am 23
|
||||||
#define Anum_pg_am_amname 1
|
#define Anum_pg_am_amname 1
|
||||||
#define Anum_pg_am_amstrategies 2
|
#define Anum_pg_am_amstrategies 2
|
||||||
#define Anum_pg_am_amsupport 3
|
#define Anum_pg_am_amsupport 3
|
||||||
@ -86,36 +87,37 @@ typedef FormData_pg_am *Form_pg_am;
|
|||||||
#define Anum_pg_am_amcanmulticol 6
|
#define Anum_pg_am_amcanmulticol 6
|
||||||
#define Anum_pg_am_amoptionalkey 7
|
#define Anum_pg_am_amoptionalkey 7
|
||||||
#define Anum_pg_am_amindexnulls 8
|
#define Anum_pg_am_amindexnulls 8
|
||||||
#define Anum_pg_am_amconcurrent 9
|
#define Anum_pg_am_amstorage 9
|
||||||
#define Anum_pg_am_amclusterable 10
|
#define Anum_pg_am_amconcurrent 10
|
||||||
#define Anum_pg_am_aminsert 11
|
#define Anum_pg_am_amclusterable 11
|
||||||
#define Anum_pg_am_ambeginscan 12
|
#define Anum_pg_am_aminsert 12
|
||||||
#define Anum_pg_am_amgettuple 13
|
#define Anum_pg_am_ambeginscan 13
|
||||||
#define Anum_pg_am_amgetmulti 14
|
#define Anum_pg_am_amgettuple 14
|
||||||
#define Anum_pg_am_amrescan 15
|
#define Anum_pg_am_amgetmulti 15
|
||||||
#define Anum_pg_am_amendscan 16
|
#define Anum_pg_am_amrescan 16
|
||||||
#define Anum_pg_am_ammarkpos 17
|
#define Anum_pg_am_amendscan 17
|
||||||
#define Anum_pg_am_amrestrpos 18
|
#define Anum_pg_am_ammarkpos 18
|
||||||
#define Anum_pg_am_ambuild 19
|
#define Anum_pg_am_amrestrpos 19
|
||||||
#define Anum_pg_am_ambulkdelete 20
|
#define Anum_pg_am_ambuild 20
|
||||||
#define Anum_pg_am_amvacuumcleanup 21
|
#define Anum_pg_am_ambulkdelete 21
|
||||||
#define Anum_pg_am_amcostestimate 22
|
#define Anum_pg_am_amvacuumcleanup 22
|
||||||
|
#define Anum_pg_am_amcostestimate 23
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* initial contents of pg_am
|
* initial contents of pg_am
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DATA(insert OID = 403 ( btree 5 1 1 t t t t t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
|
DATA(insert OID = 403 ( btree 5 1 1 t t t t f t t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate ));
|
||||||
DESCR("b-tree index access method");
|
DESCR("b-tree index access method");
|
||||||
#define BTREE_AM_OID 403
|
#define BTREE_AM_OID 403
|
||||||
DATA(insert OID = 405 ( hash 1 1 0 f f f f t f hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete - hashcostestimate ));
|
DATA(insert OID = 405 ( hash 1 1 0 f f f f f t f hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate ));
|
||||||
DESCR("hash index access method");
|
DESCR("hash index access method");
|
||||||
#define HASH_AM_OID 405
|
#define HASH_AM_OID 405
|
||||||
DATA(insert OID = 783 ( gist 100 7 0 f t f f t t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate ));
|
DATA(insert OID = 783 ( gist 100 7 0 f t f f t t t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate ));
|
||||||
DESCR("GiST index access method");
|
DESCR("GiST index access method");
|
||||||
#define GIST_AM_OID 783
|
#define GIST_AM_OID 783
|
||||||
DATA(insert OID = 2742 ( gin 100 4 0 f f f f t f gininsert ginbeginscan gingettuple gingetmulti ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ));
|
DATA(insert OID = 2742 ( gin 100 4 0 f f f f t t f gininsert ginbeginscan gingettuple gingetmulti ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ));
|
||||||
DESCR("GIN index access method");
|
DESCR("GIN index access method");
|
||||||
#define GIN_AM_OID 2742
|
#define GIN_AM_OID 2742
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.409 2006/05/02 11:28:55 teodor Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.410 2006/05/02 22:25:10 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The script catalog/genbki.sh reads this file and generates .bki
|
* The script catalog/genbki.sh reads this file and generates .bki
|
||||||
@ -674,9 +674,9 @@ DATA(insert OID = 337 ( btrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281" _
|
|||||||
DESCR("btree(internal)");
|
DESCR("btree(internal)");
|
||||||
DATA(insert OID = 338 ( btbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ btbuild - _null_ ));
|
DATA(insert OID = 338 ( btbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ btbuild - _null_ ));
|
||||||
DESCR("btree(internal)");
|
DESCR("btree(internal)");
|
||||||
DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ btbulkdelete - _null_ ));
|
DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 f f t f v 4 2281 "2281 2281 2281 2281" _null_ _null_ _null_ btbulkdelete - _null_ ));
|
||||||
DESCR("btree(internal)");
|
DESCR("btree(internal)");
|
||||||
DATA(insert OID = 972 ( btvacuumcleanup PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ btvacuumcleanup - _null_ ));
|
DATA(insert OID = 972 ( btvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281 2281" _null_ _null_ _null_ btvacuumcleanup - _null_ ));
|
||||||
DESCR("btree(internal)");
|
DESCR("btree(internal)");
|
||||||
DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ btcostestimate - _null_ ));
|
DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ btcostestimate - _null_ ));
|
||||||
DESCR("btree(internal)");
|
DESCR("btree(internal)");
|
||||||
@ -791,7 +791,9 @@ DATA(insert OID = 447 ( hashrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281"
|
|||||||
DESCR("hash(internal)");
|
DESCR("hash(internal)");
|
||||||
DATA(insert OID = 448 ( hashbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ hashbuild - _null_ ));
|
DATA(insert OID = 448 ( hashbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ hashbuild - _null_ ));
|
||||||
DESCR("hash(internal)");
|
DESCR("hash(internal)");
|
||||||
DATA(insert OID = 442 ( hashbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ hashbulkdelete - _null_ ));
|
DATA(insert OID = 442 ( hashbulkdelete PGNSP PGUID 12 f f t f v 4 2281 "2281 2281 2281 2281" _null_ _null_ _null_ hashbulkdelete - _null_ ));
|
||||||
|
DESCR("hash(internal)");
|
||||||
|
DATA(insert OID = 425 ( hashvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281 2281" _null_ _null_ _null_ hashvacuumcleanup - _null_ ));
|
||||||
DESCR("hash(internal)");
|
DESCR("hash(internal)");
|
||||||
DATA(insert OID = 438 ( hashcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ hashcostestimate - _null_ ));
|
DATA(insert OID = 438 ( hashcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ hashcostestimate - _null_ ));
|
||||||
DESCR("hash(internal)");
|
DESCR("hash(internal)");
|
||||||
@ -1055,9 +1057,10 @@ DATA(insert OID = 781 ( gistrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281"
|
|||||||
DESCR("gist(internal)");
|
DESCR("gist(internal)");
|
||||||
DATA(insert OID = 782 ( gistbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ gistbuild - _null_ ));
|
DATA(insert OID = 782 ( gistbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ gistbuild - _null_ ));
|
||||||
DESCR("gist(internal)");
|
DESCR("gist(internal)");
|
||||||
DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ gistbulkdelete - _null_ ));
|
DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 f f t f v 4 2281 "2281 2281 2281 2281" _null_ _null_ _null_ gistbulkdelete - _null_ ));
|
||||||
|
DESCR("gist(internal)");
|
||||||
|
DATA(insert OID = 2561 ( gistvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281 2281" _null_ _null_ _null_ gistvacuumcleanup - _null_ ));
|
||||||
DESCR("gist(internal)");
|
DESCR("gist(internal)");
|
||||||
DATA(insert OID = 2561 ( gistvacuumcleanup PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ gistvacuumcleanup - _null_ ));
|
|
||||||
DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gistcostestimate - _null_ ));
|
DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gistcostestimate - _null_ ));
|
||||||
DESCR("gist(internal)");
|
DESCR("gist(internal)");
|
||||||
|
|
||||||
@ -3832,9 +3835,9 @@ DATA(insert OID = 2737 ( ginrestrpos PGNSP PGUID 12 f f t f v 1 2278 "2281"
|
|||||||
DESCR("gin(internal)");
|
DESCR("gin(internal)");
|
||||||
DATA(insert OID = 2738 ( ginbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ ginbuild - _null_ ));
|
DATA(insert OID = 2738 ( ginbuild PGNSP PGUID 12 f f t f v 3 2278 "2281 2281 2281" _null_ _null_ _null_ ginbuild - _null_ ));
|
||||||
DESCR("gin(internal)");
|
DESCR("gin(internal)");
|
||||||
DATA(insert OID = 2739 ( ginbulkdelete PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ ginbulkdelete - _null_ ));
|
DATA(insert OID = 2739 ( ginbulkdelete PGNSP PGUID 12 f f t f v 4 2281 "2281 2281 2281 2281" _null_ _null_ _null_ ginbulkdelete - _null_ ));
|
||||||
DESCR("gin(internal)");
|
DESCR("gin(internal)");
|
||||||
DATA(insert OID = 2740 ( ginvacuumcleanup PGNSP PGUID 12 f f t f v 3 2281 "2281 2281 2281" _null_ _null_ _null_ ginvacuumcleanup - _null_ ));
|
DATA(insert OID = 2740 ( ginvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281 2281" _null_ _null_ _null_ ginvacuumcleanup - _null_ ));
|
||||||
DESCR("gin(internal)");
|
DESCR("gin(internal)");
|
||||||
DATA(insert OID = 2741 ( gincostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gincostestimate - _null_ ));
|
DATA(insert OID = 2741 ( gincostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gincostestimate - _null_ ));
|
||||||
DESCR("gin(internal)");
|
DESCR("gin(internal)");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user