summaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtinsert.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/nbtree/nbtinsert.c')
-rw-r--r--src/backend/access/nbtree/nbtinsert.c188
1 files changed, 101 insertions, 87 deletions
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index a4153288dd..463a0f00fe 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.54 2000/01/26 05:55:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.55 2000/02/18 06:32:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,8 +20,11 @@
static InsertIndexResult _bt_insertonpg(Relation rel, Buffer buf, BTStack stack, int keysz, ScanKey scankey, BTItem btitem, BTItem afteritem);
-static Buffer _bt_split(Relation rel, Buffer buf, OffsetNumber firstright);
-static OffsetNumber _bt_findsplitloc(Relation rel, Page page, OffsetNumber start, OffsetNumber maxoff, Size llimit);
+static Buffer _bt_split(Relation rel, Size keysz, ScanKey scankey,
+ Buffer buf, OffsetNumber firstright);
+static OffsetNumber _bt_findsplitloc(Relation rel, Size keysz, ScanKey scankey,
+ Page page, OffsetNumber start,
+ OffsetNumber maxoff, Size llimit);
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);
@@ -297,7 +300,7 @@ _bt_insertonpg(Relation rel,
hitemid = PageGetItemId(page, P_HIKEY);
hitem = (BTItem) PageGetItem(page, hitemid);
if (maxoff > P_HIKEY &&
- !_bt_itemcmp(rel, keysz, hitem,
+ !_bt_itemcmp(rel, keysz, scankey, hitem,
(BTItem) PageGetItem(page, PageGetItemId(page, P_FIRSTKEY)),
BTEqualStrategyNumber))
elog(FATAL, "btree: bad key on the page in the chain of duplicates");
@@ -373,7 +376,8 @@ _bt_insertonpg(Relation rel,
{
itid = PageGetItemId(page, offnum);
chkitem = (BTItem) PageGetItem(page, itid);
- if (!_bt_itemcmp(rel, keysz, previtem, chkitem,
+ if (!_bt_itemcmp(rel, keysz, scankey,
+ previtem, chkitem,
BTEqualStrategyNumber))
{
if (currsize > maxsize)
@@ -471,9 +475,10 @@ _bt_insertonpg(Relation rel,
MAXALIGN(sizeof(BTPageOpaqueData))
+sizeof(ItemIdData);
llimit /= 2;
- firstright = _bt_findsplitloc(rel, page, start, maxoff, llimit);
+ firstright = _bt_findsplitloc(rel, keysz, scankey,
+ page, start, maxoff, llimit);
- if (_bt_itemcmp(rel, keysz,
+ if (_bt_itemcmp(rel, keysz, scankey,
(BTItem) PageGetItem(page, PageGetItemId(page, start)),
(BTItem) PageGetItem(page, PageGetItemId(page, firstright)),
BTEqualStrategyNumber))
@@ -503,7 +508,8 @@ _bt_insertonpg(Relation rel,
ItemPointerSet(&(stack->bts_btitem->bti_itup.t_tid),
bknum, P_HIKEY);
pbuf = _bt_getstackbuf(rel, stack, BT_WRITE);
- if (_bt_itemcmp(rel, keysz, stack->bts_btitem,
+ if (_bt_itemcmp(rel, keysz, scankey,
+ stack->bts_btitem,
(BTItem) PageGetItem(page,
PageGetItemId(page, start)),
BTLessStrategyNumber))
@@ -519,7 +525,7 @@ _bt_insertonpg(Relation rel,
}
/* split the buffer into left and right halves */
- rbuf = _bt_split(rel, buf, firstright);
+ rbuf = _bt_split(rel, keysz, scankey, buf, firstright);
/* which new page (left half or right half) gets the tuple? */
if (_bt_goesonpg(rel, buf, keysz, scankey, afteritem))
@@ -550,7 +556,7 @@ _bt_insertonpg(Relation rel,
elog(FATAL, "btree: un-shifted page is empty");
lowLeftItem = (BTItem) PageGetItem(page,
PageGetItemId(page, P_FIRSTKEY));
- if (_bt_itemcmp(rel, keysz, lowLeftItem,
+ if (_bt_itemcmp(rel, keysz, scankey, lowLeftItem,
(BTItem) PageGetItem(page, PageGetItemId(page, P_HIKEY)),
BTEqualStrategyNumber))
lpageop->btpo_flags |= BTP_CHAIN;
@@ -613,7 +619,8 @@ l_spl: ;
{
ritem = (BTItem) PageGetItem(rpage,
PageGetItemId(rpage, P_FIRSTKEY));
- if (_bt_itemcmp(rel, keysz, ritem,
+ if (_bt_itemcmp(rel, keysz, scankey,
+ ritem,
(BTItem) PageGetItem(rpage,
PageGetItemId(rpage, P_HIKEY)),
BTEqualStrategyNumber))
@@ -663,13 +670,16 @@ l_spl: ;
* possible in splitting leftmost page) and current parent
* item == new_item. - vadim 05/27/97
*/
- if (_bt_itemcmp(rel, keysz, stack->bts_btitem, new_item,
+ if (_bt_itemcmp(rel, keysz, scankey,
+ stack->bts_btitem, new_item,
BTGreaterStrategyNumber) ||
(!shifted &&
- _bt_itemcmp(rel, keysz, stack->bts_btitem,
- new_item, BTEqualStrategyNumber) &&
- _bt_itemcmp(rel, keysz, lowLeftItem,
- new_item, BTLessStrategyNumber)))
+ _bt_itemcmp(rel, keysz, scankey,
+ stack->bts_btitem, new_item,
+ BTEqualStrategyNumber) &&
+ _bt_itemcmp(rel, keysz, scankey,
+ lowLeftItem, new_item,
+ BTLessStrategyNumber)))
{
do_update = true;
@@ -831,7 +841,8 @@ l_spl: ;
* pin and lock on buf are maintained.
*/
static Buffer
-_bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
+_bt_split(Relation rel, Size keysz, ScanKey scankey,
+ Buffer buf, OffsetNumber firstright)
{
Buffer rbuf;
Page origpage;
@@ -915,7 +926,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
{
Size llimit = PageGetFreeSpace(leftpage) / 2;
- firstright = _bt_findsplitloc(rel, origpage, start, maxoff, llimit);
+ firstright = _bt_findsplitloc(rel, keysz, scankey,
+ origpage, start, maxoff, llimit);
}
for (i = start; i <= maxoff; i = OffsetNumberNext(i))
@@ -1027,6 +1039,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
*/
static OffsetNumber
_bt_findsplitloc(Relation rel,
+ Size keysz,
+ ScanKey scankey,
Page page,
OffsetNumber start,
OffsetNumber maxoff,
@@ -1039,12 +1053,10 @@ _bt_findsplitloc(Relation rel,
BTItem safeitem,
nxtitem;
Size nbytes;
- int natts;
if (start >= maxoff)
elog(FATAL, "btree: cannot split if start (%d) >= maxoff (%d)",
start, maxoff);
- natts = rel->rd_rel->relnatts;
saferight = start;
safeitemid = PageGetItemId(page, saferight);
nbytes = ItemIdGetLength(safeitemid) + sizeof(ItemIdData);
@@ -1064,7 +1076,7 @@ _bt_findsplitloc(Relation rel,
* at isn't equal to the last safe one we saw, then it's our new
* safe tuple.
*/
- if (!_bt_itemcmp(rel, natts,
+ if (!_bt_itemcmp(rel, keysz, scankey,
safeitem, nxtitem, BTEqualStrategyNumber))
{
safeitem = nxtitem;
@@ -1345,92 +1357,94 @@ _bt_goesonpg(Relation rel,
}
/*
- * _bt_itemcmp() -- compare item1 to item2 using a requested
- * strategy (<, <=, =, >=, >)
+ * _bt_tuplecompare() -- compare two IndexTuples,
+ * return -1, 0, or +1
*
*/
-bool
-_bt_itemcmp(Relation rel,
- Size keysz,
- BTItem item1,
- BTItem item2,
- StrategyNumber strat)
+int32
+_bt_tuplecompare(Relation rel,
+ Size keysz,
+ ScanKey scankey,
+ IndexTuple tuple1,
+ IndexTuple tuple2)
{
TupleDesc tupDes;
- IndexTuple indexTuple1,
- indexTuple2;
- Datum attrDatum1,
- attrDatum2;
int i;
- bool isFirstNull,
- isSecondNull;
- bool compare;
- bool useEqual = false;
-
- if (strat == BTLessEqualStrategyNumber)
- {
- useEqual = true;
- strat = BTLessStrategyNumber;
- }
- else if (strat == BTGreaterEqualStrategyNumber)
- {
- useEqual = true;
- strat = BTGreaterStrategyNumber;
- }
+ int32 compare = 0;
tupDes = RelationGetDescr(rel);
- indexTuple1 = &(item1->bti_itup);
- indexTuple2 = &(item2->bti_itup);
for (i = 1; i <= keysz; i++)
{
- attrDatum1 = index_getattr(indexTuple1, i, tupDes, &isFirstNull);
- attrDatum2 = index_getattr(indexTuple2, i, tupDes, &isSecondNull);
+ ScanKey entry = &scankey[i - 1];
+ Datum attrDatum1,
+ attrDatum2;
+ bool isFirstNull,
+ isSecondNull;
+
+ attrDatum1 = index_getattr(tuple1, i, tupDes, &isFirstNull);
+ attrDatum2 = index_getattr(tuple2, i, tupDes, &isSecondNull);
/* see comments about NULLs handling in btbuild */
- if (isFirstNull) /* attr in item1 is NULL */
+ if (isFirstNull) /* attr in tuple1 is NULL */
{
- if (isSecondNull) /* attr in item2 is NULL too */
- compare = (strat == BTEqualStrategyNumber) ? true : false;
+ if (isSecondNull) /* attr in tuple2 is NULL too */
+ compare = 0;
else
- compare = (strat == BTGreaterStrategyNumber) ? true : false;
+ compare = 1; /* NULL ">" not-NULL */
}
- else if (isSecondNull) /* attr in item1 is NOT_NULL and */
- { /* and attr in item2 is NULL */
- compare = (strat == BTLessStrategyNumber) ? true : false;
+ else if (isSecondNull) /* attr in tuple1 is NOT_NULL and */
+ { /* attr in tuple2 is NULL */
+ compare = -1; /* not-NULL "<" NULL */
}
else
- compare = _bt_invokestrat(rel, i, strat, attrDatum1, attrDatum2);
-
- if (compare) /* true for one of ">, <, =" */
{
- if (strat != BTEqualStrategyNumber)
- return true;
+ compare = (int32) FMGR_PTR2(&entry->sk_func,
+ attrDatum1, attrDatum2);
}
- else
-/* false for one of ">, <, =" */
- {
- if (strat == BTEqualStrategyNumber)
- return false;
- /*
- * if original strat was "<=, >=" OR "<, >" but some
- * attribute(s) left - need to test for Equality
- */
- if (useEqual || i < keysz)
- {
- if (isFirstNull || isSecondNull)
- compare = (isFirstNull && isSecondNull) ? true : false;
- else
- compare = _bt_invokestrat(rel, i, BTEqualStrategyNumber,
- attrDatum1, attrDatum2);
- if (compare) /* item1' and item2' attributes are equal */
- continue; /* - try to compare next attributes */
- }
- return false;
- }
+ if (compare != 0)
+ break; /* done when we find unequal attributes */
}
- return true;
+
+ return compare;
+}
+
+/*
+ * _bt_itemcmp() -- compare two BTItems using a requested
+ * strategy (<, <=, =, >=, >)
+ *
+ */
+bool
+_bt_itemcmp(Relation rel,
+ Size keysz,
+ ScanKey scankey,
+ BTItem item1,
+ BTItem item2,
+ StrategyNumber strat)
+{
+ int32 compare;
+
+ compare = _bt_tuplecompare(rel, keysz, scankey,
+ &(item1->bti_itup),
+ &(item2->bti_itup));
+
+ switch (strat)
+ {
+ case BTLessStrategyNumber:
+ return (bool) (compare < 0);
+ case BTLessEqualStrategyNumber:
+ return (bool) (compare <= 0);
+ case BTEqualStrategyNumber:
+ return (bool) (compare == 0);
+ case BTGreaterEqualStrategyNumber:
+ return (bool) (compare >= 0);
+ case BTGreaterStrategyNumber:
+ return (bool) (compare > 0);
+ }
+
+ elog(ERROR, "_bt_itemcmp: bogus strategy %d", (int) strat);
+ return false;
}
/*
@@ -1585,7 +1599,7 @@ _bt_shift(Relation rel, Buffer buf, BTStack stack, int keysz,
/* init old page opaque */
pageop->btpo_flags = npageop->btpo_flags; /* restore flags */
pageop->btpo_flags &= ~BTP_CHAIN;
- if (_bt_itemcmp(rel, keysz, hikey, btitem, BTEqualStrategyNumber))
+ if (_bt_itemcmp(rel, keysz, scankey, hikey, btitem, BTEqualStrategyNumber))
pageop->btpo_flags |= BTP_CHAIN;
pageop->btpo_prev = npageop->btpo_prev; /* restore prev */
pageop->btpo_next = nbknum; /* next points to the new page */