aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/gist/gist.c2
-rw-r--r--src/backend/access/hash/hash.c4
-rw-r--r--src/backend/access/index/indexam.c7
-rw-r--r--src/backend/access/nbtree/nbtinsert.c147
-rw-r--r--src/backend/access/nbtree/nbtree.c14
-rw-r--r--src/backend/access/nbtree/nbtsearch.c6
-rw-r--r--src/backend/access/rtree/rtree.c4
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;