Commit c8076f09 authored by Tom Lane's avatar Tom Lane

Restructure index AM interface for index building and index tuple deletion,

per previous discussion on pghackers.  Most of the duplicate code in
different AMs' ambuild routines has been moved out to a common routine
in index.c; this means that all index types now do the right things about
inserting recently-dead tuples, etc.  (I also removed support for EXTEND
INDEX in the ambuild routines, since that's about to go away anyway, and
it cluttered the code a lot.)  The retail indextuple deletion routines have
been replaced by a "bulk delete" routine in which the indexscan is inside
the access method.  I haven't pushed this change as far as it should go yet,
but it should allow considerable simplification of the internal bookkeeping
for deletions.  Also, add flag columns to pg_am to eliminate various
hardcoded tests on AM OIDs, and remove unused pg_am columns.

Fix rtree and gist index types to not attempt to store NULLs; before this,
gist usually crashed, while rtree managed not to crash but computed wacko
bounding boxes for NULL entries (which might have had something to do with
the performance problems we've heard about occasionally).

Add AtEOXact routines to hash, rtree, and gist, all of which have static
state that needs to be reset after an error.  We discovered this need long
ago for btree, but missed the other guys.

Oh, one more thing: concurrent VACUUM is now the default.
parent 997439f5
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.18 2001/06/12 05:55:48 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.19 2001/07/15 22:48:15 tgl Exp $
--> -->
<chapter id="catalogs"> <chapter id="catalogs">
...@@ -1045,7 +1045,8 @@ ...@@ -1045,7 +1045,8 @@
<entry>indpred</entry> <entry>indpred</entry>
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry></entry> <entry></entry>
<entry>Query plan for partial index predicate (not functional)</entry> <entry>Expression tree (in the form of a nodeToString representation)
for partial index predicate</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.26 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.27 2001/07/15 22:48:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,12 +24,9 @@ ...@@ -24,12 +24,9 @@
*/ */
int NIndexTupleProcessed; int NIndexTupleProcessed;
/* ---------------- /* ----------------
* index_keytest * index_keytest - does this index tuple satisfy the scan key(s)?
*
* old comments
* May eventually combine with other tests (like timeranges)?
* Should have Buffer buffer; as an argument and pass it to amgetattr.
* ---------------- * ----------------
*/ */
bool bool
...@@ -38,16 +35,16 @@ index_keytest(IndexTuple tuple, ...@@ -38,16 +35,16 @@ index_keytest(IndexTuple tuple,
int scanKeySize, int scanKeySize,
ScanKey key) ScanKey key)
{ {
bool isNull;
Datum datum;
Datum test;
IncrIndexProcessed(); IncrIndexProcessed();
while (scanKeySize > 0) while (scanKeySize > 0)
{ {
Datum datum;
bool isNull;
Datum test;
datum = index_getattr(tuple, datum = index_getattr(tuple,
key[0].sk_attno, key->sk_attno,
tupdesc, tupdesc,
&isNull); &isNull);
...@@ -57,25 +54,19 @@ index_keytest(IndexTuple tuple, ...@@ -57,25 +54,19 @@ index_keytest(IndexTuple tuple,
return false; return false;
} }
if (key[0].sk_flags & SK_ISNULL) if (key->sk_flags & SK_ISNULL)
return false; return false;
if (key[0].sk_flags & SK_COMMUTE) if (key->sk_flags & SK_COMMUTE)
{ test = FunctionCall2(&key->sk_func, key->sk_argument, datum);
test = FunctionCall2(&key[0].sk_func,
key[0].sk_argument, datum);
}
else else
{ test = FunctionCall2(&key->sk_func, datum, key->sk_argument);
test = FunctionCall2(&key[0].sk_func,
datum, key[0].sk_argument);
}
if (DatumGetBool(test) == !!(key[0].sk_flags & SK_NEGATE)) if (DatumGetBool(test) == !!(key->sk_flags & SK_NEGATE))
return false; return false;
scanKeySize -= 1;
key++; key++;
scanKeySize--;
} }
return true; return true;
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -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
* $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.37 2001/06/28 16:00:07 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.38 2001/07/15 22:48:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -59,13 +59,8 @@ gistbeginscan(PG_FUNCTION_ARGS) ...@@ -59,13 +59,8 @@ gistbeginscan(PG_FUNCTION_ARGS)
ScanKey key = (ScanKey) PG_GETARG_POINTER(3); ScanKey key = (ScanKey) PG_GETARG_POINTER(3);
IndexScanDesc s; IndexScanDesc s;
/*
* Let index_beginscan does its work...
*
* RelationSetLockForRead(r);
*/
s = RelationGetIndexScan(r, fromEnd, nkeys, key); s = RelationGetIndexScan(r, fromEnd, nkeys, key);
gistregscan(s); gistregscan(s);
PG_RETURN_POINTER(s); PG_RETURN_POINTER(s);
...@@ -283,6 +278,27 @@ gistdropscan(IndexScanDesc s) ...@@ -283,6 +278,27 @@ gistdropscan(IndexScanDesc s)
pfree(l); pfree(l);
} }
/*
* AtEOXact_gist() --- clean up gist subsystem at xact abort or commit.
*
* This is here because it needs to touch this module's static var GISTScans.
*/
void
AtEOXact_gist(void)
{
/*
* Note: these actions should only be necessary during xact abort; but
* they can't hurt during a commit.
*/
/*
* Reset the active-scans list to empty. We do not need to free the
* list elements, because they're all palloc()'d, so they'll go away
* at end of transaction anyway.
*/
GISTScans = NULL;
}
void void
gistadjscans(Relation rel, int op, BlockNumber blkno, OffsetNumber offnum) gistadjscans(Relation rel, int op, BlockNumber blkno, OffsetNumber offnum)
{ {
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.29 2001/03/07 21:20:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashovfl.c,v 1.30 2001/07/15 22:48:15 tgl Exp $
* *
* NOTES * NOTES
* Overflow pages look like ordinary relation pages. * Overflow pages look like ordinary relation pages.
...@@ -112,14 +112,14 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp) ...@@ -112,14 +112,14 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp)
metap = (HashMetaPage) _hash_chgbufaccess(rel, metabufp, HASH_READ, HASH_WRITE); metap = (HashMetaPage) _hash_chgbufaccess(rel, metabufp, HASH_READ, HASH_WRITE);
splitnum = metap->OVFL_POINT; splitnum = metap->hashm_ovflpoint;
max_free = metap->SPARES[splitnum]; max_free = metap->hashm_spares[splitnum];
free_page = (max_free - 1) >> (metap->hashm_bshift + BYTE_TO_BIT); free_page = (max_free - 1) >> (metap->hashm_bshift + BYTE_TO_BIT);
free_bit = (max_free - 1) & (BMPGSZ_BIT(metap) - 1); free_bit = (max_free - 1) & (BMPGSZ_BIT(metap) - 1);
/* Look through all the free maps to find the first free block */ /* Look through all the free maps to find the first free block */
first_page = metap->LAST_FREED >> (metap->hashm_bshift + BYTE_TO_BIT); first_page = metap->hashm_lastfreed >> (metap->hashm_bshift + BYTE_TO_BIT);
for (i = first_page; i <= free_page; i++) for (i = first_page; i <= free_page; i++)
{ {
Page mappage; Page mappage;
...@@ -138,7 +138,7 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp) ...@@ -138,7 +138,7 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp)
if (i == first_page) if (i == first_page)
{ {
bit = metap->LAST_FREED & (BMPGSZ_BIT(metap) - 1); bit = metap->hashm_lastfreed & (BMPGSZ_BIT(metap) - 1);
j = bit / BITS_PER_MAP; j = bit / BITS_PER_MAP;
bit = bit & ~(BITS_PER_MAP - 1); bit = bit & ~(BITS_PER_MAP - 1);
} }
...@@ -153,10 +153,10 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp) ...@@ -153,10 +153,10 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp)
} }
/* No Free Page Found - have to allocate a new page */ /* No Free Page Found - have to allocate a new page */
metap->LAST_FREED = metap->SPARES[splitnum]; metap->hashm_lastfreed = metap->hashm_spares[splitnum];
metap->SPARES[splitnum]++; metap->hashm_spares[splitnum]++;
offset = metap->SPARES[splitnum] - offset = metap->hashm_spares[splitnum] -
(splitnum ? metap->SPARES[splitnum - 1] : 0); (splitnum ? metap->hashm_spares[splitnum - 1] : 0);
#define OVMSG "HASH: Out of overflow pages. Out of luck.\n" #define OVMSG "HASH: Out of overflow pages. Out of luck.\n"
...@@ -164,9 +164,9 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp) ...@@ -164,9 +164,9 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp)
{ {
if (++splitnum >= NCACHED) if (++splitnum >= NCACHED)
elog(ERROR, OVMSG); elog(ERROR, OVMSG);
metap->OVFL_POINT = splitnum; metap->hashm_ovflpoint = splitnum;
metap->SPARES[splitnum] = metap->SPARES[splitnum - 1]; metap->hashm_spares[splitnum] = metap->hashm_spares[splitnum - 1];
metap->SPARES[splitnum - 1]--; metap->hashm_spares[splitnum - 1]--;
offset = 0; offset = 0;
} }
...@@ -194,15 +194,15 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp) ...@@ -194,15 +194,15 @@ _hash_getovfladdr(Relation rel, Buffer *metabufp)
if (_hash_initbitmap(rel, metap, OADDR_OF(splitnum, offset), if (_hash_initbitmap(rel, metap, OADDR_OF(splitnum, offset),
1, free_page)) 1, free_page))
elog(ERROR, "overflow_page: problem with _hash_initbitmap."); elog(ERROR, "overflow_page: problem with _hash_initbitmap.");
metap->SPARES[splitnum]++; metap->hashm_spares[splitnum]++;
offset++; offset++;
if (offset > SPLITMASK) if (offset > SPLITMASK)
{ {
if (++splitnum >= NCACHED) if (++splitnum >= NCACHED)
elog(ERROR, OVMSG); elog(ERROR, OVMSG);
metap->OVFL_POINT = splitnum; metap->hashm_ovflpoint = splitnum;
metap->SPARES[splitnum] = metap->SPARES[splitnum - 1]; metap->hashm_spares[splitnum] = metap->hashm_spares[splitnum - 1];
metap->SPARES[splitnum - 1]--; metap->hashm_spares[splitnum - 1]--;
offset = 0; offset = 0;
} }
} }
...@@ -235,13 +235,13 @@ found: ...@@ -235,13 +235,13 @@ found:
*/ */
bit = 1 + bit + (i * BMPGSZ_BIT(metap)); bit = 1 + bit + (i * BMPGSZ_BIT(metap));
if (bit >= metap->LAST_FREED) if (bit >= metap->hashm_lastfreed)
metap->LAST_FREED = bit - 1; metap->hashm_lastfreed = bit - 1;
/* Calculate the split number for this page */ /* Calculate the split number for this page */
for (i = 0; (i < splitnum) && (bit > metap->SPARES[i]); i++) for (i = 0; (i < splitnum) && (bit > metap->hashm_spares[i]); i++)
; ;
offset = (i ? bit - metap->SPARES[i - 1] : bit); offset = (i ? bit - metap->hashm_spares[i - 1] : bit);
if (offset >= SPLITMASK) if (offset >= SPLITMASK)
elog(ERROR, OVMSG); elog(ERROR, OVMSG);
...@@ -355,10 +355,10 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf) ...@@ -355,10 +355,10 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
* element hashm_mapp[bitmappage]. * element hashm_mapp[bitmappage].
*/ */
splitnum = (addr >> SPLITSHIFT); splitnum = (addr >> SPLITSHIFT);
ovflpgno = (splitnum ? metap->SPARES[splitnum - 1] : 0) + (addr & SPLITMASK) - 1; ovflpgno = (splitnum ? metap->hashm_spares[splitnum - 1] : 0) + (addr & SPLITMASK) - 1;
if (ovflpgno < metap->LAST_FREED) if (ovflpgno < metap->hashm_lastfreed)
metap->LAST_FREED = ovflpgno; metap->hashm_lastfreed = ovflpgno;
bitmappage = (ovflpgno >> (metap->hashm_bshift + BYTE_TO_BIT)); bitmappage = (ovflpgno >> (metap->hashm_bshift + BYTE_TO_BIT));
bitmapbit = ovflpgno & (BMPGSZ_BIT(metap) - 1); bitmapbit = ovflpgno & (BMPGSZ_BIT(metap) - 1);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.31 2001/06/27 23:31:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.32 2001/07/15 22:48:15 tgl Exp $
* *
* NOTES * NOTES
* Postgres hash pages look like ordinary relation pages. The opaque * Postgres hash pages look like ordinary relation pages. The opaque
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* address of the page if it is an overflow page. * address of the page if it is an overflow page.
* *
* The first page in a hash relation, page zero, is special -- it stores * The first page in a hash relation, page zero, is special -- it stores
* information describing the hash table; it is referred to as teh * information describing the hash table; it is referred to as the
* "meta page." Pages one and higher store the actual data. * "meta page." Pages one and higher store the actual data.
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
...@@ -48,6 +48,19 @@ static void _hash_splitpage(Relation rel, Buffer metabuf, Bucket obucket, Bucket ...@@ -48,6 +48,19 @@ static void _hash_splitpage(Relation rel, Buffer metabuf, Bucket obucket, Bucket
* before the lock table is fully initialized, so we can't use it. * before the lock table is fully initialized, so we can't use it.
* Strictly speaking, this violates 2pl, but we don't do 2pl on the * Strictly speaking, this violates 2pl, but we don't do 2pl on the
* system catalogs anyway. * system catalogs anyway.
*
* Note that our page locks are actual lockmanager locks, not buffer
* locks (as are used by btree, for example). This is a good idea because
* the algorithms are not deadlock-free, and we'd better be able to detect
* and recover from deadlocks.
*
* Another important difference from btree is that a hash indexscan
* retains both a lock and a buffer pin on the current index page
* between hashgettuple() calls (btree keeps only a buffer pin).
* Because of this, it's safe to do item deletions with only a regular
* write lock on a hash page --- there cannot be an indexscan stopped on
* the page being deleted, other than an indexscan of our own backend,
* which will be taken care of by _hash_adjscans.
*/ */
...@@ -350,6 +363,16 @@ _hash_unsetpagelock(Relation rel, ...@@ -350,6 +363,16 @@ _hash_unsetpagelock(Relation rel,
} }
} }
/*
* Delete a hash index item.
*
* It is safe to delete an item after acquiring a regular WRITE lock on
* the page, because no other backend can hold a READ lock on the page,
* and that means no other backend currently has an indexscan stopped on
* any item of the item being deleted. Our own backend might have such
* an indexscan (in fact *will*, since that's how VACUUM found the item
* in the first place), but _hash_adjscans will fix the scan position.
*/
void void
_hash_pagedel(Relation rel, ItemPointer tid) _hash_pagedel(Relation rel, ItemPointer tid)
{ {
...@@ -384,7 +407,7 @@ _hash_pagedel(Relation rel, ItemPointer tid) ...@@ -384,7 +407,7 @@ _hash_pagedel(Relation rel, ItemPointer tid)
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE); metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE);
metap = (HashMetaPage) BufferGetPage(metabuf); metap = (HashMetaPage) BufferGetPage(metabuf);
_hash_checkpage((Page) metap, LH_META_PAGE); _hash_checkpage((Page) metap, LH_META_PAGE);
++metap->hashm_nkeys; metap->hashm_nkeys--;
_hash_wrtbuf(rel, metabuf); _hash_wrtbuf(rel, metabuf);
} }
...@@ -402,32 +425,32 @@ _hash_expandtable(Relation rel, Buffer metabuf) ...@@ -402,32 +425,32 @@ _hash_expandtable(Relation rel, Buffer metabuf)
_hash_checkpage((Page) metap, LH_META_PAGE); _hash_checkpage((Page) metap, LH_META_PAGE);
metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE); metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE);
new_bucket = ++metap->MAX_BUCKET; new_bucket = ++metap->hashm_maxbucket;
metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ); metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ);
old_bucket = (metap->MAX_BUCKET & metap->LOW_MASK); old_bucket = (metap->hashm_maxbucket & metap->hashm_lowmask);
/* /*
* If the split point is increasing (MAX_BUCKET's log base 2 * * If the split point is increasing (hashm_maxbucket's log base 2 *
* increases), we need to copy the current contents of the spare split * increases), we need to copy the current contents of the spare split
* bucket to the next bucket. * bucket to the next bucket.
*/ */
spare_ndx = _hash_log2(metap->MAX_BUCKET + 1); spare_ndx = _hash_log2(metap->hashm_maxbucket + 1);
if (spare_ndx > metap->OVFL_POINT) if (spare_ndx > metap->hashm_ovflpoint)
{ {
metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE); metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE);
metap->SPARES[spare_ndx] = metap->SPARES[metap->OVFL_POINT]; metap->hashm_spares[spare_ndx] = metap->hashm_spares[metap->hashm_ovflpoint];
metap->OVFL_POINT = spare_ndx; metap->hashm_ovflpoint = spare_ndx;
metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ); metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ);
} }
if (new_bucket > metap->HIGH_MASK) if (new_bucket > metap->hashm_highmask)
{ {
/* Starting a new doubling */ /* Starting a new doubling */
metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE); metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_READ, HASH_WRITE);
metap->LOW_MASK = metap->HIGH_MASK; metap->hashm_lowmask = metap->hashm_highmask;
metap->HIGH_MASK = new_bucket | metap->LOW_MASK; metap->hashm_highmask = new_bucket | metap->hashm_lowmask;
metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ); metap = (HashMetaPage) _hash_chgbufaccess(rel, &metabuf, HASH_WRITE, HASH_READ);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashscan.c,v 1.24 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hashscan.c,v 1.25 2001/07/15 22:48:15 tgl Exp $
* *
* NOTES * NOTES
* Because we can be doing an index scan on a relation while we * Because we can be doing an index scan on a relation while we
...@@ -45,6 +45,31 @@ typedef HashScanListData *HashScanList; ...@@ -45,6 +45,31 @@ typedef HashScanListData *HashScanList;
static HashScanList HashScans = (HashScanList) NULL; static HashScanList HashScans = (HashScanList) NULL;
/*
* AtEOXact_hash() --- clean up hash subsystem at xact abort or commit.
*
* This is here because it needs to touch this module's static var HashScans.
*/
void
AtEOXact_hash(void)
{
/*
* Note: these actions should only be necessary during xact abort; but
* they can't hurt during a commit.
*/
/*
* Reset the active-scans list to empty. We do not need to free the
* list elements, because they're all palloc()'d, so they'll go away
* at end of transaction anyway.
*/
HashScans = NULL;
/* If we were building a hash, we ain't anymore. */
BuildingHash = false;
}
/* /*
* _Hash_regscan() -- register a new scan. * _Hash_regscan() -- register a new scan.
*/ */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.51 2001/06/22 19:16:21 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.52 2001/07/15 22:48:15 tgl Exp $
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
* index_open - open an index relation by relationId * index_open - open an index relation by relationId
...@@ -18,23 +18,17 @@ ...@@ -18,23 +18,17 @@
* index_rescan - restart a scan of an index * index_rescan - restart a scan of an index
* index_endscan - end a scan * index_endscan - end a scan
* index_insert - insert an index tuple into a relation * index_insert - insert an index tuple into a relation
* index_delete - delete an item from an index relation
* index_markpos - mark a scan position * index_markpos - mark a scan position
* index_restrpos - restore a scan position * index_restrpos - restore a scan position
* index_getnext - get the next tuple from a scan * index_getnext - get the next tuple from a scan
* ** index_fetch - retrieve tuple with tid * index_bulk_delete - bulk deletion of index tuples
* ** index_replace - replace a tuple * index_cost_estimator - fetch amcostestimate procedure OID
* ** index_getattr - get an attribute from an index tuple * index_getprocid - get a support procedure OID
* index_getprocid - get a support procedure id from the rel tuple
*
* IndexScanIsValid - check index scan
* *
* NOTES * NOTES
* This file contains the index_ routines which used * This file contains the index_ routines which used
* to be a scattered collection of stuff in access/genam. * to be a scattered collection of stuff in access/genam.
* *
* The ** routines: index_fetch, index_replace, and index_getattr
* have not yet been implemented. They may not be needed.
* *
* old comments * old comments
* Scans are implemented as follows: * Scans are implemented as follows:
...@@ -210,23 +204,6 @@ index_insert(Relation relation, ...@@ -210,23 +204,6 @@ index_insert(Relation relation,
return specificResult; return specificResult;
} }
/* ----------------
* index_delete - delete an item from an index relation
* ----------------
*/
void
index_delete(Relation relation, ItemPointer indexItem)
{
RegProcedure procedure;
RELATION_CHECKS;
GET_REL_PROCEDURE(delete, amdelete);
OidFunctionCall2(procedure,
PointerGetDatum(relation),
PointerGetDatum(indexItem));
}
/* ---------------- /* ----------------
* index_beginscan - start a scan of an index * index_beginscan - start a scan of an index
* ---------------- * ----------------
...@@ -378,6 +355,35 @@ index_getnext(IndexScanDesc scan, ...@@ -378,6 +355,35 @@ index_getnext(IndexScanDesc scan,
return result; return result;
} }
/* ----------------
* index_bulk_delete - do mass deletion of index entries
*
* callback routine tells whether a given main-heap tuple is
* to be deleted
*
* return value is an optional palloc'd struct of statistics
* ----------------
*/
IndexBulkDeleteResult *
index_bulk_delete(Relation relation,
IndexBulkDeleteCallback callback,
void *callback_state)
{
RegProcedure procedure;
IndexBulkDeleteResult *result;
RELATION_CHECKS;
GET_REL_PROCEDURE(bulk_delete, ambulkdelete);
result = (IndexBulkDeleteResult *)
DatumGetPointer(OidFunctionCall3(procedure,
PointerGetDatum(relation),
PointerGetDatum((Pointer) callback),
PointerGetDatum(callback_state)));
return result;
}
/* ---------------- /* ----------------
* index_cost_estimator * index_cost_estimator
* *
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for access/nbtree # Makefile for access/nbtree
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/access/nbtree/Makefile,v 1.10 2000/08/31 16:09:41 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/access/nbtree/Makefile,v 1.11 2001/07/15 22:48:16 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -12,7 +12,7 @@ subdir = src/backend/access/nbtree ...@@ -12,7 +12,7 @@ subdir = src/backend/access/nbtree
top_builddir = ../../../.. top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = nbtcompare.o nbtinsert.o nbtpage.o nbtree.o nbtscan.o nbtsearch.o \ OBJS = nbtcompare.o nbtinsert.o nbtpage.o nbtree.o nbtsearch.o \
nbtstrat.o nbtutils.o nbtsort.o nbtstrat.o nbtutils.o nbtsort.o
all: SUBSYS.o all: SUBSYS.o
......
$Header: /cvsroot/pgsql/src/backend/access/nbtree/README,v 1.4 2000/07/25 05:26:40 tgl Exp $ $Header: /cvsroot/pgsql/src/backend/access/nbtree/README,v 1.5 2001/07/15 22:48:16 tgl Exp $
This directory contains a correct implementation of Lehman and Yao's This directory contains a correct implementation of Lehman and Yao's
high-concurrency B-tree management algorithm (P. Lehman and S. Yao, high-concurrency B-tree management algorithm (P. Lehman and S. Yao,
...@@ -109,15 +109,11 @@ In addition, the following things are handy to know: ...@@ -109,15 +109,11 @@ In addition, the following things are handy to know:
is too high a price). Rebuilding corrupted indexes during restart is too high a price). Rebuilding corrupted indexes during restart
seems more attractive. seems more attractive.
+ On deletions, we need to adjust the position of active scans on + Deletions are handled by getting a super-exclusive lock on the target
the index. The code in nbtscan.c handles this. We don't need to page, so that no other backend has a pin on the page when the deletion
do this for insertions or splits because _bt_restscan can find the starts. This means no scan is pointing at the page. This is OK for
new position of the previously-found item. NOTE that nbtscan.c deleting leaf items, probably not OK for deleting internal nodes;
only copes with deletions issued by the current backend. This will need to think harder when it's time to support index compaction.
essentially means that concurrent deletions are not supported, but
that's true already in the Lehman and Yao algorithm. nbtscan.c
exists only to support VACUUM and allow it to delete items while
it's scanning the index.
+ "ScanKey" data structures are used in two fundamentally different ways + "ScanKey" data structures are used in two fundamentally different ways
in this code. Searches for the initial position for a scan, as well as in this code. Searches for the initial position for a scan, as well as
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.83 2001/06/22 19:16:21 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.84 2001/07/15 22:48:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -126,7 +126,7 @@ top: ...@@ -126,7 +126,7 @@ top:
if (TransactionIdIsValid(xwait)) if (TransactionIdIsValid(xwait))
{ {
/* Have to wait for the other guy ... */ /* Have to wait for the other guy ... */
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
XactLockTableWait(xwait); XactLockTableWait(xwait);
/* start over... */ /* start over... */
_bt_freestack(stack); _bt_freestack(stack);
...@@ -234,7 +234,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel, ...@@ -234,7 +234,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
if (TransactionIdIsValid(xwait)) if (TransactionIdIsValid(xwait))
{ {
if (nbuf != InvalidBuffer) if (nbuf != InvalidBuffer)
_bt_relbuf(rel, nbuf, BT_READ); _bt_relbuf(rel, nbuf);
/* Tell _bt_doinsert to wait... */ /* Tell _bt_doinsert to wait... */
return xwait; return xwait;
} }
...@@ -263,7 +263,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel, ...@@ -263,7 +263,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
break; break;
nblkno = opaque->btpo_next; nblkno = opaque->btpo_next;
if (nbuf != InvalidBuffer) if (nbuf != InvalidBuffer)
_bt_relbuf(rel, nbuf, BT_READ); _bt_relbuf(rel, nbuf);
nbuf = _bt_getbuf(rel, nblkno, BT_READ); nbuf = _bt_getbuf(rel, nblkno, BT_READ);
page = BufferGetPage(nbuf); page = BufferGetPage(nbuf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -273,7 +273,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel, ...@@ -273,7 +273,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
} }
if (nbuf != InvalidBuffer) if (nbuf != InvalidBuffer)
_bt_relbuf(rel, nbuf, BT_READ); _bt_relbuf(rel, nbuf);
return NullTransactionId; return NullTransactionId;
} }
...@@ -397,7 +397,7 @@ _bt_insertonpg(Relation rel, ...@@ -397,7 +397,7 @@ _bt_insertonpg(Relation rel,
/* step right one page */ /* step right one page */
BlockNumber rblkno = lpageop->btpo_next; BlockNumber rblkno = lpageop->btpo_next;
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
buf = _bt_getbuf(rel, rblkno, BT_WRITE); buf = _bt_getbuf(rel, rblkno, BT_WRITE);
page = BufferGetPage(buf); page = BufferGetPage(buf);
lpageop = (BTPageOpaque) PageGetSpecialPointer(page); lpageop = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -1175,12 +1175,12 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access) ...@@ -1175,12 +1175,12 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
*/ */
if (P_RIGHTMOST(opaque)) if (P_RIGHTMOST(opaque))
{ {
_bt_relbuf(rel, buf, access); _bt_relbuf(rel, buf);
return (InvalidBuffer); return (InvalidBuffer);
} }
blkno = opaque->btpo_next; blkno = opaque->btpo_next;
_bt_relbuf(rel, buf, access); _bt_relbuf(rel, buf);
buf = _bt_getbuf(rel, blkno, access); buf = _bt_getbuf(rel, blkno, access);
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -1449,7 +1449,7 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release) ...@@ -1449,7 +1449,7 @@ _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release)
&itup_off, &itup_blkno); &itup_off, &itup_blkno);
/* Keep lock on new "root" buffer ! */ /* Keep lock on new "root" buffer ! */
if (buf != rootbuf) if (buf != rootbuf)
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
buf = newbuf; buf = newbuf;
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -1525,7 +1525,7 @@ _bt_fixtree(Relation rel, BlockNumber blkno) ...@@ -1525,7 +1525,7 @@ _bt_fixtree(Relation rel, BlockNumber blkno)
if (P_ISROOT(opaque)) if (P_ISROOT(opaque))
{ {
/* Tree is Ok now */ /* Tree is Ok now */
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
return; return;
} }
/* Call _bt_fixroot() if there is no upper level */ /* Call _bt_fixroot() if there is no upper level */
...@@ -1533,12 +1533,12 @@ _bt_fixtree(Relation rel, BlockNumber blkno) ...@@ -1533,12 +1533,12 @@ _bt_fixtree(Relation rel, BlockNumber blkno)
{ {
elog(NOTICE, "bt_fixtree[%s]: fixing root page", RelationGetRelationName(rel)); elog(NOTICE, "bt_fixtree[%s]: fixing root page", RelationGetRelationName(rel));
buf = _bt_fixroot(rel, buf, true); buf = _bt_fixroot(rel, buf, true);
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
return; return;
} }
/* Have to go up one level */ /* Have to go up one level */
pblkno = opaque->btpo_parent; pblkno = opaque->btpo_parent;
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
} }
blkno = pblkno; blkno = pblkno;
} }
...@@ -1571,7 +1571,7 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit) ...@@ -1571,7 +1571,7 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
page = BufferGetPage(buf); page = BufferGetPage(buf);
/* copy page to temp storage */ /* copy page to temp storage */
memmove(tbuf, page, PageGetPageSize(page)); memmove(tbuf, page, PageGetPageSize(page));
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
page = (Page) tbuf; page = (Page) tbuf;
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -1682,7 +1682,7 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit) ...@@ -1682,7 +1682,7 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
{ {
if (coff[i] != P_FIRSTDATAKEY(newopaque)) if (coff[i] != P_FIRSTDATAKEY(newopaque))
elog(ERROR, "bt_fixlevel[%s]: invalid item order(3) (need to recreate index)", RelationGetRelationName(rel)); elog(ERROR, "bt_fixlevel[%s]: invalid item order(3) (need to recreate index)", RelationGetRelationName(rel));
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
buf = newbuf; buf = newbuf;
page = newpage; page = newpage;
opaque = newopaque; opaque = newopaque;
...@@ -1691,7 +1691,7 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit) ...@@ -1691,7 +1691,7 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
continue; continue;
} }
/* unfound - need to insert on current page */ /* unfound - need to insert on current page */
_bt_relbuf(rel, newbuf, BT_WRITE); _bt_relbuf(rel, newbuf);
} }
/* insert pointer */ /* insert pointer */
ritem = (BTItem) PageGetItem(cpage[i - 1], ritem = (BTItem) PageGetItem(cpage[i - 1],
...@@ -1718,10 +1718,10 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit) ...@@ -1718,10 +1718,10 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
&itup_off, &itup_blkno); &itup_off, &itup_blkno);
/* what buffer we need in ? */ /* what buffer we need in ? */
if (newitemonleft) if (newitemonleft)
_bt_relbuf(rel, newbuf, BT_WRITE); _bt_relbuf(rel, newbuf);
else else
{ {
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
buf = newbuf; buf = newbuf;
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -1741,7 +1741,7 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit) ...@@ -1741,7 +1741,7 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
/* copy page with pointer to cblkno[cidx] to temp storage */ /* copy page with pointer to cblkno[cidx] to temp storage */
memmove(tbuf, page, PageGetPageSize(page)); memmove(tbuf, page, PageGetPageSize(page));
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
page = (Page) tbuf; page = (Page) tbuf;
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
} }
...@@ -1751,13 +1751,13 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit) ...@@ -1751,13 +1751,13 @@ _bt_fixlevel(Relation rel, Buffer buf, BlockNumber limit)
goodbye = false; goodbye = false;
/* Pointers to child pages are Ok - right end of child level ? */ /* Pointers to child pages are Ok - right end of child level ? */
_bt_relbuf(rel, cbuf[0], BT_READ); _bt_relbuf(rel, cbuf[0]);
_bt_relbuf(rel, cbuf[1], BT_READ); _bt_relbuf(rel, cbuf[1]);
if (cidx == 1 || if (cidx == 1 ||
(cidx == 2 && (P_RIGHTMOST(copaque[2]) || goodbye))) (cidx == 2 && (P_RIGHTMOST(copaque[2]) || goodbye)))
{ {
if (cidx == 2) if (cidx == 2)
_bt_relbuf(rel, cbuf[2], BT_READ); _bt_relbuf(rel, cbuf[2]);
return; return;
} }
if (cblkno[0] == limit || cblkno[1] == limit) if (cblkno[0] == limit || cblkno[1] == limit)
...@@ -1819,7 +1819,7 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno, ...@@ -1819,7 +1819,7 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno,
{ {
if (offnum <= stack.bts_offset) if (offnum <= stack.bts_offset)
elog(ERROR, "bt_fixbranch[%s]: invalid item order (need to recreate index)", RelationGetRelationName(rel)); elog(ERROR, "bt_fixbranch[%s]: invalid item order (need to recreate index)", RelationGetRelationName(rel));
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
return; return;
} }
...@@ -1837,7 +1837,7 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno, ...@@ -1837,7 +1837,7 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno,
if (rbuf == InvalidBuffer) if (rbuf == InvalidBuffer)
elog(ERROR, "bt_fixbranch[%s]: right pointer unfound(2) (need to recreate index)", RelationGetRelationName(rel)); elog(ERROR, "bt_fixbranch[%s]: right pointer unfound(2) (need to recreate index)", RelationGetRelationName(rel));
rblkno = BufferGetBlockNumber(rbuf); rblkno = BufferGetBlockNumber(rbuf);
_bt_relbuf(rel, rbuf, BT_READ); _bt_relbuf(rel, rbuf);
/* /*
* If we have parent item in true_stack then go up one level and * If we have parent item in true_stack then go up one level and
...@@ -1845,7 +1845,7 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno, ...@@ -1845,7 +1845,7 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno,
*/ */
if (true_stack) if (true_stack)
{ {
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
blkno = true_stack->bts_blkno; blkno = true_stack->bts_blkno;
true_stack = true_stack->bts_parent; true_stack = true_stack->bts_parent;
continue; continue;
...@@ -1860,19 +1860,19 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno, ...@@ -1860,19 +1860,19 @@ _bt_fixbranch(Relation rel, BlockNumber lblkno,
if (!BTreeInvalidParent(opaque)) if (!BTreeInvalidParent(opaque))
{ {
blkno = opaque->btpo_parent; blkno = opaque->btpo_parent;
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
continue; continue;
} }
/* Have to switch to excl buf lock and re-check btpo_parent */ /* Have to switch to excl buf lock and re-check btpo_parent */
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
buf = _bt_getbuf(rel, blkno, BT_WRITE); buf = _bt_getbuf(rel, blkno, BT_WRITE);
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (!BTreeInvalidParent(opaque)) if (!BTreeInvalidParent(opaque))
{ {
blkno = opaque->btpo_parent; blkno = opaque->btpo_parent;
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
continue; continue;
} }
...@@ -1913,7 +1913,7 @@ _bt_fixup(Relation rel, Buffer buf) ...@@ -1913,7 +1913,7 @@ _bt_fixup(Relation rel, Buffer buf)
if (!BTreeInvalidParent(opaque)) if (!BTreeInvalidParent(opaque))
{ {
blkno = opaque->btpo_parent; blkno = opaque->btpo_parent;
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
elog(NOTICE, "bt_fixup[%s]: checking/fixing upper levels", RelationGetRelationName(rel)); elog(NOTICE, "bt_fixup[%s]: checking/fixing upper levels", RelationGetRelationName(rel));
_bt_fixtree(rel, blkno); _bt_fixtree(rel, blkno);
return; return;
...@@ -1921,8 +1921,7 @@ _bt_fixup(Relation rel, Buffer buf) ...@@ -1921,8 +1921,7 @@ _bt_fixup(Relation rel, Buffer buf)
if (P_LEFTMOST(opaque)) if (P_LEFTMOST(opaque))
break; break;
blkno = opaque->btpo_prev; blkno = opaque->btpo_prev;
LockBuffer(buf, BUFFER_LOCK_UNLOCK); _bt_relbuf(rel, buf);
ReleaseBuffer(buf);
buf = _bt_getbuf(rel, blkno, BT_WRITE); buf = _bt_getbuf(rel, blkno, BT_WRITE);
} }
...@@ -1932,9 +1931,7 @@ _bt_fixup(Relation rel, Buffer buf) ...@@ -1932,9 +1931,7 @@ _bt_fixup(Relation rel, Buffer buf)
*/ */
elog(NOTICE, "bt_fixup[%s]: fixing root page", RelationGetRelationName(rel)); elog(NOTICE, "bt_fixup[%s]: fixing root page", RelationGetRelationName(rel));
buf = _bt_fixroot(rel, buf, true); buf = _bt_fixroot(rel, buf, true);
_bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, buf);
return;
} }
static OffsetNumber static OffsetNumber
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.52 2001/06/27 23:31:38 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.53 2001/07/15 22:48:16 tgl Exp $
* *
* NOTES * NOTES
* Postgres btree pages look like ordinary relation pages. The opaque * Postgres btree pages look like ordinary relation pages. The opaque
...@@ -138,7 +138,7 @@ _bt_getroot(Relation rel, int access) ...@@ -138,7 +138,7 @@ _bt_getroot(Relation rel, int access)
/* If access = BT_READ, caller doesn't want us to create root yet */ /* If access = BT_READ, caller doesn't want us to create root yet */
if (access == BT_READ) if (access == BT_READ)
{ {
_bt_relbuf(rel, metabuf, BT_READ); _bt_relbuf(rel, metabuf);
return InvalidBuffer; return InvalidBuffer;
} }
...@@ -215,14 +215,14 @@ _bt_getroot(Relation rel, int access) ...@@ -215,14 +215,14 @@ _bt_getroot(Relation rel, int access)
* guarantee no deadlocks, we have to release the metadata * guarantee no deadlocks, we have to release the metadata
* page and start all over again. * page and start all over again.
*/ */
_bt_relbuf(rel, metabuf, BT_WRITE); _bt_relbuf(rel, metabuf);
return _bt_getroot(rel, access); return _bt_getroot(rel, access);
} }
} }
else else
{ {
rootblkno = metad->btm_root; rootblkno = metad->btm_root;
_bt_relbuf(rel, metabuf, BT_READ); /* done with the meta page */ _bt_relbuf(rel, metabuf); /* done with the meta page */
rootbuf = _bt_getbuf(rel, rootblkno, BT_READ); rootbuf = _bt_getbuf(rel, rootblkno, BT_READ);
} }
...@@ -270,8 +270,8 @@ _bt_getroot(Relation rel, int access) ...@@ -270,8 +270,8 @@ _bt_getroot(Relation rel, int access)
goto check_parent; goto check_parent;
} }
else else
/* someone else already fixed root */
{ {
/* someone else already fixed root */
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK); LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
LockBuffer(rootbuf, BT_READ); LockBuffer(rootbuf, BT_READ);
} }
...@@ -283,7 +283,7 @@ _bt_getroot(Relation rel, int access) ...@@ -283,7 +283,7 @@ _bt_getroot(Relation rel, int access)
* chance that parent is root page. * chance that parent is root page.
*/ */
newrootbuf = _bt_getbuf(rel, rootopaque->btpo_parent, BT_READ); newrootbuf = _bt_getbuf(rel, rootopaque->btpo_parent, BT_READ);
_bt_relbuf(rel, rootbuf, BT_READ); _bt_relbuf(rel, rootbuf);
rootbuf = newrootbuf; rootbuf = newrootbuf;
rootpage = BufferGetPage(rootbuf); rootpage = BufferGetPage(rootbuf);
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage); rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
...@@ -293,7 +293,7 @@ _bt_getroot(Relation rel, int access) ...@@ -293,7 +293,7 @@ _bt_getroot(Relation rel, int access)
} }
/* try again */ /* try again */
_bt_relbuf(rel, rootbuf, BT_READ); _bt_relbuf(rel, rootbuf);
return _bt_getroot(rel, access); return _bt_getroot(rel, access);
} }
...@@ -350,10 +350,12 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access) ...@@ -350,10 +350,12 @@ _bt_getbuf(Relation rel, BlockNumber blkno, int access)
/* /*
* _bt_relbuf() -- release a locked buffer. * _bt_relbuf() -- release a locked buffer.
* *
* Lock and pin (refcount) are both dropped. * Lock and pin (refcount) are both dropped. Note that either read or
* write lock can be dropped this way, but if we modified the buffer,
* this is NOT the right way to release a write lock.
*/ */
void void
_bt_relbuf(Relation rel, Buffer buf, int access) _bt_relbuf(Relation rel, Buffer buf)
{ {
LockBuffer(buf, BUFFER_LOCK_UNLOCK); LockBuffer(buf, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buf); ReleaseBuffer(buf);
...@@ -449,24 +451,23 @@ _bt_metaproot(Relation rel, BlockNumber rootbknum, int level) ...@@ -449,24 +451,23 @@ _bt_metaproot(Relation rel, BlockNumber rootbknum, int level)
} }
/* /*
* Delete an item from a btree. It had better be a leaf item... * Delete an item from a btree page.
*
* This routine assumes that the caller has pinned and locked the buffer,
* and will write the buffer afterwards.
*/ */
void void
_bt_pagedel(Relation rel, ItemPointer tid) _bt_itemdel(Relation rel, Buffer buf, ItemPointer tid)
{ {
Buffer buf; Page page = BufferGetPage(buf);
Page page;
BlockNumber blkno;
OffsetNumber offno; OffsetNumber offno;
blkno = ItemPointerGetBlockNumber(tid);
offno = ItemPointerGetOffsetNumber(tid); offno = ItemPointerGetOffsetNumber(tid);
buf = _bt_getbuf(rel, blkno, BT_WRITE);
page = BufferGetPage(buf);
START_CRIT_SECTION(); START_CRIT_SECTION();
PageIndexTupleDelete(page, offno); PageIndexTupleDelete(page, offno);
/* XLOG stuff */ /* XLOG stuff */
{ {
xl_btree_delete xlrec; xl_btree_delete xlrec;
...@@ -490,8 +491,6 @@ _bt_pagedel(Relation rel, ItemPointer tid) ...@@ -490,8 +491,6 @@ _bt_pagedel(Relation rel, ItemPointer tid)
PageSetLSN(page, recptr); PageSetLSN(page, recptr);
PageSetSUI(page, ThisStartUpID); PageSetSUI(page, ThisStartUpID);
} }
END_CRIT_SECTION();
/* write the buffer and release the lock */ END_CRIT_SECTION();
_bt_wrtbuf(rel, buf);
} }
This diff is collapsed.
/*-------------------------------------------------------------------------
*
* btscan.c
* manage scans on btrees.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/Attic/nbtscan.c,v 1.33 2001/01/24 19:42:48 momjian Exp $
*
*
* NOTES
* Because we can be doing an index scan on a relation while we update
* it, we need to avoid missing data that moves around in the index.
* Insertions and page splits are no problem because _bt_restscan()
* can figure out where the current item moved to, but if a deletion
* happens at or before the current scan position, we'd better do
* something to stay in sync.
*
* The routines in this file handle the problem for deletions issued
* by the current backend. Currently, that's all we need, since
* deletions are only done by VACUUM and it gets an exclusive lock.
*
* The scheme is to manage a list of active scans in the current backend.
* Whenever we remove a record from an index, we check the list of active
* scans to see if any has been affected. A scan is affected only if it
* is on the same relation, and the same page, as the update.
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/nbtree.h"
typedef struct BTScanListData
{
IndexScanDesc btsl_scan;
struct BTScanListData *btsl_next;
} BTScanListData;
typedef BTScanListData *BTScanList;
static BTScanList BTScans = (BTScanList) NULL;
static void _bt_scandel(IndexScanDesc scan, BlockNumber blkno, OffsetNumber offno);
/*
* AtEOXact_nbtree() --- clean up nbtree subsystem at xact abort or commit.
*
* This is here because it needs to touch this module's static var BTScans.
*/
void
AtEOXact_nbtree(void)
{
/*
* Note: these actions should only be necessary during xact abort; but
* they can't hurt during a commit.
*/
/*
* Reset the active-scans list to empty. We do not need to free the
* list elements, because they're all palloc()'d, so they'll go away
* at end of transaction anyway.
*/
BTScans = NULL;
/* If we were building a btree, we ain't anymore. */
BuildingBtree = false;
}
/*
* _bt_regscan() -- register a new scan.
*/
void
_bt_regscan(IndexScanDesc scan)
{
BTScanList new_el;
new_el = (BTScanList) palloc(sizeof(BTScanListData));
new_el->btsl_scan = scan;
new_el->btsl_next = BTScans;
BTScans = new_el;
}
/*
* _bt_dropscan() -- drop a scan from the scan list
*/
void
_bt_dropscan(IndexScanDesc scan)
{
BTScanList chk,
last;
last = (BTScanList) NULL;
for (chk = BTScans;
chk != (BTScanList) NULL && chk->btsl_scan != scan;
chk = chk->btsl_next)
last = chk;
if (chk == (BTScanList) NULL)
elog(ERROR, "btree scan list trashed; can't find 0x%p", (void *) scan);
if (last == (BTScanList) NULL)
BTScans = chk->btsl_next;
else
last->btsl_next = chk->btsl_next;
pfree(chk);
}
/*
* _bt_adjscans() -- adjust all scans in the scan list to compensate
* for a given deletion
*/
void
_bt_adjscans(Relation rel, ItemPointer tid)
{
BTScanList l;
Oid relid;
relid = RelationGetRelid(rel);
for (l = BTScans; l != (BTScanList) NULL; l = l->btsl_next)
{
if (relid == RelationGetRelid(l->btsl_scan->relation))
_bt_scandel(l->btsl_scan,
ItemPointerGetBlockNumber(tid),
ItemPointerGetOffsetNumber(tid));
}
}
/*
* _bt_scandel() -- adjust a single scan on deletion
*
*/
static void
_bt_scandel(IndexScanDesc scan, BlockNumber blkno, OffsetNumber offno)
{
ItemPointer current;
Buffer buf;
BTScanOpaque so;
OffsetNumber start;
Page page;
BTPageOpaque opaque;
so = (BTScanOpaque) scan->opaque;
buf = so->btso_curbuf;
current = &(scan->currentItemData);
if (ItemPointerIsValid(current)
&& ItemPointerGetBlockNumber(current) == blkno
&& ItemPointerGetOffsetNumber(current) >= offno)
{
page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
start = P_FIRSTDATAKEY(opaque);
if (ItemPointerGetOffsetNumber(current) == start)
ItemPointerSetInvalid(&(so->curHeapIptr));
else
{
/*
* We have to lock buffer before _bt_step and unlock it after
* that.
*/
LockBuffer(buf, BT_READ);
_bt_step(scan, &buf, BackwardScanDirection);
if (ItemPointerIsValid(current))
{
Page pg = BufferGetPage(buf);
BTItem btitem = (BTItem) PageGetItem(pg,
PageGetItemId(pg, ItemPointerGetOffsetNumber(current)));
so->curHeapIptr = btitem->bti_itup.t_tid;
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
}
}
}
current = &(scan->currentMarkData);
if (ItemPointerIsValid(current)
&& ItemPointerGetBlockNumber(current) == blkno
&& ItemPointerGetOffsetNumber(current) >= offno)
{
page = BufferGetPage(so->btso_mrkbuf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
start = P_FIRSTDATAKEY(opaque);
if (ItemPointerGetOffsetNumber(current) == start)
ItemPointerSetInvalid(&(so->mrkHeapIptr));
else
{
ItemPointerData tmp;
tmp = *current;
*current = scan->currentItemData;
scan->currentItemData = tmp;
so->btso_curbuf = so->btso_mrkbuf;
so->btso_mrkbuf = buf;
buf = so->btso_curbuf;
LockBuffer(buf, BT_READ); /* as above */
_bt_step(scan, &buf, BackwardScanDirection);
so->btso_curbuf = so->btso_mrkbuf;
so->btso_mrkbuf = buf;
tmp = *current;
*current = scan->currentItemData;
scan->currentItemData = tmp;
if (ItemPointerIsValid(current))
{
Page pg = BufferGetPage(buf);
BTItem btitem = (BTItem) PageGetItem(pg,
PageGetItemId(pg, ItemPointerGetOffsetNumber(current)));
so->mrkHeapIptr = btitem->bti_itup.t_tid;
LockBuffer(buf, BUFFER_LOCK_UNLOCK); /* as above */
}
}
}
}
...@@ -8,7 +8,7 @@ ...@@ -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
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.66 2001/03/23 04:49:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.67 2001/07/15 22:48:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -94,7 +94,7 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, ...@@ -94,7 +94,7 @@ _bt_search(Relation rel, int keysz, ScanKey scankey,
new_stack->bts_parent = stack_in; new_stack->bts_parent = stack_in;
/* drop the read lock on the parent page, acquire one on the child */ /* drop the read lock on the parent page, acquire one on the child */
_bt_relbuf(rel, *bufP, BT_READ); _bt_relbuf(rel, *bufP);
*bufP = _bt_getbuf(rel, blkno, BT_READ); *bufP = _bt_getbuf(rel, blkno, BT_READ);
/* /*
...@@ -155,7 +155,7 @@ _bt_moveright(Relation rel, ...@@ -155,7 +155,7 @@ _bt_moveright(Relation rel,
/* step right one page */ /* step right one page */
BlockNumber rblkno = opaque->btpo_next; BlockNumber rblkno = opaque->btpo_next;
_bt_relbuf(rel, buf, access); _bt_relbuf(rel, buf);
buf = _bt_getbuf(rel, rblkno, access); buf = _bt_getbuf(rel, rblkno, access);
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -406,7 +406,7 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) ...@@ -406,7 +406,7 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
/* No more items, so close down the current-item info */ /* No more items, so close down the current-item info */
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
so->btso_curbuf = InvalidBuffer; so->btso_curbuf = InvalidBuffer;
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
return (RetrieveIndexResult) NULL; return (RetrieveIndexResult) NULL;
} }
...@@ -760,7 +760,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) ...@@ -760,7 +760,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
nomatches: nomatches:
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
so->btso_curbuf = InvalidBuffer; so->btso_curbuf = InvalidBuffer;
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
res = (RetrieveIndexResult) NULL; res = (RetrieveIndexResult) NULL;
} }
...@@ -815,14 +815,14 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) ...@@ -815,14 +815,14 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
/* if we're at end of scan, release the buffer and return */ /* if we're at end of scan, release the buffer and return */
if (P_RIGHTMOST(opaque)) if (P_RIGHTMOST(opaque))
{ {
_bt_relbuf(rel, *bufP, BT_READ); _bt_relbuf(rel, *bufP);
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
*bufP = so->btso_curbuf = InvalidBuffer; *bufP = so->btso_curbuf = InvalidBuffer;
return false; return false;
} }
/* step right one page */ /* step right one page */
blkno = opaque->btpo_next; blkno = opaque->btpo_next;
_bt_relbuf(rel, *bufP, BT_READ); _bt_relbuf(rel, *bufP);
*bufP = _bt_getbuf(rel, blkno, BT_READ); *bufP = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(*bufP); page = BufferGetPage(*bufP);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -846,7 +846,7 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) ...@@ -846,7 +846,7 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
/* if we're at end of scan, release the buffer and return */ /* if we're at end of scan, release the buffer and return */
if (P_LEFTMOST(opaque)) if (P_LEFTMOST(opaque))
{ {
_bt_relbuf(rel, *bufP, BT_READ); _bt_relbuf(rel, *bufP);
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
*bufP = so->btso_curbuf = InvalidBuffer; *bufP = so->btso_curbuf = InvalidBuffer;
return false; return false;
...@@ -854,7 +854,7 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) ...@@ -854,7 +854,7 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
/* step left */ /* step left */
obknum = BufferGetBlockNumber(*bufP); obknum = BufferGetBlockNumber(*bufP);
blkno = opaque->btpo_prev; blkno = opaque->btpo_prev;
_bt_relbuf(rel, *bufP, BT_READ); _bt_relbuf(rel, *bufP);
*bufP = _bt_getbuf(rel, blkno, BT_READ); *bufP = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(*bufP); page = BufferGetPage(*bufP);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -868,7 +868,7 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) ...@@ -868,7 +868,7 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
while (opaque->btpo_next != obknum) while (opaque->btpo_next != obknum)
{ {
blkno = opaque->btpo_next; blkno = opaque->btpo_next;
_bt_relbuf(rel, *bufP, BT_READ); _bt_relbuf(rel, *bufP);
*bufP = _bt_getbuf(rel, blkno, BT_READ); *bufP = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(*bufP); page = BufferGetPage(*bufP);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -952,7 +952,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) ...@@ -952,7 +952,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
itup = &(btitem->bti_itup); itup = &(btitem->bti_itup);
blkno = ItemPointerGetBlockNumber(&(itup->t_tid)); blkno = ItemPointerGetBlockNumber(&(itup->t_tid));
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
buf = _bt_getbuf(rel, blkno, BT_READ); buf = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(buf); page = BufferGetPage(buf);
...@@ -968,7 +968,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) ...@@ -968,7 +968,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
do do
{ {
blkno = opaque->btpo_next; blkno = opaque->btpo_next;
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
buf = _bt_getbuf(rel, blkno, BT_READ); buf = _bt_getbuf(rel, blkno, BT_READ);
page = BufferGetPage(buf); page = BufferGetPage(buf);
opaque = (BTPageOpaque) PageGetSpecialPointer(page); opaque = (BTPageOpaque) PageGetSpecialPointer(page);
...@@ -1035,7 +1035,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) ...@@ -1035,7 +1035,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
/* no tuples in the index match this scan key */ /* no tuples in the index match this scan key */
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
so->btso_curbuf = InvalidBuffer; so->btso_curbuf = InvalidBuffer;
_bt_relbuf(rel, buf, BT_READ); _bt_relbuf(rel, buf);
res = (RetrieveIndexResult) NULL; res = (RetrieveIndexResult) NULL;
} }
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.37 2001/06/09 18:16:56 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.38 2001/07/15 22:48:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -60,13 +60,8 @@ rtbeginscan(PG_FUNCTION_ARGS) ...@@ -60,13 +60,8 @@ rtbeginscan(PG_FUNCTION_ARGS)
ScanKey key = (ScanKey) PG_GETARG_POINTER(3); ScanKey key = (ScanKey) PG_GETARG_POINTER(3);
IndexScanDesc s; IndexScanDesc s;
/*
* Let index_beginscan does its work...
*
* RelationSetLockForRead(r);
*/
s = RelationGetIndexScan(r, fromEnd, nkeys, key); s = RelationGetIndexScan(r, fromEnd, nkeys, key);
rtregscan(s); rtregscan(s);
PG_RETURN_POINTER(s); PG_RETURN_POINTER(s);
...@@ -282,6 +277,27 @@ rtdropscan(IndexScanDesc s) ...@@ -282,6 +277,27 @@ rtdropscan(IndexScanDesc s)
pfree(l); pfree(l);
} }
/*
* AtEOXact_rtree() --- clean up rtree subsystem at xact abort or commit.
*
* This is here because it needs to touch this module's static var RTScans.
*/
void
AtEOXact_rtree(void)
{
/*
* Note: these actions should only be necessary during xact abort; but
* they can't hurt during a commit.
*/
/*
* Reset the active-scans list to empty. We do not need to free the
* list elements, because they're all palloc()'d, so they'll go away
* at end of transaction anyway.
*/
RTScans = NULL;
}
void void
rtadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum) rtadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.106 2001/07/12 04:11:13 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.107 2001/07/15 22:48:16 tgl Exp $
* *
* NOTES * NOTES
* Transaction aborts can now occur two ways: * Transaction aborts can now occur two ways:
...@@ -156,7 +156,10 @@ ...@@ -156,7 +156,10 @@
#include <sys/time.h> #include <sys/time.h>
#include "access/gistscan.h"
#include "access/hash.h"
#include "access/nbtree.h" #include "access/nbtree.h"
#include "access/rtree.h"
#include "access/xact.h" #include "access/xact.h"
#include "catalog/heap.h" #include "catalog/heap.h"
#include "catalog/index.h" #include "catalog/index.h"
...@@ -1040,7 +1043,10 @@ CommitTransaction(void) ...@@ -1040,7 +1043,10 @@ CommitTransaction(void)
smgrDoPendingDeletes(true); smgrDoPendingDeletes(true);
AtEOXact_SPI(); AtEOXact_SPI();
AtEOXact_gist();
AtEOXact_hash();
AtEOXact_nbtree(); AtEOXact_nbtree();
AtEOXact_rtree();
AtCommit_Cache(); AtCommit_Cache();
AtCommit_Locks(); AtCommit_Locks();
AtEOXact_CatCache(true); AtEOXact_CatCache(true);
...@@ -1147,7 +1153,10 @@ AbortTransaction(void) ...@@ -1147,7 +1153,10 @@ AbortTransaction(void)
smgrDoPendingDeletes(false); smgrDoPendingDeletes(false);
AtEOXact_SPI(); AtEOXact_SPI();
AtEOXact_gist();
AtEOXact_hash();
AtEOXact_nbtree(); AtEOXact_nbtree();
AtEOXact_rtree();
AtAbort_Cache(); AtAbort_Cache();
AtEOXact_CatCache(false); AtEOXact_CatCache(false);
AtAbort_Memory(); AtAbort_Memory();
......
...@@ -8,7 +8,7 @@ ...@@ -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
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.110 2001/06/25 23:03:03 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.111 2001/07/15 22:48:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1119,7 +1119,7 @@ build_indices() ...@@ -1119,7 +1119,7 @@ build_indices()
heap = heap_openr(ILHead->il_heap, NoLock); heap = heap_openr(ILHead->il_heap, NoLock);
ind = index_openr(ILHead->il_ind); ind = index_openr(ILHead->il_ind);
index_build(heap, ind, ILHead->il_info, NULL); index_build(heap, ind, ILHead->il_info);
/* /*
* In normal processing mode, index_build would close the heap and * In normal processing mode, index_build would close the heap and
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.170 2001/06/29 21:08:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.171 2001/07/15 22:48:17 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -1031,7 +1031,7 @@ RelationTruncateIndexes(Oid heapId) ...@@ -1031,7 +1031,7 @@ RelationTruncateIndexes(Oid heapId)
/* Initialize the index and rebuild */ /* Initialize the index and rebuild */
InitIndexStrategy(indexInfo->ii_NumIndexAttrs, InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
currentIndex, accessMethodId); currentIndex, accessMethodId);
index_build(heapRelation, currentIndex, indexInfo, NULL); index_build(heapRelation, currentIndex, indexInfo);
/* /*
* index_build will close both the heap and index relations (but * index_build will close both the heap and index relations (but
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.59 2001/06/01 02:41:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.60 2001/07/15 22:48:17 tgl Exp $
* *
* NOTES * NOTES
* these routines moved here from commands/define.c and somewhat cleaned up. * these routines moved here from commands/define.c and somewhat cleaned up.
...@@ -402,7 +402,7 @@ OperatorShellMake(char *operatorName, ...@@ -402,7 +402,7 @@ OperatorShellMake(char *operatorName,
* rightSortObjectId -- same as for commutatorObjectId * rightSortObjectId -- same as for commutatorObjectId
* operatorProcedure -- must access the pg_procedure catalog to get the * operatorProcedure -- must access the pg_procedure catalog to get the
* ObjectId of the procedure that actually does the operator * ObjectId of the procedure that actually does the operator
* actions this is required. Do an amgetattr to find out the * actions this is required. Do a lookup to find out the
* return type of the procedure * return type of the procedure
* restrictionProcedure -- must access the pg_procedure catalog to get * restrictionProcedure -- must access the pg_procedure catalog to get
* the ObjectId but this is optional * the ObjectId but this is optional
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.134 2001/06/14 01:09:22 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.135 2001/07/15 22:48:17 tgl Exp $
* *
* NOTES * NOTES
* The PerformAddAttribute() code, like most of the relation * The PerformAddAttribute() code, like most of the relation
...@@ -269,7 +269,7 @@ PerformPortalClose(char *name, CommandDest dest) ...@@ -269,7 +269,7 @@ PerformPortalClose(char *name, CommandDest dest)
* Initial idea of ordering the tuple attributes so that all * Initial idea of ordering the tuple attributes so that all
* the variable length domains occured last was scratched. Doing * the variable length domains occured last was scratched. Doing
* so would not speed access too much (in general) and would create * so would not speed access too much (in general) and would create
* many complications in formtuple, amgetattr, and addattribute. * many complications in formtuple, heap_getattr, and addattribute.
* *
* scan attribute catalog for name conflict (within rel) * scan attribute catalog for name conflict (within rel)
* scan type catalog for absence of data type (if not arg) * scan type catalog for absence of data type (if not arg)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.50 2001/06/13 21:44:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.51 2001/07/15 22:48:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -83,6 +83,8 @@ DefineIndex(char *heapRelationName, ...@@ -83,6 +83,8 @@ DefineIndex(char *heapRelationName,
Oid *classObjectId; Oid *classObjectId;
Oid accessMethodId; Oid accessMethodId;
Oid relationId; Oid relationId;
HeapTuple tuple;
Form_pg_am accessMethodForm;
IndexInfo *indexInfo; IndexInfo *indexInfo;
int numberOfAttributes; int numberOfAttributes;
List *cnfPred = NIL; List *cnfPred = NIL;
...@@ -107,27 +109,25 @@ DefineIndex(char *heapRelationName, ...@@ -107,27 +109,25 @@ DefineIndex(char *heapRelationName,
heapRelationName); heapRelationName);
/* /*
* compute access method id * look up the access method, verify it can handle the requested features
*/ */
accessMethodId = GetSysCacheOid(AMNAME, tuple = SearchSysCache(AMNAME,
PointerGetDatum(accessMethodName), PointerGetDatum(accessMethodName),
0, 0, 0); 0, 0, 0);
if (!OidIsValid(accessMethodId)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "DefineIndex: access method \"%s\" not found", elog(ERROR, "DefineIndex: access method \"%s\" not found",
accessMethodName); accessMethodName);
accessMethodId = tuple->t_data->t_oid;
accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
/* if (unique && ! accessMethodForm->amcanunique)
* XXX Hardwired hacks to check for limitations on supported index elog(ERROR, "DefineIndex: access method \"%s\" does not support UNIQUE indexes",
* types. We really ought to be learning this info from entries in the accessMethodName);
* pg_am table, instead of having it wired-in here! if (numberOfAttributes > 1 && ! accessMethodForm->amcanmulticol)
*/ elog(ERROR, "DefineIndex: access method \"%s\" does not support multi-column indexes",
if (unique && accessMethodId != BTREE_AM_OID) accessMethodName);
elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
if (numberOfAttributes > 1 && ReleaseSysCache(tuple);
!( accessMethodId == BTREE_AM_OID ||
accessMethodId == GIST_AM_OID))
elog(ERROR, "DefineIndex: multi-column indices are only available with the btree or GiST access methods");
/* /*
* WITH clause reinstated to handle lossy indices. -- JMH, 7/22/96 * WITH clause reinstated to handle lossy indices. -- JMH, 7/22/96
...@@ -298,7 +298,15 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) ...@@ -298,7 +298,15 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
InitIndexStrategy(indexInfo->ii_NumIndexAttrs, InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
indexRelation, accessMethodId); indexRelation, accessMethodId);
index_build(heapRelation, indexRelation, indexInfo, oldPred); /*
* XXX currently BROKEN: if we want to support EXTEND INDEX, oldPred
* needs to be passed through to IndexBuildHeapScan. We could do this
* without help from the index AMs if we added an oldPred field to the
* IndexInfo struct. Currently I'm expecting that EXTEND INDEX will
* get removed, so I'm not going to do that --- tgl 7/14/01
*/
index_build(heapRelation, indexRelation, indexInfo);
/* heap and index rels are closed as a side-effect of index_build */ /* heap and index rels are closed as a side-effect of index_build */
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.204 2001/07/13 22:55:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.205 2001/07/15 22:48:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -128,7 +128,7 @@ static void vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage); ...@@ -128,7 +128,7 @@ static void vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage);
static void vacuum_index(VacPageList vacpagelist, Relation indrel, 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 VacPage tid_reaped(ItemPointer itemptr, VacPageList vacpagelist); static bool 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);
...@@ -542,17 +542,11 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -542,17 +542,11 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
/* /*
* Do the actual work --- either FULL or "lazy" vacuum * Do the actual work --- either FULL or "lazy" vacuum
*
* XXX for the moment, lazy vac not supported unless CONCURRENT_VACUUM
*/ */
#ifdef CONCURRENT_VACUUM
if (vacstmt->full) if (vacstmt->full)
full_vacuum_rel(onerel); full_vacuum_rel(onerel);
else else
lazy_vacuum_rel(onerel, vacstmt); lazy_vacuum_rel(onerel, vacstmt);
#else
full_vacuum_rel(onerel);
#endif
/* all done with this class, but hold lock until commit */ /* all done with this class, but hold lock until commit */
heap_close(onerel, NoLock); heap_close(onerel, NoLock);
...@@ -1049,7 +1043,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel, ...@@ -1049,7 +1043,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
elog(MESSAGE_LEVEL, "Pages %u: Changed %u, reaped %u, Empty %u, New %u; \ elog(MESSAGE_LEVEL, "Pages %u: Changed %u, reaped %u, Empty %u, New %u; \
Tup %.0f: Vac %.0f, Keep/VTL %.0f/%u, UnUsed %.0f, MinLen %lu, MaxLen %lu; \ Tup %.0f: Vac %.0f, Keep/VTL %.0f/%u, UnUsed %.0f, MinLen %lu, MaxLen %lu; \
Re-using: Free/Avail. Space %.0f/%.0f; EndEmpty/Avail. Pages %u/%u. %s", Re-using: Free/Avail. Space %.0f/%.0f; EndEmpty/Avail. Pages %u/%u.\n\t%s",
nblocks, changed_pages, vacuum_pages->num_pages, empty_pages, nblocks, changed_pages, vacuum_pages->num_pages, empty_pages,
new_pages, num_tuples, tups_vacuumed, new_pages, num_tuples, tups_vacuumed,
nkeep, vacrelstats->num_vtlinks, nkeep, vacrelstats->num_vtlinks,
...@@ -1965,7 +1959,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, ...@@ -1965,7 +1959,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
} }
Assert(num_moved == checked_moved); Assert(num_moved == checked_moved);
elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u; Tuple(s) moved: %u. %s", elog(MESSAGE_LEVEL, "Rel %s: Pages: %u --> %u; Tuple(s) moved: %u.\n\t%s",
RelationGetRelationName(onerel), RelationGetRelationName(onerel),
nblocks, blkno, num_moved, nblocks, blkno, num_moved,
vac_show_rusage(&ru0)); vac_show_rusage(&ru0));
...@@ -2213,7 +2207,7 @@ scan_index(Relation indrel, double num_tuples) ...@@ -2213,7 +2207,7 @@ scan_index(Relation indrel, double num_tuples)
nipages = RelationGetNumberOfBlocks(indrel); nipages = RelationGetNumberOfBlocks(indrel);
vac_update_relstats(RelationGetRelid(indrel), nipages, nitups, false); vac_update_relstats(RelationGetRelid(indrel), nipages, nitups, false);
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f. %s", elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f.\n\t%s",
RelationGetRelationName(indrel), nipages, nitups, RelationGetRelationName(indrel), nipages, nitups,
vac_show_rusage(&ru0)); vac_show_rusage(&ru0));
...@@ -2247,85 +2241,55 @@ static void ...@@ -2247,85 +2241,55 @@ static void
vacuum_index(VacPageList vacpagelist, Relation indrel, vacuum_index(VacPageList vacpagelist, Relation indrel,
double num_tuples, int keep_tuples) double num_tuples, int keep_tuples)
{ {
RetrieveIndexResult res; IndexBulkDeleteResult *stats;
IndexScanDesc iscan;
ItemPointer heapptr;
int tups_vacuumed;
BlockNumber num_pages;
double num_index_tuples;
VacPage vp;
VacRUsage ru0; VacRUsage ru0;
vac_init_rusage(&ru0); vac_init_rusage(&ru0);
/* walk through the entire index */ /* Do bulk deletion */
iscan = index_beginscan(indrel, false, 0, (ScanKey) NULL); stats = index_bulk_delete(indrel, tid_reaped, (void *) vacpagelist);
tups_vacuumed = 0;
num_index_tuples = 0;
while ((res = index_getnext(iscan, ForwardScanDirection))
!= (RetrieveIndexResult) NULL)
{
heapptr = &res->heap_iptr;
if ((vp = tid_reaped(heapptr, vacpagelist)) != (VacPage) NULL)
{
#ifdef NOT_USED
elog(DEBUG, "<%x,%x> -> <%x,%x>",
ItemPointerGetBlockNumber(&(res->index_iptr)),
ItemPointerGetOffsetNumber(&(res->index_iptr)),
ItemPointerGetBlockNumber(&(res->heap_iptr)),
ItemPointerGetOffsetNumber(&(res->heap_iptr)));
#endif
if (vp->offsets_free == 0)
{
elog(NOTICE, "Index %s: pointer to EmptyPage (blk %u off %u) - fixing",
RelationGetRelationName(indrel),
vp->blkno, ItemPointerGetOffsetNumber(heapptr));
}
++tups_vacuumed;
index_delete(indrel, &res->index_iptr);
}
else
num_index_tuples += 1;
pfree(res);
}
index_endscan(iscan); if (!stats)
return;
/* now update statistics in pg_class */ /* now update statistics in pg_class */
num_pages = RelationGetNumberOfBlocks(indrel);
vac_update_relstats(RelationGetRelid(indrel), vac_update_relstats(RelationGetRelid(indrel),
num_pages, num_index_tuples, false); stats->num_pages, stats->num_index_tuples,
false);
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f: Deleted %u. %s", elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f: Deleted %.0f.\n\t%s",
RelationGetRelationName(indrel), num_pages, RelationGetRelationName(indrel), stats->num_pages,
num_index_tuples - keep_tuples, tups_vacuumed, stats->num_index_tuples - keep_tuples, stats->tuples_removed,
vac_show_rusage(&ru0)); vac_show_rusage(&ru0));
/* /*
* Check for tuple count mismatch. If the index is partial, then * 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. * it's OK for it to have fewer tuples than the heap; else we got trouble.
*/ */
if (num_index_tuples != num_tuples + keep_tuples) if (stats->num_index_tuples != num_tuples + keep_tuples)
{ {
if (num_index_tuples > num_tuples + keep_tuples || if (stats->num_index_tuples > num_tuples + keep_tuples ||
! is_partial_index(indrel)) ! is_partial_index(indrel))
elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\ elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\
\n\tRecreate the index.", \n\tRecreate the index.",
RelationGetRelationName(indrel), num_index_tuples, num_tuples); RelationGetRelationName(indrel),
stats->num_index_tuples, num_tuples);
} }
pfree(stats);
} }
/* /*
* tid_reaped() -- is a particular tid reaped? * tid_reaped() -- is a particular tid reaped?
* *
* This has the right signature to be an IndexBulkDeleteCallback.
*
* vacpagelist->VacPage_array is sorted in right order. * vacpagelist->VacPage_array is sorted in right order.
*/ */
static VacPage static bool
tid_reaped(ItemPointer itemptr, VacPageList vacpagelist) tid_reaped(ItemPointer itemptr, void *state)
{ {
VacPageList vacpagelist = (VacPageList) state;
OffsetNumber ioffno; OffsetNumber ioffno;
OffsetNumber *voff; OffsetNumber *voff;
VacPage vp, VacPage vp,
...@@ -2342,8 +2306,8 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist) ...@@ -2342,8 +2306,8 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist)
sizeof(VacPage), sizeof(VacPage),
vac_cmp_blk); vac_cmp_blk);
if (vpp == (VacPage *) NULL) if (vpp == NULL)
return (VacPage) NULL; return false;
/* ok - we are on a partially or fully reaped page */ /* ok - we are on a partially or fully reaped page */
vp = *vpp; vp = *vpp;
...@@ -2351,7 +2315,7 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist) ...@@ -2351,7 +2315,7 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist)
if (vp->offsets_free == 0) if (vp->offsets_free == 0)
{ {
/* this is EmptyPage, so claim all tuples on it are reaped!!! */ /* this is EmptyPage, so claim all tuples on it are reaped!!! */
return vp; return true;
} }
voff = (OffsetNumber *) vac_bsearch((void *) &ioffno, voff = (OffsetNumber *) vac_bsearch((void *) &ioffno,
...@@ -2360,11 +2324,11 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist) ...@@ -2360,11 +2324,11 @@ tid_reaped(ItemPointer itemptr, VacPageList vacpagelist)
sizeof(OffsetNumber), sizeof(OffsetNumber),
vac_cmp_offno); vac_cmp_offno);
if (voff == (OffsetNumber *) NULL) if (voff == NULL)
return (VacPage) NULL; return false;
/* tid is reaped */ /* tid is reaped */
return vp; return true;
} }
/* /*
...@@ -2595,6 +2559,13 @@ is_partial_index(Relation indrel) ...@@ -2595,6 +2559,13 @@ is_partial_index(Relation indrel)
HeapTuple cachetuple; HeapTuple cachetuple;
Form_pg_index indexStruct; Form_pg_index indexStruct;
/*
* If the index's AM doesn't support nulls, it's partial for our purposes
*/
if (! indrel->rd_am->amindexnulls)
return true;
/* Otherwise, look to see if there's a partial-index predicate */
cachetuple = SearchSysCache(INDEXRELID, cachetuple = SearchSysCache(INDEXRELID,
ObjectIdGetDatum(RelationGetRelid(indrel)), ObjectIdGetDatum(RelationGetRelid(indrel)),
0, 0, 0); 0, 0, 0);
...@@ -2603,7 +2574,7 @@ is_partial_index(Relation indrel) ...@@ -2603,7 +2574,7 @@ is_partial_index(Relation indrel)
RelationGetRelid(indrel)); RelationGetRelid(indrel));
indexStruct = (Form_pg_index) GETSTRUCT(cachetuple); indexStruct = (Form_pg_index) GETSTRUCT(cachetuple);
result = (VARSIZE(&indexStruct->indpred) != 0); result = (VARSIZE(&indexStruct->indpred) > VARHDRSZ);
ReleaseSysCache(cachetuple); ReleaseSysCache(cachetuple);
return result; return result;
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.1 2001/07/13 22:55:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.2 2001/07/15 22:48:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -112,7 +112,7 @@ static void lazy_record_dead_tuple(LVRelStats *vacrelstats, ...@@ -112,7 +112,7 @@ static void lazy_record_dead_tuple(LVRelStats *vacrelstats,
ItemPointer itemptr); ItemPointer itemptr);
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, LVRelStats *vacrelstats); static bool lazy_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);
...@@ -371,11 +371,11 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, ...@@ -371,11 +371,11 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
if (pgchanged) if (pgchanged)
{ {
WriteBuffer(buf); SetBufferCommitInfoNeedsSave(buf);
changed_pages++; changed_pages++;
} }
else
ReleaseBuffer(buf); ReleaseBuffer(buf);
} }
/* If any tuples need to be deleted, perform final vacuum cycle */ /* If any tuples need to be deleted, perform final vacuum cycle */
...@@ -507,64 +507,40 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer, ...@@ -507,64 +507,40 @@ lazy_vacuum_page(Relation onerel, BlockNumber blkno, Buffer buffer,
static void static void
lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats) lazy_vacuum_index(Relation indrel, LVRelStats *vacrelstats)
{ {
RetrieveIndexResult res; IndexBulkDeleteResult *stats;
IndexScanDesc iscan;
int tups_vacuumed;
BlockNumber num_pages;
double num_index_tuples;
VacRUsage ru0; VacRUsage ru0;
vac_init_rusage(&ru0); vac_init_rusage(&ru0);
/* /*
* Only btree and hash indexes are currently safe for concurrent access; * If index is unsafe for concurrent access, must lock it.
* see notes in ExecOpenIndices(). XXX should rely on index AM for this
*/ */
if (indrel->rd_rel->relam != BTREE_AM_OID && if (! indrel->rd_am->amconcurrent)
indrel->rd_rel->relam != HASH_AM_OID)
LockRelation(indrel, AccessExclusiveLock); LockRelation(indrel, AccessExclusiveLock);
/* XXX should use a bulk-delete call here */ /* Do bulk deletion */
stats = index_bulk_delete(indrel, lazy_tid_reaped, (void *) vacrelstats);
/* walk through the entire index */
iscan = index_beginscan(indrel, false, 0, (ScanKey) NULL);
tups_vacuumed = 0;
num_index_tuples = 0;
while ((res = index_getnext(iscan, ForwardScanDirection))
!= (RetrieveIndexResult) NULL)
{
ItemPointer heapptr = &res->heap_iptr;
if (lazy_tid_reaped(heapptr, vacrelstats))
{
index_delete(indrel, &res->index_iptr);
++tups_vacuumed;
}
else
num_index_tuples += 1;
pfree(res);
}
index_endscan(iscan);
/* now update statistics in pg_class */
num_pages = RelationGetNumberOfBlocks(indrel);
vac_update_relstats(RelationGetRelid(indrel),
num_pages, num_index_tuples, false);
/* /*
* Release lock acquired above. * Release lock acquired above.
*/ */
if (indrel->rd_rel->relam != BTREE_AM_OID && if (! indrel->rd_am->amconcurrent)
indrel->rd_rel->relam != HASH_AM_OID)
UnlockRelation(indrel, AccessExclusiveLock); UnlockRelation(indrel, AccessExclusiveLock);
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f: Deleted %u.\n\t%s", /* now update statistics in pg_class */
RelationGetRelationName(indrel), num_pages, if (stats)
num_index_tuples, tups_vacuumed, {
vac_show_rusage(&ru0)); vac_update_relstats(RelationGetRelid(indrel),
stats->num_pages, stats->num_index_tuples,
false);
elog(MESSAGE_LEVEL, "Index %s: Pages %u; Tuples %.0f: Deleted %.0f.\n\t%s",
RelationGetRelationName(indrel), stats->num_pages,
stats->num_index_tuples, stats->tuples_removed,
vac_show_rusage(&ru0));
pfree(stats);
}
} }
/* /*
...@@ -960,11 +936,14 @@ lazy_record_free_space(LVRelStats *vacrelstats, ...@@ -960,11 +936,14 @@ lazy_record_free_space(LVRelStats *vacrelstats,
/* /*
* lazy_tid_reaped() -- is a particular tid deletable? * lazy_tid_reaped() -- is a particular tid deletable?
* *
* This has the right signature to be an IndexBulkDeleteCallback.
*
* Assumes dead_tuples array is in sorted order. * Assumes dead_tuples array is in sorted order.
*/ */
static bool static bool
lazy_tid_reaped(ItemPointer itemptr, LVRelStats *vacrelstats) lazy_tid_reaped(ItemPointer itemptr, void *state)
{ {
LVRelStats *vacrelstats = (LVRelStats *) state;
ItemPointer res; ItemPointer res;
res = (ItemPointer) bsearch((void *) itemptr, res = (ItemPointer) bsearch((void *) itemptr,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.75 2001/03/22 06:16:12 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.76 2001/07/15 22:48:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -504,25 +504,26 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo) ...@@ -504,25 +504,26 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
/* /*
* Open (and lock, if necessary) the index relation * Open (and lock, if necessary) the index relation
* *
* Hack for not btree and hash indices: they use relation level * If the index AM is not safe for concurrent updates, obtain
* exclusive locking on update (i.e. - they are not ready for * an exclusive lock on the index to lock out other updaters as
* MVCC) and so we have to exclusively lock indices here to * well as readers (index_beginscan places AccessShareLock).
* prevent deadlocks if we will scan them - index_beginscan places * We will release this lock in ExecCloseIndices.
* AccessShareLock, indices update methods don't use locks at all.
* We release this lock in ExecCloseIndices. Note, that hashes use
* page level locking - i.e. are not deadlock-free - let's them be
* on their way -:)) vadim 03-12-1998
* *
* If there are multiple not-btree-or-hash indices, all backends must * If the index AM supports concurrent updates, we obtain no lock
* lock the indices in the same order or we will get deadlocks * here at all, which is a tad weird, but safe since any critical
* here during concurrent updates. This is now guaranteed by * operation on the index (like deleting it) will acquire exclusive
* lock on the parent table. Perhaps someday we should acquire
* RowExclusiveLock on the index here?
*
* If there are multiple not-concurrent-safe indexes, all backends
* must lock the indexes in the same order or we will get deadlocks
* here during concurrent updates. This is guaranteed by
* RelationGetIndexList(), which promises to return the index list * RelationGetIndexList(), which promises to return the index list
* in OID order. tgl 06-19-2000 * in OID order.
*/ */
indexDesc = index_open(indexOid); indexDesc = index_open(indexOid);
if (indexDesc->rd_rel->relam != BTREE_AM_OID && if (! indexDesc->rd_am->amconcurrent)
indexDesc->rd_rel->relam != HASH_AM_OID)
LockRelation(indexDesc, AccessExclusiveLock); LockRelation(indexDesc, AccessExclusiveLock);
/* /*
...@@ -560,24 +561,21 @@ ExecCloseIndices(ResultRelInfo *resultRelInfo) ...@@ -560,24 +561,21 @@ ExecCloseIndices(ResultRelInfo *resultRelInfo)
{ {
int i; int i;
int numIndices; int numIndices;
RelationPtr relationDescs; RelationPtr indexDescs;
numIndices = resultRelInfo->ri_NumIndices; numIndices = resultRelInfo->ri_NumIndices;
relationDescs = resultRelInfo->ri_IndexRelationDescs; indexDescs = resultRelInfo->ri_IndexRelationDescs;
for (i = 0; i < numIndices; i++) for (i = 0; i < numIndices; i++)
{ {
if (relationDescs[i] == NULL) if (indexDescs[i] == NULL)
continue; continue;
/* /* Drop lock, if one was acquired by ExecOpenIndices */
* See notes in ExecOpenIndices. if (! indexDescs[i]->rd_am->amconcurrent)
*/ UnlockRelation(indexDescs[i], AccessExclusiveLock);
if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID &&
relationDescs[i]->rd_rel->relam != HASH_AM_OID)
UnlockRelation(relationDescs[i], AccessExclusiveLock);
index_close(relationDescs[i]); index_close(indexDescs[i]);
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.61 2001/06/22 19:16:22 wieck Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.62 2001/07/15 22:48:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -993,7 +993,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -993,7 +993,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
ExecOpenScanR(reloid, /* relation */ ExecOpenScanR(reloid, /* relation */
0, /* nkeys */ 0, /* nkeys */
(ScanKey) NULL, /* scan key */ (ScanKey) NULL, /* scan key */
0, /* is index */ false, /* is index */
direction, /* scan direction */ direction, /* scan direction */
estate->es_snapshot, /* */ estate->es_snapshot, /* */
&currentRelation, /* return: rel desc */ &currentRelation, /* return: rel desc */
...@@ -1023,7 +1023,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -1023,7 +1023,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
ExecOpenScanR(indexOid, /* relation */ ExecOpenScanR(indexOid, /* relation */
numScanKeys[i], /* nkeys */ numScanKeys[i], /* nkeys */
scanKeys[i], /* scan key */ scanKeys[i], /* scan key */
true, /* is index */ true, /* is index */
direction, /* scan direction */ direction, /* scan direction */
estate->es_snapshot, estate->es_snapshot,
&(relationDescs[i]), /* return: rel desc */ &(relationDescs[i]), /* return: rel desc */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.30 2001/05/27 20:42:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.31 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -166,7 +166,7 @@ InitScanRelation(SeqScan *node, EState *estate, ...@@ -166,7 +166,7 @@ InitScanRelation(SeqScan *node, EState *estate,
ExecOpenScanR(reloid, /* relation */ ExecOpenScanR(reloid, /* relation */
0, /* nkeys */ 0, /* nkeys */
NULL, /* scan key */ NULL, /* scan key */
0, /* is index */ false, /* is index */
direction, /* scan direction */ direction, /* scan direction */
estate->es_snapshot, estate->es_snapshot,
&currentRelation, /* return: rel desc */ &currentRelation, /* return: rel desc */
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.66 2001/05/20 20:28:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.67 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -126,7 +126,7 @@ find_secondary_indexes(Oid relationObjectId) ...@@ -126,7 +126,7 @@ find_secondary_indexes(Oid relationObjectId)
/* Extract info from the pg_index tuple */ /* Extract info from the pg_index tuple */
info->indexoid = index->indexrelid; info->indexoid = index->indexrelid;
info->indproc = index->indproc; /* functional index ?? */ info->indproc = index->indproc; /* functional index ?? */
if (VARSIZE(&index->indpred) != 0) /* partial index ?? */ if (VARSIZE(&index->indpred) > VARHDRSZ) /* partial index ?? */
{ {
char *predString; char *predString;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datum.c,v 1.20 2001/03/22 03:59:50 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datum.c,v 1.21 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -118,7 +118,7 @@ datumCopy(Datum value, bool typByVal, int typLen) ...@@ -118,7 +118,7 @@ datumCopy(Datum value, bool typByVal, int typLen)
* *
* Free the space occupied by a datum CREATED BY "datumCopy" * Free the space occupied by a datum CREATED BY "datumCopy"
* *
* NOTE: DO NOT USE THIS ROUTINE with datums returned by amgetattr() etc. * NOTE: DO NOT USE THIS ROUTINE with datums returned by heap_getattr() etc.
* ONLY datums created by "datumCopy" can be freed! * ONLY datums created by "datumCopy" can be freed!
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
# Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group # Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California # Portions Copyright (c) 1994, Regents of the University of California
# #
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.129 2001/06/23 23:29:48 petere Exp $ # $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.130 2001/07/15 22:48:18 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -813,7 +813,7 @@ echo "UPDATE pg_database SET \ ...@@ -813,7 +813,7 @@ echo "UPDATE pg_database SET \
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
echo "Vacuuming database." echo "Vacuuming database."
echo "VACUUM ANALYZE" \ echo "VACUUM FULL ANALYZE" \
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
echo "Copying template1 to template0." echo "Copying template1 to template0."
...@@ -824,7 +824,7 @@ echo "UPDATE pg_database SET \ ...@@ -824,7 +824,7 @@ echo "UPDATE pg_database SET \
datallowconn = 'f' \ datallowconn = 'f' \
WHERE datname = 'template0'" \ WHERE datname = 'template0'" \
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
echo "VACUUM pg_database" \ echo "VACUUM FULL pg_database" \
| "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: genam.h,v 1.25 2001/01/24 19:43:19 momjian Exp $ * $Id: genam.h,v 1.26 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,8 +18,21 @@ ...@@ -18,8 +18,21 @@
#include "access/relscan.h" #include "access/relscan.h"
#include "access/sdir.h" #include "access/sdir.h"
/* Struct for statistics returned by bulk-delete operation */
typedef struct IndexBulkDeleteResult
{
BlockNumber num_pages; /* pages remaining in index */
double tuples_removed; /* # removed by bulk-delete operation */
double num_index_tuples; /* # remaining */
} IndexBulkDeleteResult;
/* Typedef for callback function to determine if a tuple is bulk-deletable */
typedef bool (*IndexBulkDeleteCallback) (ItemPointer itemptr, void *state);
/* ---------------- /* ----------------
* generalized index_ interface routines * generalized index_ interface routines (in indexam.c)
* ---------------- * ----------------
*/ */
extern Relation index_open(Oid relationId); extern Relation index_open(Oid relationId);
...@@ -29,7 +42,6 @@ extern InsertIndexResult index_insert(Relation relation, ...@@ -29,7 +42,6 @@ extern InsertIndexResult index_insert(Relation relation,
Datum *datum, char *nulls, Datum *datum, char *nulls,
ItemPointer heap_t_ctid, ItemPointer heap_t_ctid,
Relation heapRel); Relation heapRel);
extern void index_delete(Relation relation, ItemPointer indexItem);
extern IndexScanDesc index_beginscan(Relation relation, bool scanFromEnd, extern IndexScanDesc index_beginscan(Relation relation, bool scanFromEnd,
uint16 numberOfKeys, ScanKey key); uint16 numberOfKeys, ScanKey key);
extern void index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key); extern void index_rescan(IndexScanDesc scan, bool scanFromEnd, ScanKey key);
...@@ -38,6 +50,9 @@ extern void index_markpos(IndexScanDesc scan); ...@@ -38,6 +50,9 @@ extern void index_markpos(IndexScanDesc scan);
extern void index_restrpos(IndexScanDesc scan); extern void index_restrpos(IndexScanDesc scan);
extern RetrieveIndexResult index_getnext(IndexScanDesc scan, extern RetrieveIndexResult index_getnext(IndexScanDesc scan,
ScanDirection direction); ScanDirection direction);
extern IndexBulkDeleteResult *index_bulk_delete(Relation relation,
IndexBulkDeleteCallback callback,
void *callback_state);
extern RegProcedure index_cost_estimator(Relation relation); extern RegProcedure index_cost_estimator(Relation relation);
extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
uint16 procnum); uint16 procnum);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: gist.h,v 1.28 2001/05/31 18:16:55 tgl Exp $ * $Id: gist.h,v 1.29 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -162,7 +162,7 @@ typedef struct GISTENTRY ...@@ -162,7 +162,7 @@ typedef struct GISTENTRY
/* gist.c */ /* gist.c */
extern Datum gistbuild(PG_FUNCTION_ARGS); extern Datum gistbuild(PG_FUNCTION_ARGS);
extern Datum gistinsert(PG_FUNCTION_ARGS); extern Datum gistinsert(PG_FUNCTION_ARGS);
extern Datum gistdelete(PG_FUNCTION_ARGS); extern Datum gistbulkdelete(PG_FUNCTION_ARGS);
extern void _gistdump(Relation r); extern void _gistdump(Relation r);
extern void gistfreestack(GISTSTACK *s); extern void gistfreestack(GISTSTACK *s);
extern void initGISTstate(GISTSTATE *giststate, Relation index); extern void initGISTstate(GISTSTATE *giststate, Relation index);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: gistscan.h,v 1.15 2001/05/30 19:53:39 tgl Exp $ * $Id: gistscan.h,v 1.16 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -22,5 +22,6 @@ extern Datum gistmarkpos(PG_FUNCTION_ARGS); ...@@ -22,5 +22,6 @@ extern Datum gistmarkpos(PG_FUNCTION_ARGS);
extern Datum gistrestrpos(PG_FUNCTION_ARGS); extern Datum gistrestrpos(PG_FUNCTION_ARGS);
extern Datum gistendscan(PG_FUNCTION_ARGS); extern Datum gistendscan(PG_FUNCTION_ARGS);
extern void gistadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum); extern void gistadjscans(Relation r, int op, BlockNumber blkno, OffsetNumber offnum);
extern void AtEOXact_gist(void);
#endif /* GISTSCAN_H */ #endif /* GISTSCAN_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: hash.h,v 1.38 2001/03/22 04:00:27 momjian Exp $ * $Id: hash.h,v 1.39 2001/07/15 22:48:18 tgl Exp $
* *
* NOTES * NOTES
* modeled after Margo Seltzer's hash implementation for unix. * modeled after Margo Seltzer's hash implementation for unix.
...@@ -55,7 +55,7 @@ typedef uint32 PageOffset; ...@@ -55,7 +55,7 @@ typedef uint32 PageOffset;
#define OADDR_OF(S,O) ((OverflowPageAddress)((uint32)((uint32)(S) << SPLITSHIFT) + (O))) #define OADDR_OF(S,O) ((OverflowPageAddress)((uint32)((uint32)(S) << SPLITSHIFT) + (O)))
#define BUCKET_TO_BLKNO(B) \ #define BUCKET_TO_BLKNO(B) \
((Bucket) ((B) + ((B) ? metap->SPARES[_hash_log2((B)+1)-1] : 0)) + 1) ((Bucket) ((B) + ((B) ? metap->hashm_spares[_hash_log2((B)+1)-1] : 0)) + 1)
#define OADDR_TO_BLKNO(B) \ #define OADDR_TO_BLKNO(B) \
((BlockNumber) \ ((BlockNumber) \
(BUCKET_TO_BLKNO ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)))); (BUCKET_TO_BLKNO ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B))));
...@@ -165,16 +165,6 @@ typedef struct HashMetaPageData ...@@ -165,16 +165,6 @@ typedef struct HashMetaPageData
typedef HashMetaPageData *HashMetaPage; typedef HashMetaPageData *HashMetaPage;
/* Short hands for accessing structure */
#define OVFL_POINT hashm_ovflpoint
#define LAST_FREED hashm_lastfreed
#define MAX_BUCKET hashm_maxbucket
#define FFACTOR hashm_ffactor
#define HIGH_MASK hashm_highmask
#define LOW_MASK hashm_lowmask
#define NKEYS hashm_nkeys
#define SPARES hashm_spares
extern bool BuildingHash; extern bool BuildingHash;
typedef struct HashItemData typedef struct HashItemData
...@@ -256,7 +246,7 @@ extern Datum hashrescan(PG_FUNCTION_ARGS); ...@@ -256,7 +246,7 @@ extern Datum hashrescan(PG_FUNCTION_ARGS);
extern Datum hashendscan(PG_FUNCTION_ARGS); 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 hashdelete(PG_FUNCTION_ARGS); extern Datum hashbulkdelete(PG_FUNCTION_ARGS);
/* /*
* Datatype-specific hash functions in hashfunc.c. * Datatype-specific hash functions in hashfunc.c.
...@@ -310,6 +300,7 @@ extern void _hash_expandtable(Relation rel, Buffer metabuf); ...@@ -310,6 +300,7 @@ extern void _hash_expandtable(Relation rel, Buffer metabuf);
extern void _hash_regscan(IndexScanDesc scan); extern void _hash_regscan(IndexScanDesc scan);
extern void _hash_dropscan(IndexScanDesc scan); extern void _hash_dropscan(IndexScanDesc scan);
extern void _hash_adjscans(Relation rel, ItemPointer tid); extern void _hash_adjscans(Relation rel, ItemPointer tid);
extern void AtEOXact_hash(void);
/* hashsearch.c */ /* hashsearch.c */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: nbtree.h,v 1.55 2001/03/22 04:00:29 momjian Exp $ * $Id: nbtree.h,v 1.56 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -319,6 +319,8 @@ typedef struct xl_btree_newroot ...@@ -319,6 +319,8 @@ typedef struct xl_btree_newroot
*/ */
extern bool BuildingBtree; /* in nbtree.c */ extern bool BuildingBtree; /* in nbtree.c */
extern void AtEOXact_nbtree(void);
extern Datum btbuild(PG_FUNCTION_ARGS); extern Datum btbuild(PG_FUNCTION_ARGS);
extern Datum btinsert(PG_FUNCTION_ARGS); extern Datum btinsert(PG_FUNCTION_ARGS);
extern Datum btgettuple(PG_FUNCTION_ARGS); extern Datum btgettuple(PG_FUNCTION_ARGS);
...@@ -328,7 +330,7 @@ extern void btmovescan(IndexScanDesc scan, Datum v); ...@@ -328,7 +330,7 @@ extern void btmovescan(IndexScanDesc scan, Datum v);
extern Datum btendscan(PG_FUNCTION_ARGS); extern Datum btendscan(PG_FUNCTION_ARGS);
extern Datum btmarkpos(PG_FUNCTION_ARGS); extern Datum btmarkpos(PG_FUNCTION_ARGS);
extern Datum btrestrpos(PG_FUNCTION_ARGS); extern Datum btrestrpos(PG_FUNCTION_ARGS);
extern Datum btdelete(PG_FUNCTION_ARGS); extern Datum btbulkdelete(PG_FUNCTION_ARGS);
extern void btree_redo(XLogRecPtr lsn, XLogRecord *record); extern void btree_redo(XLogRecPtr lsn, XLogRecord *record);
extern void btree_undo(XLogRecPtr lsn, XLogRecord *record); extern void btree_undo(XLogRecPtr lsn, XLogRecord *record);
...@@ -346,20 +348,12 @@ extern InsertIndexResult _bt_doinsert(Relation rel, BTItem btitem, ...@@ -346,20 +348,12 @@ extern InsertIndexResult _bt_doinsert(Relation rel, BTItem btitem,
extern void _bt_metapinit(Relation rel); extern void _bt_metapinit(Relation rel);
extern Buffer _bt_getroot(Relation rel, int access); extern Buffer _bt_getroot(Relation rel, int access);
extern Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access); extern Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access);
extern void _bt_relbuf(Relation rel, Buffer buf, int access); extern void _bt_relbuf(Relation rel, Buffer buf);
extern void _bt_wrtbuf(Relation rel, Buffer buf); extern void _bt_wrtbuf(Relation rel, Buffer buf);
extern void _bt_wrtnorelbuf(Relation rel, Buffer buf); extern void _bt_wrtnorelbuf(Relation rel, Buffer buf);
extern void _bt_pageinit(Page page, Size size); extern void _bt_pageinit(Page page, Size size);
extern void _bt_metaproot(Relation rel, BlockNumber rootbknum, int level); extern void _bt_metaproot(Relation rel, BlockNumber rootbknum, int level);
extern void _bt_pagedel(Relation rel, ItemPointer tid); extern void _bt_itemdel(Relation rel, Buffer buf, ItemPointer tid);
/*
* prototypes for functions in nbtscan.c
*/
extern void _bt_regscan(IndexScanDesc scan);
extern void _bt_dropscan(IndexScanDesc scan);
extern void _bt_adjscans(Relation rel, ItemPointer tid);
extern void AtEOXact_nbtree(void);
/* /*
* prototypes for functions in nbtsearch.c * prototypes for functions in nbtsearch.c
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: rtree.h,v 1.23 2001/05/30 19:53:39 tgl Exp $ * $Id: rtree.h,v 1.24 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -110,7 +110,7 @@ extern void freestack(RTSTACK *s); ...@@ -110,7 +110,7 @@ extern void freestack(RTSTACK *s);
* Defined in access/rtree/ * Defined in access/rtree/
*/ */
extern Datum rtinsert(PG_FUNCTION_ARGS); extern Datum rtinsert(PG_FUNCTION_ARGS);
extern Datum rtdelete(PG_FUNCTION_ARGS); extern Datum rtbulkdelete(PG_FUNCTION_ARGS);
extern Datum rtgettuple(PG_FUNCTION_ARGS); extern Datum rtgettuple(PG_FUNCTION_ARGS);
extern Datum rtbeginscan(PG_FUNCTION_ARGS); extern Datum rtbeginscan(PG_FUNCTION_ARGS);
...@@ -129,6 +129,7 @@ extern void rtree_desc(char *buf, uint8 xl_info, char *rec); ...@@ -129,6 +129,7 @@ extern void rtree_desc(char *buf, uint8 xl_info, char *rec);
/* rtscan.c */ /* rtscan.c */
extern void rtadjscans(Relation r, int op, BlockNumber blkno, extern void rtadjscans(Relation r, int op, BlockNumber blkno,
OffsetNumber offnum); OffsetNumber offnum);
extern void AtEOXact_rtree(void);
/* rtstrat.c */ /* rtstrat.c */
extern RegProcedure RTMapOperator(Relation r, AttrNumber attnum, extern RegProcedure RTMapOperator(Relation r, AttrNumber attnum,
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.85 2001/06/22 19:16:24 wieck Exp $ * $Id: catversion.h,v 1.86 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200106221 #define CATALOG_VERSION_NO 200107151
#endif #endif
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: index.h,v 1.35 2001/05/30 20:52:34 momjian Exp $ * $Id: index.h,v 1.36 2001/07/15 22:48:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -17,6 +17,16 @@ ...@@ -17,6 +17,16 @@
#include "access/itup.h" #include "access/itup.h"
#include "nodes/execnodes.h" #include "nodes/execnodes.h"
/* Typedef for callback function for IndexBuildHeapScan */
typedef void (*IndexBuildCallback) (Relation index,
HeapTuple htup,
Datum *attdata,
char *nulls,
bool tupleIsAlive,
void *state);
extern Form_pg_am AccessMethodObjectIdGetForm(Oid accessMethodObjectId, extern Form_pg_am AccessMethodObjectIdGetForm(Oid accessMethodObjectId,
MemoryContext resultCxt); MemoryContext resultCxt);
...@@ -56,7 +66,13 @@ extern bool SetReindexProcessing(bool processing); ...@@ -56,7 +66,13 @@ extern bool SetReindexProcessing(bool processing);
extern bool IsReindexProcessing(void); extern bool IsReindexProcessing(void);
extern void index_build(Relation heapRelation, Relation indexRelation, extern void index_build(Relation heapRelation, Relation indexRelation,
IndexInfo *indexInfo, Node *oldPred); IndexInfo *indexInfo);
extern double IndexBuildHeapScan(Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo,
IndexBuildCallback callback,
void *callback_state);
extern bool reindex_index(Oid indexId, bool force, bool inplace); extern bool reindex_index(Oid indexId, bool force, bool inplace);
extern bool activate_indexes_of_a_table(Oid relid, bool activate); extern bool activate_indexes_of_a_table(Oid relid, bool activate);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_am.h,v 1.17 2001/05/30 19:55:08 tgl Exp $ * $Id: pg_am.h,v 1.18 2001/07/15 22:48:18 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -38,30 +38,26 @@ CATALOG(pg_am) ...@@ -38,30 +38,26 @@ CATALOG(pg_am)
{ {
NameData amname; /* access method name */ NameData amname; /* access method name */
int4 amowner; /* usesysid of creator */ int4 amowner; /* usesysid of creator */
int2 amstrategies; /* total NUMBER of strategies by which we int2 amstrategies; /* total NUMBER of strategies (operators) by
* can traverse/search this AM */ * which we can traverse/search this AM */
int2 amsupport; /* total NUMBER of support functions that int2 amsupport; /* total NUMBER of support functions that
* this AM uses */ * this AM uses */
int2 amorderstrategy;/* if this AM has a sort order, the int2 amorderstrategy;/* if this AM has a sort order, the
* strategy number of the sort operator. * strategy number of the sort operator.
* Zero if AM is not ordered. */ * Zero if AM is not ordered. */
bool amcanunique; /* does AM support UNIQUE indexes? */
bool amcanmulticol; /* does AM support multi-column indexes? */
bool amindexnulls; /* does AM support NULL index entries? */
bool amconcurrent; /* does AM support concurrent updates? */
regproc amgettuple; /* "next valid tuple" function */ regproc amgettuple; /* "next valid tuple" function */
regproc aminsert; /* "insert this tuple" function */ regproc aminsert; /* "insert this tuple" function */
regproc amdelete; /* "delete this tuple" function */
regproc amgetattr; /* - deprecated */
regproc amsetlock; /* - deprecated */
regproc amsettid; /* - deprecated */
regproc amfreetuple; /* - deprecated */
regproc ambeginscan; /* "start new scan" function */ regproc ambeginscan; /* "start new scan" function */
regproc amrescan; /* "restart this scan" function */ regproc amrescan; /* "restart this scan" function */
regproc amendscan; /* "end this scan" function */ regproc amendscan; /* "end this scan" function */
regproc ammarkpos; /* "mark current scan position" function */ regproc ammarkpos; /* "mark current scan position" function */
regproc amrestrpos; /* "restore marked scan position" function */ regproc amrestrpos; /* "restore marked scan position" function */
regproc amopen; /* - deprecated */
regproc amclose; /* - deprecated */
regproc ambuild; /* "build new index" function */ regproc ambuild; /* "build new index" function */
regproc amcreate; /* - deprecated */ regproc ambulkdelete; /* bulk-delete function */
regproc amdestroy; /* - deprecated */
regproc amcostestimate; /* estimate cost of an indexscan */ regproc amcostestimate; /* estimate cost of an indexscan */
} FormData_pg_am; } FormData_pg_am;
...@@ -76,46 +72,40 @@ typedef FormData_pg_am *Form_pg_am; ...@@ -76,46 +72,40 @@ typedef FormData_pg_am *Form_pg_am;
* compiler constants for pg_am * compiler constants for pg_am
* ---------------- * ----------------
*/ */
#define Natts_pg_am 23 #define Natts_pg_am 19
#define Anum_pg_am_amname 1 #define Anum_pg_am_amname 1
#define Anum_pg_am_amowner 2 #define Anum_pg_am_amowner 2
#define Anum_pg_am_amstrategies 3 #define Anum_pg_am_amstrategies 3
#define Anum_pg_am_amsupport 4 #define Anum_pg_am_amsupport 4
#define Anum_pg_am_amorderstrategy 5 #define Anum_pg_am_amorderstrategy 5
#define Anum_pg_am_amgettuple 6 #define Anum_pg_am_amcanunique 6
#define Anum_pg_am_aminsert 7 #define Anum_pg_am_amcanmulticol 7
#define Anum_pg_am_amdelete 8 #define Anum_pg_am_amindexnulls 8
#define Anum_pg_am_amgetattr 9 #define Anum_pg_am_amconcurrent 9
#define Anum_pg_am_amsetlock 10 #define Anum_pg_am_amgettuple 10
#define Anum_pg_am_amsettid 11 #define Anum_pg_am_aminsert 11
#define Anum_pg_am_amfreetuple 12 #define Anum_pg_am_ambeginscan 12
#define Anum_pg_am_ambeginscan 13 #define Anum_pg_am_amrescan 13
#define Anum_pg_am_amrescan 14 #define Anum_pg_am_amendscan 14
#define Anum_pg_am_amendscan 15 #define Anum_pg_am_ammarkpos 15
#define Anum_pg_am_ammarkpos 16 #define Anum_pg_am_amrestrpos 16
#define Anum_pg_am_amrestrpos 17 #define Anum_pg_am_ambuild 17
#define Anum_pg_am_amopen 18 #define Anum_pg_am_ambulkdelete 18
#define Anum_pg_am_amclose 19 #define Anum_pg_am_amcostestimate 19
#define Anum_pg_am_ambuild 20
#define Anum_pg_am_amcreate 21
#define Anum_pg_am_amdestroy 22
#define Anum_pg_am_amcostestimate 23
/* ---------------- /* ----------------
* initial contents of pg_am * initial contents of pg_am
* ---------------- * ----------------
*/ */
DATA(insert OID = 402 ( rtree PGUID 8 3 0 rtgettuple rtinsert rtdelete - - - - rtbeginscan rtrescan rtendscan rtmarkpos rtrestrpos - - rtbuild - - rtcostestimate )); DATA(insert OID = 402 ( rtree PGUID 8 3 0 f f f f rtgettuple rtinsert rtbeginscan rtrescan rtendscan rtmarkpos rtrestrpos rtbuild rtbulkdelete rtcostestimate ));
DESCR(""); DESCR("r-tree index access method");
DATA(insert OID = 403 ( btree PGUID 5 1 1 btgettuple btinsert btdelete - - - - btbeginscan btrescan btendscan btmarkpos btrestrpos - - btbuild - - btcostestimate )); DATA(insert OID = 403 ( btree PGUID 5 1 1 t t t t btgettuple btinsert btbeginscan btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btcostestimate ));
DESCR(""); DESCR("b-tree index access method");
#define BTREE_AM_OID 403 #define BTREE_AM_OID 403
DATA(insert OID = 405 ( hash PGUID 1 1 0 hashgettuple hashinsert hashdelete - - - - hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos - - hashbuild - - hashcostestimate )); DATA(insert OID = 405 ( hash PGUID 1 1 0 f f f t hashgettuple hashinsert hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashcostestimate ));
DESCR(""); DESCR("hash index access method");
#define HASH_AM_OID 405 DATA(insert OID = 783 ( gist PGUID 100 7 0 f t f f gistgettuple gistinsert gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistcostestimate ));
DATA(insert OID = 783 ( gist PGUID 100 7 0 gistgettuple gistinsert gistdelete - - - - gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos - - gistbuild - - gistcostestimate )); DESCR("GiST index access method");
DESCR("");
#define GIST_AM_OID 783
#endif /* PG_AM_H */ #endif /* PG_AM_H */
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_index.h,v 1.21 2001/07/09 18:35:52 momjian Exp $ * $Id: pg_index.h,v 1.22 2001/07/15 22:48:18 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -58,7 +58,9 @@ CATALOG(pg_index) ...@@ -58,7 +58,9 @@ CATALOG(pg_index)
bool indisprimary; /* is this index for primary key */ bool indisprimary; /* is this index for primary key */
Oid indreference; /* oid of index of referenced relation (ie Oid indreference; /* oid of index of referenced relation (ie
* - this index for foreign key */ * - this index for foreign key */
text indpred; /* query plan for partial index predicate */ /* VARIABLE LENGTH FIELD: */
text indpred; /* expression tree for predicate,
* if a partial index */
} FormData_pg_index; } FormData_pg_index;
/* ---------------- /* ----------------
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_proc.h,v 1.196 2001/07/11 22:14:02 momjian Exp $ * $Id: pg_proc.h,v 1.197 2001/07/15 22:48:18 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
...@@ -210,11 +210,6 @@ DESCR("not equal"); ...@@ -210,11 +210,6 @@ DESCR("not equal");
DATA(insert OID = 89 ( version PGUID 12 f t f t 0 f 25 "" 100 0 0 100 pgsql_version - )); DATA(insert OID = 89 ( version PGUID 12 f t f t 0 f 25 "" 100 0 0 100 pgsql_version - ));
DESCR("PostgreSQL version string"); DESCR("PostgreSQL version string");
DATA(insert OID = 1265 ( rtcostestimate PGUID 12 f t f t 8 f 0 "0 0 0 0 0 0 0 0" 100 0 0 100 rtcostestimate - ));
DESCR("r-tree cost estimator");
DATA(insert OID = 1268 ( btcostestimate PGUID 12 f t f t 8 f 0 "0 0 0 0 0 0 0 0" 100 0 0 100 btcostestimate - ));
DESCR("btree cost estimator");
/* OIDS 100 - 199 */ /* OIDS 100 - 199 */
DATA(insert OID = 100 ( int8fac PGUID 12 f t t t 1 f 20 "20" 100 0 0 100 int8fac - )); DATA(insert OID = 100 ( int8fac PGUID 12 f t t t 1 f 20 "20" 100 0 0 100 int8fac - ));
...@@ -671,11 +666,9 @@ DESCR("convert float4 to int4"); ...@@ -671,11 +666,9 @@ DESCR("convert float4 to int4");
DATA(insert OID = 320 ( rtinsert PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 rtinsert - )); DATA(insert OID = 320 ( rtinsert PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 rtinsert - ));
DESCR("r-tree(internal)"); DESCR("r-tree(internal)");
DATA(insert OID = 321 ( rtdelete PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 rtdelete - ));
DESCR("r-tree(internal)");
DATA(insert OID = 322 ( rtgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 rtgettuple - )); DATA(insert OID = 322 ( rtgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 rtgettuple - ));
DESCR("r-tree(internal)"); DESCR("r-tree(internal)");
DATA(insert OID = 323 ( rtbuild PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 rtbuild - )); DATA(insert OID = 323 ( rtbuild PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 rtbuild - ));
DESCR("r-tree(internal)"); DESCR("r-tree(internal)");
DATA(insert OID = 324 ( rtbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 rtbeginscan - )); DATA(insert OID = 324 ( rtbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 rtbeginscan - ));
DESCR("r-tree(internal)"); DESCR("r-tree(internal)");
...@@ -687,13 +680,15 @@ DATA(insert OID = 327 ( rtrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 ...@@ -687,13 +680,15 @@ DATA(insert OID = 327 ( rtrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100
DESCR("r-tree(internal)"); DESCR("r-tree(internal)");
DATA(insert OID = 328 ( rtrescan PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 rtrescan - )); DATA(insert OID = 328 ( rtrescan PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 rtrescan - ));
DESCR("r-tree(internal)"); DESCR("r-tree(internal)");
DATA(insert OID = 321 ( rtbulkdelete PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 rtbulkdelete - ));
DESCR("r-tree(internal)");
DATA(insert OID = 1265 ( rtcostestimate PGUID 12 f t f t 8 f 0 "0 0 0 0 0 0 0 0" 100 0 0 100 rtcostestimate - ));
DESCR("r-tree(internal)");
DATA(insert OID = 330 ( btgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 btgettuple - )); DATA(insert OID = 330 ( btgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 btgettuple - ));
DESCR("btree(internal)"); DESCR("btree(internal)");
DATA(insert OID = 331 ( btinsert PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 btinsert - )); DATA(insert OID = 331 ( btinsert PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 btinsert - ));
DESCR("btree(internal)"); DESCR("btree(internal)");
DATA(insert OID = 332 ( btdelete PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 btdelete - ));
DESCR("btree(internal)");
DATA(insert OID = 333 ( btbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 btbeginscan - )); DATA(insert OID = 333 ( btbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 btbeginscan - ));
DESCR("btree(internal)"); DESCR("btree(internal)");
DATA(insert OID = 334 ( btrescan PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 btrescan - )); DATA(insert OID = 334 ( btrescan PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 btrescan - ));
...@@ -704,7 +699,11 @@ DATA(insert OID = 336 ( btmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 b ...@@ -704,7 +699,11 @@ DATA(insert OID = 336 ( btmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 b
DESCR("btree(internal)"); DESCR("btree(internal)");
DATA(insert OID = 337 ( btrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 btrestrpos - )); DATA(insert OID = 337 ( btrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 btrestrpos - ));
DESCR("btree(internal)"); DESCR("btree(internal)");
DATA(insert OID = 338 ( btbuild PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 btbuild - )); DATA(insert OID = 338 ( btbuild PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 btbuild - ));
DESCR("btree(internal)");
DATA(insert OID = 332 ( btbulkdelete PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 btbulkdelete - ));
DESCR("btree(internal)");
DATA(insert OID = 1268 ( btcostestimate PGUID 12 f t f t 8 f 0 "0 0 0 0 0 0 0 0" 100 0 0 100 btcostestimate - ));
DESCR("btree(internal)"); DESCR("btree(internal)");
DATA(insert OID = 339 ( poly_same PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100 poly_same - )); DATA(insert OID = 339 ( poly_same PGUID 12 f t t t 2 f 16 "604 604" 100 0 0 100 poly_same - ));
...@@ -789,15 +788,10 @@ DESCR("convert name to char()"); ...@@ -789,15 +788,10 @@ DESCR("convert name to char()");
DATA(insert OID = 409 ( name PGUID 12 f t t t 1 f 19 "1042" 100 0 0 100 bpchar_name - )); DATA(insert OID = 409 ( name PGUID 12 f t t t 1 f 19 "1042" 100 0 0 100 bpchar_name - ));
DESCR("convert char() to name"); DESCR("convert char() to name");
DATA(insert OID = 438 ( hashcostestimate PGUID 12 f t f t 8 f 0 "0 0 0 0 0 0 0 0" 100 0 0 100 hashcostestimate - ));
DESCR("hash index cost estimator");
DATA(insert OID = 440 ( hashgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 hashgettuple - )); DATA(insert OID = 440 ( hashgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 hashgettuple - ));
DESCR("hash(internal)"); DESCR("hash(internal)");
DATA(insert OID = 441 ( hashinsert PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 hashinsert - )); DATA(insert OID = 441 ( hashinsert PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 hashinsert - ));
DESCR("hash(internal)"); DESCR("hash(internal)");
DATA(insert OID = 442 ( hashdelete PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 hashdelete - ));
DESCR("hash(internal)");
DATA(insert OID = 443 ( hashbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 hashbeginscan - )); DATA(insert OID = 443 ( hashbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 hashbeginscan - ));
DESCR("hash(internal)"); DESCR("hash(internal)");
DATA(insert OID = 444 ( hashrescan PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 hashrescan - )); DATA(insert OID = 444 ( hashrescan PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 hashrescan - ));
...@@ -808,8 +802,13 @@ DATA(insert OID = 446 ( hashmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 ...@@ -808,8 +802,13 @@ DATA(insert OID = 446 ( hashmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100
DESCR("hash(internal)"); DESCR("hash(internal)");
DATA(insert OID = 447 ( hashrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 hashrestrpos - )); DATA(insert OID = 447 ( hashrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 hashrestrpos - ));
DESCR("hash(internal)"); DESCR("hash(internal)");
DATA(insert OID = 448 ( hashbuild PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 hashbuild - )); DATA(insert OID = 448 ( hashbuild PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 hashbuild - ));
DESCR("hash(internal)");
DATA(insert OID = 442 ( hashbulkdelete PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 hashbulkdelete - ));
DESCR("hash(internal)"); DESCR("hash(internal)");
DATA(insert OID = 438 ( hashcostestimate PGUID 12 f t f t 8 f 0 "0 0 0 0 0 0 0 0" 100 0 0 100 hashcostestimate - ));
DESCR("hash(internal)");
DATA(insert OID = 449 ( hashint2 PGUID 12 f t t t 1 f 23 "21" 100 0 0 100 hashint2 - )); DATA(insert OID = 449 ( hashint2 PGUID 12 f t t t 1 f 23 "21" 100 0 0 100 hashint2 - ));
DESCR("hash"); DESCR("hash");
DATA(insert OID = 450 ( hashint4 PGUID 12 f t t t 1 f 23 "23" 100 0 0 100 hashint4 - )); DATA(insert OID = 450 ( hashint4 PGUID 12 f t t t 1 f 23 "23" 100 0 0 100 hashint4 - ));
...@@ -1014,14 +1013,10 @@ DESCR("larger of two"); ...@@ -1014,14 +1013,10 @@ DESCR("larger of two");
DATA(insert OID = 771 ( int2smaller PGUID 12 f t t t 2 f 21 "21 21" 100 0 0 100 int2smaller - )); DATA(insert OID = 771 ( int2smaller PGUID 12 f t t t 2 f 21 "21 21" 100 0 0 100 int2smaller - ));
DESCR("smaller of two"); DESCR("smaller of two");
DATA(insert OID = 772 ( gistcostestimate PGUID 12 f t f t 8 f 0 "0 0 0 0 0 0 0 0" 100 0 0 100 gistcostestimate - ));
DESCR("gist cost estimator");
DATA(insert OID = 774 ( gistgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 gistgettuple - )); DATA(insert OID = 774 ( gistgettuple PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 gistgettuple - ));
DESCR("gist(internal)"); DESCR("gist(internal)");
DATA(insert OID = 775 ( gistinsert PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 gistinsert - )); DATA(insert OID = 775 ( gistinsert PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 gistinsert - ));
DESCR("gist(internal)"); DESCR("gist(internal)");
DATA(insert OID = 776 ( gistdelete PGUID 12 f t f t 2 f 23 "0 0" 100 0 0 100 gistdelete - ));
DESCR("gist(internal)");
DATA(insert OID = 777 ( gistbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 gistbeginscan - )); DATA(insert OID = 777 ( gistbeginscan PGUID 12 f t f t 4 f 23 "0 0 0 0" 100 0 0 100 gistbeginscan - ));
DESCR("gist(internal)"); DESCR("gist(internal)");
DATA(insert OID = 778 ( gistrescan PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 gistrescan - )); DATA(insert OID = 778 ( gistrescan PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 gistrescan - ));
...@@ -1032,7 +1027,11 @@ DATA(insert OID = 780 ( gistmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 ...@@ -1032,7 +1027,11 @@ DATA(insert OID = 780 ( gistmarkpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100
DESCR("gist(internal)"); DESCR("gist(internal)");
DATA(insert OID = 781 ( gistrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 gistrestrpos - )); DATA(insert OID = 781 ( gistrestrpos PGUID 12 f t f t 1 f 23 "0" 100 0 0 100 gistrestrpos - ));
DESCR("gist(internal)"); DESCR("gist(internal)");
DATA(insert OID = 782 ( gistbuild PGUID 12 f t f t 5 f 23 "0 0 0 0 0" 100 0 0 100 gistbuild - )); DATA(insert OID = 782 ( gistbuild PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 gistbuild - ));
DESCR("gist(internal)");
DATA(insert OID = 776 ( gistbulkdelete PGUID 12 f t f t 3 f 23 "0 0 0" 100 0 0 100 gistbulkdelete - ));
DESCR("gist(internal)");
DATA(insert OID = 772 ( gistcostestimate PGUID 12 f t f t 8 f 0 "0 0 0 0 0 0 0 0" 100 0 0 100 gistcostestimate - ));
DESCR("gist(internal)"); DESCR("gist(internal)");
DATA(insert OID = 784 ( tintervaleq PGUID 12 f t f t 2 f 16 "704 704" 100 0 0 100 tintervaleq - )); DATA(insert OID = 784 ( tintervaleq PGUID 12 f t f t 2 f 16 "704 704" 100 0 0 100 tintervaleq - ));
......
...@@ -57,14 +57,6 @@ WHERE pg_am.aminsert != 0 AND ...@@ -57,14 +57,6 @@ WHERE pg_am.aminsert != 0 AND
-----+---------- -----+----------
(0 rows) (0 rows)
SELECT oid, pg_am.amdelete
FROM pg_am
WHERE pg_am.amdelete != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amdelete);
oid | amdelete
-----+----------
(0 rows)
SELECT oid, pg_am.ambeginscan SELECT oid, pg_am.ambeginscan
FROM pg_am FROM pg_am
WHERE pg_am.ambeginscan != 0 AND WHERE pg_am.ambeginscan != 0 AND
...@@ -113,6 +105,14 @@ WHERE pg_am.ambuild != 0 AND ...@@ -113,6 +105,14 @@ WHERE pg_am.ambuild != 0 AND
-----+--------- -----+---------
(0 rows) (0 rows)
SELECT oid, pg_am.ambulkdelete
FROM pg_am
WHERE pg_am.ambulkdelete != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambulkdelete);
oid | ambulkdelete
-----+--------------
(0 rows)
SELECT oid, pg_am.amcostestimate SELECT oid, pg_am.amcostestimate
FROM pg_am FROM pg_am
WHERE pg_am.amcostestimate != 0 AND WHERE pg_am.amcostestimate != 0 AND
......
...@@ -480,8 +480,8 @@ WHERE p1.aggtransfn = p2.oid AND ...@@ -480,8 +480,8 @@ WHERE p1.aggtransfn = p2.oid AND
(p2.pronargs = 1 AND p1.aggbasetype = 0))); (p2.pronargs = 1 AND p1.aggbasetype = 0)));
oid | aggname | oid | proname oid | aggname | oid | proname
-------+---------+-----+------------- -------+---------+-----+-------------
16963 | max | 768 | int4larger 16959 | max | 768 | int4larger
16977 | min | 769 | int4smaller 16973 | min | 769 | int4smaller
(2 rows) (2 rows)
-- Cross-check finalfn (if present) against its entry in pg_proc. -- Cross-check finalfn (if present) against its entry in pg_proc.
......
...@@ -29,10 +29,6 @@ SELECT oid, pg_am.aminsert ...@@ -29,10 +29,6 @@ SELECT oid, pg_am.aminsert
FROM pg_am FROM pg_am
WHERE pg_am.aminsert != 0 AND WHERE pg_am.aminsert != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.aminsert); NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.aminsert);
SELECT oid, pg_am.amdelete
FROM pg_am
WHERE pg_am.amdelete != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amdelete);
SELECT oid, pg_am.ambeginscan SELECT oid, pg_am.ambeginscan
FROM pg_am FROM pg_am
WHERE pg_am.ambeginscan != 0 AND WHERE pg_am.ambeginscan != 0 AND
...@@ -57,6 +53,10 @@ SELECT oid, pg_am.ambuild ...@@ -57,6 +53,10 @@ SELECT oid, pg_am.ambuild
FROM pg_am FROM pg_am
WHERE pg_am.ambuild != 0 AND WHERE pg_am.ambuild != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambuild); NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambuild);
SELECT oid, pg_am.ambulkdelete
FROM pg_am
WHERE pg_am.ambulkdelete != 0 AND
NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambulkdelete);
SELECT oid, pg_am.amcostestimate SELECT oid, pg_am.amcostestimate
FROM pg_am FROM pg_am
WHERE pg_am.amcostestimate != 0 AND WHERE pg_am.amcostestimate != 0 AND
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment