diff options
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/gist/gist.c | 2 | ||||
-rw-r--r-- | src/backend/access/hash/hash.c | 4 | ||||
-rw-r--r-- | src/backend/access/index/indexam.c | 7 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtinsert.c | 147 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtree.c | 14 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtsearch.c | 6 | ||||
-rw-r--r-- | src/backend/access/rtree/rtree.c | 4 |
7 files changed, 124 insertions, 60 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 7fbf0ef07d3..5188c8bf90a 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -292,7 +292,7 @@ gistbuild(Relation heap, * It doesn't do any work; just locks the relation and passes the buck. */ InsertIndexResult -gistinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid) +gistinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid, bool is_update) { InsertIndexResult res; IndexTuple itup; diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 0ab47a5cd8c..973902c85cc 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.10 1996/11/05 09:40:17 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.11 1996/11/13 20:46:48 scrappy Exp $ * * NOTES * This file contains only the public interface routines. @@ -257,7 +257,7 @@ hashbuild(Relation heap, * to the caller. */ InsertIndexResult -hashinsert(Relation rel, Datum *datum, char *nulls, ItemPointer ht_ctid) +hashinsert(Relation rel, Datum *datum, char *nulls, ItemPointer ht_ctid, bool is_update) { HashItem hitem; IndexTuple itup; diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index dc354bdfaaf..92b7d4236ef 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.7 1996/11/05 10:02:03 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.8 1996/11/13 20:46:59 scrappy Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relationId @@ -164,7 +164,8 @@ InsertIndexResult index_insert(Relation relation, Datum *datum, char *nulls, - ItemPointer heap_t_ctid) + ItemPointer heap_t_ctid, + bool is_update) { RegProcedure procedure; InsertIndexResult specificResult; @@ -177,7 +178,7 @@ index_insert(Relation relation, * ---------------- */ specificResult = (InsertIndexResult) - fmgr(procedure, relation, datum, nulls, heap_t_ctid, NULL); + fmgr(procedure, relation, datum, nulls, heap_t_ctid, is_update, NULL); /* ---------------- * the insert proc is supposed to return a "specific result" and diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 63e06f8e1e3..c1cedd33bda 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.6 1996/11/05 10:35:29 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.7 1996/11/13 20:47:11 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,10 @@ static OffsetNumber _bt_findsplitloc(Relation rel, Page page, OffsetNumber start static void _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf); static OffsetNumber _bt_pgaddtup(Relation rel, Buffer buf, int keysz, ScanKey itup_scankey, Size itemsize, BTItem btitem, BTItem afteritem); static bool _bt_goesonpg(Relation rel, Buffer buf, Size keysz, ScanKey scankey, BTItem afteritem); + +#if 0 static void _bt_updateitem(Relation rel, Size keysz, Buffer buf, Oid bti_oid, BTItem newItem); +#endif /* * _bt_doinsert() -- Handle insertion of a single btitem in the tree. @@ -41,7 +44,7 @@ static void _bt_updateitem(Relation rel, Size keysz, Buffer buf, Oid bti_oid, BT * (xid, seqno) pair. */ InsertIndexResult -_bt_doinsert(Relation rel, BTItem btitem) +_bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, bool is_update) { ScanKey itup_scankey; IndexTuple itup; @@ -59,6 +62,31 @@ _bt_doinsert(Relation rel, BTItem btitem) /* find the page containing this key */ 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); /* trade in our read lock for a write lock */ @@ -137,6 +165,10 @@ _bt_insertonpg(Relation rel, InsertIndexResult newres; BTItem new_item = (BTItem) NULL; BTItem lowLeftItem; + OffsetNumber leftmost_offset; + Page ppage; + BTPageOpaque ppageop; + BlockNumber bknum; page = BufferGetPage(buf); itemsz = IndexTupleDSize(btitem->bti_itup) @@ -236,14 +268,67 @@ _bt_insertonpg(Relation rel, lowLeftItem = (BTItem) PageGetItem(page, PageGetItemId(page, P_FIRSTKEY)); - /* page must have right pointer after split */ - _bt_updateitem(rel, keysz, pbuf, stack->bts_btitem->bti_oid, - lowLeftItem); + + /* this method does not work--_bt_updateitem tries to */ + /* overwrite an entry with another entry that might be */ + /* bigger. if lowLeftItem is bigger, it corrupts the */ + /* parent page. instead, we have to delete the original */ + /* leftmost item from the parent, and insert the new one */ + /* with a regular _bt_insertonpg (it could cause a split */ + /* because it's bigger than what was there before). */ + /* --djm 8/21/96 */ + + /* _bt_updateitem(rel, keysz, pbuf, stack->bts_btitem->bti_oid, + lowLeftItem); */ + + /* get the parent page */ + ppage = BufferGetPage(pbuf); + ppageop = (BTPageOpaque) PageGetSpecialPointer(ppage); + + /* figure out which key is leftmost (if the parent page */ + /* is rightmost, too, it must be the root) */ + if(P_RIGHTMOST(ppageop)) { + leftmost_offset = P_HIKEY; + } else { + leftmost_offset = P_FIRSTKEY; } + PageIndexTupleDelete(ppage, leftmost_offset); + + /* don't write anything out yet--we still have the write */ + /* lock, and now we call another _bt_insertonpg to */ + /* insert the correct leftmost key */ + + /* make a new leftmost item, using the tuple data from */ + /* lowLeftItem. point it to the left child. */ + /* update it on the stack at the same time. */ + bknum = BufferGetBlockNumber(buf); + pfree(stack->bts_btitem); + stack->bts_btitem = _bt_formitem(&(lowLeftItem->bti_itup)); + ItemPointerSet(&(stack->bts_btitem->bti_itup.t_tid), + bknum, P_HIKEY); + + /* unlock the children before doing this */ + _bt_relbuf(rel, buf, BT_WRITE); + _bt_relbuf(rel, rbuf, BT_WRITE); + + /* a regular _bt_binsrch should find the right place to */ + /* put the new entry, since it should be lower than any */ + /* other key on the page, therefore set afteritem to NULL */ + newskey = _bt_mkscankey(rel, &(stack->bts_btitem->bti_itup)); + newres = _bt_insertonpg(rel, pbuf, stack->bts_parent, + keysz, newskey, stack->bts_btitem, + NULL); + + pfree(newres); + pfree(newskey); - /* don't need the children anymore */ + /* we have now lost our lock on the parent buffer, and */ + /* need to get it back. */ + pbuf = _bt_getstackbuf(rel, stack, BT_WRITE); + } else { _bt_relbuf(rel, buf, BT_WRITE); _bt_relbuf(rel, rbuf, BT_WRITE); + } newskey = _bt_mkscankey(rel, &(new_item->bti_itup)); newres = _bt_insertonpg(rel, pbuf, stack->bts_parent, @@ -787,6 +872,8 @@ _bt_itemcmp(Relation rel, return (true); } +#if 0 +/* gone since updating in place doesn't work in general --djm 11/13/96 */ /* * _bt_updateitem() -- updates the key of the item identified by the * oid with the key of newItem (done in place if @@ -804,9 +891,9 @@ _bt_updateitem(Relation rel, OffsetNumber maxoff; OffsetNumber i; ItemPointerData itemPtrData; - BTItem item, itemCopy; + BTItem item; IndexTuple oldIndexTuple, newIndexTuple; - int newSize, oldSize, first; + int first; page = BufferGetPage(buf); maxoff = PageGetMaxOffsetNumber(page); @@ -825,48 +912,18 @@ _bt_updateitem(Relation rel, elog(FATAL, "_bt_getstackbuf was lying!!"); } + if(IndexTupleDSize(newItem->bti_itup) > + IndexTupleDSize(item->bti_itup)) { + elog(NOTICE, "trying to overwrite a smaller value with a bigger one in _bt_updateitem"); + elog(WARN, "this is not good."); + } + oldIndexTuple = &(item->bti_itup); newIndexTuple = &(newItem->bti_itup); - oldSize = DOUBLEALIGN(IndexTupleSize(oldIndexTuple)); - newSize = DOUBLEALIGN(IndexTupleSize(newIndexTuple)); -#ifdef NBTINSERT_PATCH_DEBUG - printf("_bt_updateitem: newSize=%d, oldSize=%d\n", newSize, oldSize); -#endif - /* - * If new and old item have the same size do the update in place - * and return. - */ - if (oldSize == newSize) { /* keep the original item pointer */ ItemPointerCopy(&(oldIndexTuple->t_tid), &itemPtrData); CopyIndexTuple(newIndexTuple, &oldIndexTuple); ItemPointerCopy(&itemPtrData, &(oldIndexTuple->t_tid)); - return; - } - - /* - * If new and old items have different size the update in place - * is not possible. In this case the old item is deleted and the - * new one is inserted. - * The new insertion should be done using _bt_insertonpg which - * would also takes care of the page splitting if needed, but - * unfortunately it doesn't work, so PageAddItem is used instead. - * There is the possibility that there is not enough space in the - * page and the item is not inserted. - */ - itemCopy = palloc(newSize); - memmove((char *) itemCopy, (char *) newItem, newSize); - itemCopy->bti_oid = item->bti_oid; - newIndexTuple = &(itemCopy->bti_itup); - ItemPointerCopy(&(oldIndexTuple->t_tid), &(newIndexTuple->t_tid)); - - /* - * Get the offset number of the item then delete it and insert - * the new item in the same place. - */ - i = OffsetNumberPrev(i); - PageIndexTupleDelete(page, i); - PageAddItem(page, (Item) itemCopy, newSize, i, LP_USED); - pfree(itemCopy); } +#endif diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index b5248b23eb3..1aa75f40271 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.9 1996/11/05 10:35:32 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.10 1996/11/13 20:47:18 scrappy Exp $ * * NOTES * This file contains only the public interface routines. @@ -74,6 +74,7 @@ btbuild(Relation heap, Oid hrelid, irelid; Node *pred, *oldPred; void *spool; + bool isunique; /* note that this is a new btree */ BuildingBtree = true; @@ -81,6 +82,9 @@ btbuild(Relation heap, pred = predInfo->pred; oldPred = predInfo->oldPred; + /* see if index is unique */ + isunique = IndexIsUniqueNoCache(RelationGetRelationId(index)); + /* initialize the btree index metadata page (if this is a new index) */ if (oldPred == NULL) _bt_metapinit(index); @@ -218,7 +222,7 @@ btbuild(Relation heap, if (FastBuild) { _bt_spool(index, btitem, spool); } else { - res = _bt_doinsert(index, btitem); + res = _bt_doinsert(index, btitem, isunique, false); } pfree(btitem); @@ -289,7 +293,7 @@ btbuild(Relation heap, * return an InsertIndexResult to the caller. */ InsertIndexResult -btinsert(Relation rel, Datum *datum, char *nulls, ItemPointer ht_ctid) +btinsert(Relation rel, Datum *datum, char *nulls, ItemPointer ht_ctid, bool is_update) { BTItem btitem; IndexTuple itup; @@ -304,7 +308,9 @@ btinsert(Relation rel, Datum *datum, char *nulls, ItemPointer ht_ctid) btitem = _bt_formitem(itup); - res = _bt_doinsert(rel, btitem); + res = _bt_doinsert(rel, btitem, + IndexIsUnique(RelationGetRelationId(rel)), is_update); + pfree(btitem); pfree(itup); diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 2866e026475..d6658ea701e 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.8 1996/11/05 10:35:34 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.9 1996/11/13 20:47:20 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -29,7 +29,7 @@ static BTStack _bt_searchr(Relation rel, int keysz, ScanKey scankey, Buffer *bufP, BTStack stack_in); static OffsetNumber _bt_firsteq(Relation rel, TupleDesc itupdesc, Page page, Size keysz, ScanKey scankey, OffsetNumber offnum); -static int _bt_compare(Relation rel, TupleDesc itupdesc, Page page, int keysz, ScanKey scankey, OffsetNumber offnum); +int _bt_compare(Relation rel, TupleDesc itupdesc, Page page, int keysz, ScanKey scankey, OffsetNumber offnum); static bool _bt_twostep(IndexScanDesc scan, Buffer *bufP, ScanDirection dir); static RetrieveIndexResult _bt_endpoint(IndexScanDesc scan, ScanDirection dir); @@ -413,7 +413,7 @@ _bt_firsteq(Relation rel, * a new minimal key is inserted, the leftmost entry on the leftmost * page is less than all possible keys, by definition. */ -static int +int _bt_compare(Relation rel, TupleDesc itupdesc, Page page, diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c index 6dfe3b7f37f..b851323d107 100644 --- a/src/backend/access/rtree/rtree.c +++ b/src/backend/access/rtree/rtree.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.9 1996/11/05 10:54:18 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.10 1996/11/13 20:47:35 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -277,7 +277,7 @@ rtbuild(Relation heap, * It doesn't do any work; just locks the relation and passes the buck. */ InsertIndexResult -rtinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid) +rtinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid, bool is_update) { InsertIndexResult res; IndexTuple itup; |