1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* nbtpage.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* BTree-specific page management code for the Postgres btree access
|
|
|
|
* method.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2001-01-24 20:43:33 +01:00
|
|
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.53 2001/07/15 22:48:16 tgl Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* NOTES
|
|
|
|
* Postgres btree pages look like ordinary relation pages. The opaque
|
|
|
|
* data at high addresses includes pointers to left and right siblings
|
|
|
|
* and flag data describing page state. The first page in a btree, page
|
|
|
|
* zero, is special -- it stores meta-information describing the tree.
|
|
|
|
* Pages one and higher store the actual tree data.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1999-07-16 01:04:24 +02:00
|
|
|
#include "postgres.h"
|
1996-11-03 13:35:27 +01:00
|
|
|
|
2000-11-30 02:39:08 +01:00
|
|
|
#include <time.h>
|
|
|
|
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "access/nbtree.h"
|
|
|
|
#include "miscadmin.h"
|
2000-11-30 02:39:08 +01:00
|
|
|
#include "storage/lmgr.h"
|
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
extern bool FixBTree; /* comments in nbtree.c */
|
2001-01-26 02:24:31 +01:00
|
|
|
extern Buffer _bt_fixroot(Relation rel, Buffer oldrootbuf, bool release);
|
1999-07-16 07:00:38 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* We use high-concurrency locking on btrees. There are two cases in
|
|
|
|
* which we don't do locking. One is when we're building the btree.
|
|
|
|
* Since the creating transaction has not committed, no one can see
|
|
|
|
* the index, and there's no reason to share locks. The second case
|
|
|
|
* is when we're just starting up the database system. We use some
|
|
|
|
* special-purpose initialization code in the relation cache manager
|
|
|
|
* (see utils/cache/relcache.c) to allow us to do indexed scans on
|
|
|
|
* the system catalogs before we'd normally be able to. This happens
|
|
|
|
* 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
|
|
|
|
* system catalogs anyway, so I declare this to be okay.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
#define USELOCKING (!BuildingBtree && !IsInitProcessingMode())
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* _bt_metapinit() -- Initialize the metadata page of a btree.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
_bt_metapinit(Relation rel)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Buffer buf;
|
|
|
|
Page pg;
|
|
|
|
BTMetaPageData metad;
|
|
|
|
BTPageOpaque op;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/* can't be sharing this with anyone, now... */
|
|
|
|
if (USELOCKING)
|
1998-12-15 13:47:01 +01:00
|
|
|
LockRelation(rel, AccessExclusiveLock);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-06-28 01:31:40 +02:00
|
|
|
if (RelationGetNumberOfBlocks(rel) != 0)
|
1998-01-07 22:07:04 +01:00
|
|
|
elog(ERROR, "Cannot initialize non-empty btree %s",
|
1997-09-07 07:04:48 +02:00
|
|
|
RelationGetRelationName(rel));
|
|
|
|
|
|
|
|
buf = ReadBuffer(rel, P_NEW);
|
|
|
|
pg = BufferGetPage(buf);
|
|
|
|
_bt_pageinit(pg, BufferGetPageSize(buf));
|
|
|
|
|
|
|
|
metad.btm_magic = BTREE_MAGIC;
|
|
|
|
metad.btm_version = BTREE_VERSION;
|
|
|
|
metad.btm_root = P_NONE;
|
|
|
|
metad.btm_level = 0;
|
2000-07-21 08:42:39 +02:00
|
|
|
memcpy((char *) BTPageGetMeta(pg), (char *) &metad, sizeof(metad));
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
op = (BTPageOpaque) PageGetSpecialPointer(pg);
|
|
|
|
op->btpo_flags = BTP_META;
|
|
|
|
|
|
|
|
WriteBuffer(buf);
|
|
|
|
|
|
|
|
/* all done */
|
|
|
|
if (USELOCKING)
|
1998-12-15 13:47:01 +01:00
|
|
|
UnlockRelation(rel, AccessExclusiveLock);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* _bt_getroot() -- Get the root page of the btree.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Since the root page can move around the btree file, we have to read
|
|
|
|
* its location from the metadata page, and then read the root page
|
|
|
|
* itself. If no root page exists yet, we have to create one. The
|
|
|
|
* standard class of race conditions exists here; I think I covered
|
|
|
|
* them all in the Hopi Indian rain dance of lock requests below.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-07-21 08:42:39 +02:00
|
|
|
* The access type parameter (BT_READ or BT_WRITE) controls whether
|
|
|
|
* a new root page will be created or not. If access = BT_READ,
|
2001-03-22 05:01:46 +01:00
|
|
|
* and no root page exists, we just return InvalidBuffer. For
|
2000-07-21 08:42:39 +02:00
|
|
|
* BT_WRITE, we try to create the root page if it doesn't exist.
|
|
|
|
* NOTE that the returned root page will have only a read lock set
|
|
|
|
* on it even if access = BT_WRITE!
|
|
|
|
*
|
|
|
|
* On successful return, the root page is pinned and read-locked.
|
|
|
|
* The metadata page is not locked or pinned on exit.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
Buffer
|
|
|
|
_bt_getroot(Relation rel, int access)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Buffer metabuf;
|
|
|
|
Page metapg;
|
|
|
|
BTPageOpaque metaopaque;
|
|
|
|
Buffer rootbuf;
|
2000-10-04 02:04:43 +02:00
|
|
|
Page rootpage;
|
1997-09-08 04:41:22 +02:00
|
|
|
BTPageOpaque rootopaque;
|
|
|
|
BlockNumber rootblkno;
|
1997-09-07 07:04:48 +02:00
|
|
|
BTMetaPageData *metad;
|
|
|
|
|
|
|
|
metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
|
1996-07-09 08:22:35 +02:00
|
|
|
metapg = BufferGetPage(metabuf);
|
|
|
|
metaopaque = (BTPageOpaque) PageGetSpecialPointer(metapg);
|
|
|
|
metad = BTPageGetMeta(metapg);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-21 08:42:39 +02:00
|
|
|
if (!(metaopaque->btpo_flags & BTP_META) ||
|
|
|
|
metad->btm_magic != BTREE_MAGIC)
|
1998-01-07 22:07:04 +01:00
|
|
|
elog(ERROR, "Index %s is not a btree",
|
1997-09-07 07:04:48 +02:00
|
|
|
RelationGetRelationName(rel));
|
|
|
|
|
|
|
|
if (metad->btm_version != BTREE_VERSION)
|
2000-07-21 08:42:39 +02:00
|
|
|
elog(ERROR, "Version mismatch on %s: version %d file, version %d code",
|
1997-09-07 07:04:48 +02:00
|
|
|
RelationGetRelationName(rel),
|
|
|
|
metad->btm_version, BTREE_VERSION);
|
|
|
|
|
|
|
|
/* if no root page initialized yet, do it */
|
|
|
|
if (metad->btm_root == P_NONE)
|
|
|
|
{
|
2000-07-21 08:42:39 +02:00
|
|
|
/* If access = BT_READ, caller doesn't want us to create root yet */
|
|
|
|
if (access == BT_READ)
|
|
|
|
{
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
_bt_relbuf(rel, metabuf);
|
2000-07-21 08:42:39 +02:00
|
|
|
return InvalidBuffer;
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-21 08:42:39 +02:00
|
|
|
/* trade in our read lock for a write lock */
|
|
|
|
LockBuffer(metabuf, BUFFER_LOCK_UNLOCK);
|
|
|
|
LockBuffer(metabuf, BT_WRITE);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Race condition: if someone else initialized the metadata
|
|
|
|
* between the time we released the read lock and acquired the
|
2000-07-21 08:42:39 +02:00
|
|
|
* write lock, above, we must avoid doing it again.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
|
|
|
if (metad->btm_root == P_NONE)
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get, initialize, write, and leave a lock of the appropriate
|
|
|
|
* type on the new root page. Since this is the first page in
|
2000-07-21 08:42:39 +02:00
|
|
|
* the tree, it's a leaf as well as the root.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
|
|
|
rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
|
|
|
|
rootblkno = BufferGetBlockNumber(rootbuf);
|
2000-10-04 02:04:43 +02:00
|
|
|
rootpage = BufferGetPage(rootbuf);
|
|
|
|
|
|
|
|
/* NO ELOG(ERROR) till meta is updated */
|
2001-01-12 22:54:01 +01:00
|
|
|
START_CRIT_SECTION();
|
2000-10-04 02:04:43 +02:00
|
|
|
|
2000-12-28 14:00:29 +01:00
|
|
|
metad->btm_root = rootblkno;
|
|
|
|
metad->btm_level = 1;
|
|
|
|
|
2000-10-04 02:04:43 +02:00
|
|
|
_bt_pageinit(rootpage, BufferGetPageSize(rootbuf));
|
|
|
|
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
|
|
|
|
rootopaque->btpo_flags |= (BTP_LEAF | BTP_ROOT);
|
|
|
|
|
|
|
|
/* XLOG stuff */
|
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
xl_btree_newroot xlrec;
|
|
|
|
XLogRecPtr recptr;
|
|
|
|
XLogRecData rdata;
|
2000-10-13 04:03:02 +02:00
|
|
|
|
2000-10-04 02:04:43 +02:00
|
|
|
xlrec.node = rel->rd_node;
|
2000-12-28 14:00:29 +01:00
|
|
|
xlrec.level = 1;
|
2000-10-13 04:03:02 +02:00
|
|
|
BlockIdSet(&(xlrec.rootblk), rootblkno);
|
2000-12-28 14:00:29 +01:00
|
|
|
rdata.buffer = InvalidBuffer;
|
2001-03-22 05:01:46 +01:00
|
|
|
rdata.data = (char *) &xlrec;
|
2000-12-28 14:00:29 +01:00
|
|
|
rdata.len = SizeOfBtreeNewroot;
|
|
|
|
rdata.next = NULL;
|
2000-10-04 02:04:43 +02:00
|
|
|
|
2000-12-28 14:00:29 +01:00
|
|
|
recptr = XLogInsert(RM_BTREE_ID,
|
2001-03-22 05:01:46 +01:00
|
|
|
XLOG_BTREE_NEWROOT | XLOG_BTREE_LEAF, &rdata);
|
2000-10-04 02:04:43 +02:00
|
|
|
|
|
|
|
PageSetLSN(rootpage, recptr);
|
|
|
|
PageSetSUI(rootpage, ThisStartUpID);
|
2000-10-13 04:03:02 +02:00
|
|
|
PageSetLSN(metapg, recptr);
|
|
|
|
PageSetSUI(metapg, ThisStartUpID);
|
2000-10-04 02:04:43 +02:00
|
|
|
}
|
2000-07-21 08:42:39 +02:00
|
|
|
|
2001-01-12 22:54:01 +01:00
|
|
|
END_CRIT_SECTION();
|
2000-07-21 08:42:39 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
_bt_wrtnorelbuf(rel, rootbuf);
|
|
|
|
|
2000-07-21 08:42:39 +02:00
|
|
|
/* swap write lock for read lock */
|
|
|
|
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
|
|
|
|
LockBuffer(rootbuf, BT_READ);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-21 08:42:39 +02:00
|
|
|
/* okay, metadata is correct, write and release it */
|
1997-09-07 07:04:48 +02:00
|
|
|
_bt_wrtbuf(rel, metabuf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
|
|
|
* Metadata initialized by someone else. In order to
|
|
|
|
* guarantee no deadlocks, we have to release the metadata
|
|
|
|
* page and start all over again.
|
|
|
|
*/
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
_bt_relbuf(rel, metabuf);
|
1998-09-01 05:29:17 +02:00
|
|
|
return _bt_getroot(rel, access);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
else
|
|
|
|
{
|
1999-06-07 16:28:22 +02:00
|
|
|
rootblkno = metad->btm_root;
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
_bt_relbuf(rel, metabuf); /* done with the meta page */
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2000-07-21 08:42:39 +02:00
|
|
|
rootbuf = _bt_getbuf(rel, rootblkno, BT_READ);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Race condition: If the root page split between the time we looked
|
|
|
|
* at the metadata page and got the root buffer, then we got the wrong
|
2001-03-22 05:01:46 +01:00
|
|
|
* buffer. Release it and try again.
|
1997-09-07 07:04:48 +02:00
|
|
|
*/
|
2000-10-04 02:04:43 +02:00
|
|
|
rootpage = BufferGetPage(rootbuf);
|
|
|
|
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
if (!P_ISROOT(rootopaque))
|
2000-07-21 08:42:39 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2001-01-26 02:24:31 +01:00
|
|
|
/*
|
2001-03-22 05:01:46 +01:00
|
|
|
* It happened, but if root page splitter failed to create new
|
|
|
|
* root page then we'll go in loop trying to call _bt_getroot
|
|
|
|
* again and again.
|
2001-01-26 02:24:31 +01:00
|
|
|
*/
|
|
|
|
if (FixBTree)
|
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
Buffer newrootbuf;
|
2001-01-26 02:24:31 +01:00
|
|
|
|
2001-03-22 05:01:46 +01:00
|
|
|
check_parent:;
|
|
|
|
if (BTreeInvalidParent(rootopaque)) /* unupdated! */
|
2001-01-26 02:24:31 +01:00
|
|
|
{
|
|
|
|
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
|
|
|
|
LockBuffer(rootbuf, BT_WRITE);
|
|
|
|
|
|
|
|
/* handle concurrent fix of root page */
|
2001-03-22 05:01:46 +01:00
|
|
|
if (BTreeInvalidParent(rootopaque)) /* unupdated! */
|
2001-01-26 02:24:31 +01:00
|
|
|
{
|
2001-02-08 00:35:33 +01:00
|
|
|
elog(NOTICE, "bt_getroot[%s]: fixing root page", RelationGetRelationName(rel));
|
2001-01-26 02:24:31 +01:00
|
|
|
newrootbuf = _bt_fixroot(rel, rootbuf, true);
|
|
|
|
LockBuffer(newrootbuf, BUFFER_LOCK_UNLOCK);
|
|
|
|
LockBuffer(newrootbuf, BT_READ);
|
|
|
|
rootbuf = newrootbuf;
|
|
|
|
rootpage = BufferGetPage(rootbuf);
|
|
|
|
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
|
|
|
|
/* New root might be splitted while changing lock */
|
|
|
|
if (P_ISROOT(rootopaque))
|
2001-03-22 05:01:46 +01:00
|
|
|
return (rootbuf);
|
2001-01-26 02:24:31 +01:00
|
|
|
/* rootbuf is read locked */
|
|
|
|
goto check_parent;
|
|
|
|
}
|
2001-03-22 05:01:46 +01:00
|
|
|
else
|
2001-01-26 02:24:31 +01:00
|
|
|
{
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
/* someone else already fixed root */
|
2001-01-26 02:24:31 +01:00
|
|
|
LockBuffer(rootbuf, BUFFER_LOCK_UNLOCK);
|
|
|
|
LockBuffer(rootbuf, BT_READ);
|
|
|
|
}
|
|
|
|
}
|
2001-03-22 05:01:46 +01:00
|
|
|
|
2001-01-26 02:24:31 +01:00
|
|
|
/*
|
2001-03-22 05:01:46 +01:00
|
|
|
* Ok, here we have old root page with btpo_parent pointing to
|
|
|
|
* upper level - check parent page because of there is good
|
|
|
|
* chance that parent is root page.
|
2001-01-26 02:24:31 +01:00
|
|
|
*/
|
|
|
|
newrootbuf = _bt_getbuf(rel, rootopaque->btpo_parent, BT_READ);
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
_bt_relbuf(rel, rootbuf);
|
2001-01-26 02:24:31 +01:00
|
|
|
rootbuf = newrootbuf;
|
|
|
|
rootpage = BufferGetPage(rootbuf);
|
|
|
|
rootopaque = (BTPageOpaque) PageGetSpecialPointer(rootpage);
|
|
|
|
if (P_ISROOT(rootopaque))
|
2001-03-22 05:01:46 +01:00
|
|
|
return (rootbuf);
|
2001-01-26 02:24:31 +01:00
|
|
|
/* no luck -:( */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* try again */
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
_bt_relbuf(rel, rootbuf);
|
1998-09-01 05:29:17 +02:00
|
|
|
return _bt_getroot(rel, access);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* By here, we have a correct lock on the root block, its reference
|
|
|
|
* count is correct, and we have no lock set on the metadata page.
|
|
|
|
* Return the root block.
|
|
|
|
*/
|
1998-09-01 05:29:17 +02:00
|
|
|
return rootbuf;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* _bt_getbuf() -- Get a buffer by block number for read or write.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* When this routine returns, the appropriate lock is set on the
|
2000-07-21 08:42:39 +02:00
|
|
|
* requested buffer and its reference count has been incremented
|
|
|
|
* (ie, the buffer is "locked and pinned").
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
Buffer
|
|
|
|
_bt_getbuf(Relation rel, BlockNumber blkno, int access)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Buffer buf;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (blkno != P_NEW)
|
|
|
|
{
|
2000-07-21 08:42:39 +02:00
|
|
|
/* Read an existing block of the relation */
|
1997-09-07 07:04:48 +02:00
|
|
|
buf = ReadBuffer(rel, blkno);
|
1999-05-25 20:20:31 +02:00
|
|
|
LockBuffer(buf, access);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
else
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2000-07-21 08:42:39 +02:00
|
|
|
Page page;
|
1999-05-26 00:04:56 +02:00
|
|
|
|
1999-05-25 20:20:31 +02:00
|
|
|
/*
|
2000-07-21 08:42:39 +02:00
|
|
|
* Extend the relation by one page.
|
|
|
|
*
|
|
|
|
* Extend bufmgr code is unclean and so we have to use extra locking
|
1999-05-26 00:04:56 +02:00
|
|
|
* here.
|
1999-05-25 20:20:31 +02:00
|
|
|
*/
|
|
|
|
LockPage(rel, 0, ExclusiveLock);
|
1997-09-07 07:04:48 +02:00
|
|
|
buf = ReadBuffer(rel, blkno);
|
2000-07-21 08:42:39 +02:00
|
|
|
LockBuffer(buf, access);
|
1999-05-25 20:20:31 +02:00
|
|
|
UnlockPage(rel, 0, ExclusiveLock);
|
2000-07-21 08:42:39 +02:00
|
|
|
|
|
|
|
/* Initialize the new page before returning it */
|
1997-09-07 07:04:48 +02:00
|
|
|
page = BufferGetPage(buf);
|
|
|
|
_bt_pageinit(page, BufferGetPageSize(buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ref count and lock type are correct */
|
1998-09-01 05:29:17 +02:00
|
|
|
return buf;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* _bt_relbuf() -- release a locked buffer.
|
2000-07-21 08:42:39 +02:00
|
|
|
*
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
_bt_relbuf(Relation rel, Buffer buf)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-05-25 20:20:31 +02:00
|
|
|
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
1997-09-07 07:04:48 +02:00
|
|
|
ReleaseBuffer(buf);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* _bt_wrtbuf() -- write a btree page to disk.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-07-21 08:42:39 +02:00
|
|
|
* This routine releases the lock held on the buffer and our refcount
|
|
|
|
* for it. It is an error to call _bt_wrtbuf() without a write lock
|
|
|
|
* and a pin on the buffer.
|
|
|
|
*
|
|
|
|
* NOTE: actually, the buffer manager just marks the shared buffer page
|
2001-03-22 05:01:46 +01:00
|
|
|
* dirty here, the real I/O happens later. Since we can't persuade the
|
2000-07-21 08:42:39 +02:00
|
|
|
* Unix kernel to schedule disk writes in a particular order, there's not
|
|
|
|
* much point in worrying about this. The most we can say is that all the
|
|
|
|
* writes will occur before commit.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
_bt_wrtbuf(Relation rel, Buffer buf)
|
|
|
|
{
|
1999-05-25 20:20:31 +02:00
|
|
|
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
1997-09-07 07:04:48 +02:00
|
|
|
WriteBuffer(buf);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* _bt_wrtnorelbuf() -- write a btree page to disk, but do not release
|
|
|
|
* our reference or lock.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* It is an error to call _bt_wrtnorelbuf() without a write lock
|
2000-07-21 08:42:39 +02:00
|
|
|
* and a pin on the buffer.
|
|
|
|
*
|
|
|
|
* See above NOTE.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
_bt_wrtnorelbuf(Relation rel, Buffer buf)
|
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
WriteNoReleaseBuffer(buf);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* _bt_pageinit() -- Initialize a new page.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
_bt_pageinit(Page page, Size size)
|
|
|
|
{
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
/*
|
1999-02-14 00:22:53 +01:00
|
|
|
* Cargo_cult programming -- don't really need this to be zero, but
|
1997-09-07 07:04:48 +02:00
|
|
|
* creating new pages is an infrequent occurrence and it makes me feel
|
|
|
|
* good when I know they're empty.
|
|
|
|
*/
|
|
|
|
|
1997-09-18 22:22:58 +02:00
|
|
|
MemSet(page, 0, size);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
PageInit(page, size, sizeof(BTPageOpaqueData));
|
1999-05-25 18:15:34 +02:00
|
|
|
((BTPageOpaque) PageGetSpecialPointer(page))->btpo_parent =
|
1999-03-28 22:32:42 +02:00
|
|
|
InvalidBlockNumber;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1997-09-07 07:04:48 +02:00
|
|
|
* _bt_metaproot() -- Change the root page of the btree.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
1997-09-07 07:04:48 +02:00
|
|
|
* Lehman and Yao require that the root page move around in order to
|
|
|
|
* guarantee deadlock-free short-term, fine-granularity locking. When
|
|
|
|
* we split the root page, we record the new parent in the metadata page
|
|
|
|
* for the relation. This routine does the work.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2000-07-21 08:42:39 +02:00
|
|
|
* No direct preconditions, but if you don't have the write lock on
|
1997-09-07 07:04:48 +02:00
|
|
|
* at least the old root page when you call this, you're making a big
|
|
|
|
* mistake. On exit, metapage data is correct and we no longer have
|
2000-07-21 08:42:39 +02:00
|
|
|
* a pin or lock on the metapage.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
1997-04-16 03:48:29 +02:00
|
|
|
_bt_metaproot(Relation rel, BlockNumber rootbknum, int level)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Buffer metabuf;
|
|
|
|
Page metap;
|
|
|
|
BTPageOpaque metaopaque;
|
1997-09-07 07:04:48 +02:00
|
|
|
BTMetaPageData *metad;
|
|
|
|
|
|
|
|
metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
|
|
|
|
metap = BufferGetPage(metabuf);
|
|
|
|
metaopaque = (BTPageOpaque) PageGetSpecialPointer(metap);
|
|
|
|
Assert(metaopaque->btpo_flags & BTP_META);
|
|
|
|
metad = BTPageGetMeta(metap);
|
|
|
|
metad->btm_root = rootbknum;
|
1999-05-26 00:04:56 +02:00
|
|
|
if (level == 0) /* called from _do_insert */
|
1997-09-07 07:04:48 +02:00
|
|
|
metad->btm_level += 1;
|
|
|
|
else
|
|
|
|
metad->btm_level = level; /* called from btsort */
|
|
|
|
_bt_wrtbuf(rel, metabuf);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
* 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.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
void
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
_bt_itemdel(Relation rel, Buffer buf, ItemPointer tid)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
Page page = BufferGetPage(buf);
|
1997-09-08 04:41:22 +02:00
|
|
|
OffsetNumber offno;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
offno = ItemPointerGetOffsetNumber(tid);
|
|
|
|
|
2001-01-12 22:54:01 +01:00
|
|
|
START_CRIT_SECTION();
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
|
2000-12-29 21:47:17 +01:00
|
|
|
PageIndexTupleDelete(page, offno);
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
|
2000-12-29 21:47:17 +01:00
|
|
|
/* XLOG stuff */
|
2000-10-04 02:04:43 +02:00
|
|
|
{
|
2001-03-22 05:01:46 +01:00
|
|
|
xl_btree_delete xlrec;
|
|
|
|
XLogRecPtr recptr;
|
|
|
|
XLogRecData rdata[2];
|
2000-10-21 17:43:36 +02:00
|
|
|
|
2000-10-04 02:04:43 +02:00
|
|
|
xlrec.target.node = rel->rd_node;
|
|
|
|
xlrec.target.tid = *tid;
|
2000-12-28 14:00:29 +01:00
|
|
|
rdata[0].buffer = InvalidBuffer;
|
2001-03-22 05:01:46 +01:00
|
|
|
rdata[0].data = (char *) &xlrec;
|
2000-12-28 14:00:29 +01:00
|
|
|
rdata[0].len = SizeOfBtreeDelete;
|
|
|
|
rdata[0].next = &(rdata[1]);
|
|
|
|
|
|
|
|
rdata[1].buffer = buf;
|
|
|
|
rdata[1].data = NULL;
|
|
|
|
rdata[1].len = 0;
|
|
|
|
rdata[1].next = NULL;
|
|
|
|
|
|
|
|
recptr = XLogInsert(RM_BTREE_ID, XLOG_BTREE_DELETE, rdata);
|
2000-10-04 02:04:43 +02:00
|
|
|
|
|
|
|
PageSetLSN(page, recptr);
|
|
|
|
PageSetSUI(page, ThisStartUpID);
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
|
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.
2001-07-16 00:48:19 +02:00
|
|
|
END_CRIT_SECTION();
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|