Fixed (I hope) unique btree index implementation.
This commit is contained in:
parent
c6a605705c
commit
daec84f09d
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.8 1996/12/06 09:45:30 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.9 1997/01/10 10:06:20 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -17,6 +17,7 @@
|
|||||||
#include <utils/memutils.h>
|
#include <utils/memutils.h>
|
||||||
#include <storage/bufpage.h>
|
#include <storage/bufpage.h>
|
||||||
#include <access/nbtree.h>
|
#include <access/nbtree.h>
|
||||||
|
#include <access/heapam.h>
|
||||||
#include <storage/bufmgr.h>
|
#include <storage/bufmgr.h>
|
||||||
|
|
||||||
#ifndef HAVE_MEMMOVE
|
#ifndef HAVE_MEMMOVE
|
||||||
@ -41,7 +42,7 @@ static void _bt_updateitem(Relation rel, Size keysz, Buffer buf, Oid bti_oid, BT
|
|||||||
* (xid, seqno) pair.
|
* (xid, seqno) pair.
|
||||||
*/
|
*/
|
||||||
InsertIndexResult
|
InsertIndexResult
|
||||||
_bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, bool is_update)
|
_bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, Relation heapRel)
|
||||||
{
|
{
|
||||||
ScanKey itup_scankey;
|
ScanKey itup_scankey;
|
||||||
IndexTuple itup;
|
IndexTuple itup;
|
||||||
@ -60,30 +61,6 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, bool is_update)
|
|||||||
/* find the page containing this key */
|
/* find the page containing this key */
|
||||||
stack = _bt_search(rel, natts, itup_scankey, &buf);
|
stack = _bt_search(rel, natts, itup_scankey, &buf);
|
||||||
|
|
||||||
/* if we're not allowing duplicates, make sure the key isn't */
|
|
||||||
/* already in the node */
|
|
||||||
if(index_is_unique && !is_update) {
|
|
||||||
OffsetNumber offset;
|
|
||||||
TupleDesc itupdesc;
|
|
||||||
Page page;
|
|
||||||
|
|
||||||
itupdesc = RelationGetTupleDescriptor(rel);
|
|
||||||
page = BufferGetPage(buf);
|
|
||||||
|
|
||||||
offset = _bt_binsrch(rel, buf, natts, itup_scankey, BT_DESCENT);
|
|
||||||
|
|
||||||
/* make sure the offset we're given points to an actual */
|
|
||||||
/* key on the page before trying to compare it */
|
|
||||||
if(!PageIsEmpty(page) &&
|
|
||||||
offset <= PageGetMaxOffsetNumber(page)) {
|
|
||||||
if(!_bt_compare(rel, itupdesc, page,
|
|
||||||
natts, itup_scankey, offset)) {
|
|
||||||
/* it is a duplicate */
|
|
||||||
elog(WARN, "Cannot insert a duplicate key into a unique index.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blkno = BufferGetBlockNumber(buf);
|
blkno = BufferGetBlockNumber(buf);
|
||||||
|
|
||||||
/* trade in our read lock for a write lock */
|
/* trade in our read lock for a write lock */
|
||||||
@ -100,6 +77,91 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, bool is_update)
|
|||||||
|
|
||||||
buf = _bt_moveright(rel, buf, natts, itup_scankey, BT_WRITE);
|
buf = _bt_moveright(rel, buf, natts, itup_scankey, BT_WRITE);
|
||||||
|
|
||||||
|
/* if we're not allowing duplicates, make sure the key isn't */
|
||||||
|
/* already in the node */
|
||||||
|
if ( index_is_unique )
|
||||||
|
{
|
||||||
|
OffsetNumber offset, maxoff;
|
||||||
|
Page page;
|
||||||
|
|
||||||
|
page = BufferGetPage(buf);
|
||||||
|
maxoff = PageGetMaxOffsetNumber (page);
|
||||||
|
|
||||||
|
offset = _bt_binsrch(rel, buf, natts, itup_scankey, BT_DESCENT);
|
||||||
|
|
||||||
|
/* make sure the offset we're given points to an actual */
|
||||||
|
/* key on the page before trying to compare it */
|
||||||
|
if ( !PageIsEmpty (page) && offset <= maxoff )
|
||||||
|
{
|
||||||
|
TupleDesc itupdesc;
|
||||||
|
BTItem btitem;
|
||||||
|
IndexTuple itup;
|
||||||
|
HeapTuple htup;
|
||||||
|
BTPageOpaque opaque;
|
||||||
|
Buffer nbuf;
|
||||||
|
BlockNumber blkno;
|
||||||
|
|
||||||
|
itupdesc = RelationGetTupleDescriptor(rel);
|
||||||
|
nbuf = InvalidBuffer;
|
||||||
|
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
|
while ( !_bt_compare (rel, itupdesc, page,
|
||||||
|
natts, itup_scankey, offset) )
|
||||||
|
{ /* they're equal */
|
||||||
|
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offset));
|
||||||
|
itup = &(btitem->bti_itup);
|
||||||
|
htup = heap_fetch (heapRel, SelfTimeQual, &(itup->t_tid), NULL);
|
||||||
|
if ( htup != (HeapTuple) NULL )
|
||||||
|
{ /* it is a duplicate */
|
||||||
|
elog(WARN, "Cannot insert a duplicate key into a unique index.");
|
||||||
|
}
|
||||||
|
/* get next offnum */
|
||||||
|
if ( offset < maxoff )
|
||||||
|
{
|
||||||
|
offset = OffsetNumberNext(offset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* move right ? */
|
||||||
|
if ( P_RIGHTMOST (opaque) )
|
||||||
|
break;
|
||||||
|
if ( _bt_compare (rel, itupdesc, page,
|
||||||
|
natts, itup_scankey, P_HIKEY) )
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* min key of the right page is the same,
|
||||||
|
* ooh - so many dead duplicates...
|
||||||
|
*/
|
||||||
|
blkno = opaque->btpo_next;
|
||||||
|
if ( nbuf != InvalidBuffer )
|
||||||
|
_bt_relbuf (rel, nbuf, BT_READ);
|
||||||
|
for (nbuf = InvalidBuffer; ; )
|
||||||
|
{
|
||||||
|
nbuf = _bt_getbuf (rel, blkno, BT_READ);
|
||||||
|
page = BufferGetPage (nbuf);
|
||||||
|
maxoff = PageGetMaxOffsetNumber(page);
|
||||||
|
opaque = (BTPageOpaque) PageGetSpecialPointer(page);
|
||||||
|
offset = P_RIGHTMOST(opaque) ? P_HIKEY : P_FIRSTKEY;
|
||||||
|
if ( ! PageIsEmpty (page) && offset <= maxoff )
|
||||||
|
{ /* Found some key */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* Empty or "pseudo"-empty page - get next */
|
||||||
|
blkno = opaque->btpo_next;
|
||||||
|
_bt_relbuf (rel, nbuf, BT_READ);
|
||||||
|
nbuf = InvalidBuffer;
|
||||||
|
if ( blkno == P_NONE )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( nbuf == InvalidBuffer )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( nbuf != InvalidBuffer )
|
||||||
|
_bt_relbuf(rel, nbuf, BT_READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* do the insertion */
|
/* do the insertion */
|
||||||
res = _bt_insertonpg(rel, buf, stack, natts, itup_scankey,
|
res = _bt_insertonpg(rel, buf, stack, natts, itup_scankey,
|
||||||
btitem, (BTItem) NULL);
|
btitem, (BTItem) NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user