88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.54 2000/01/26 05:55:58 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.55 2000/02/18 06:32:33 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
2020
2121
2222static InsertIndexResult _bt_insertonpg (Relation rel ,Buffer buf ,BTStack stack ,int keysz ,ScanKey scankey ,BTItem btitem ,BTItem afteritem );
23- static Buffer _bt_split (Relation rel ,Buffer buf ,OffsetNumber firstright );
24- static OffsetNumber _bt_findsplitloc (Relation rel ,Page page ,OffsetNumber start ,OffsetNumber maxoff ,Size llimit );
23+ static Buffer _bt_split (Relation rel ,Size keysz ,ScanKey scankey ,
24+ Buffer buf ,OffsetNumber firstright );
25+ static OffsetNumber _bt_findsplitloc (Relation rel ,Size keysz ,ScanKey scankey ,
26+ Page page ,OffsetNumber start ,
27+ OffsetNumber maxoff ,Size llimit );
2528static void _bt_newroot (Relation rel ,Buffer lbuf ,Buffer rbuf );
2629static OffsetNumber _bt_pgaddtup (Relation rel ,Buffer buf ,int keysz ,ScanKey itup_scankey ,Size itemsize ,BTItem btitem ,BTItem afteritem );
2730static bool _bt_goesonpg (Relation rel ,Buffer buf ,Size keysz ,ScanKey scankey ,BTItem afteritem );
@@ -297,7 +300,7 @@ _bt_insertonpg(Relation rel,
297300hitemid = PageGetItemId (page ,P_HIKEY );
298301hitem = (BTItem )PageGetItem (page ,hitemid );
299302if (maxoff > P_HIKEY &&
300- !_bt_itemcmp (rel ,keysz ,hitem ,
303+ !_bt_itemcmp (rel ,keysz ,scankey , hitem ,
301304 (BTItem )PageGetItem (page ,PageGetItemId (page ,P_FIRSTKEY )),
302305BTEqualStrategyNumber ))
303306elog (FATAL ,"btree: bad key on the page in the chain of duplicates" );
@@ -373,7 +376,8 @@ _bt_insertonpg(Relation rel,
373376{
374377itid = PageGetItemId (page ,offnum );
375378chkitem = (BTItem )PageGetItem (page ,itid );
376- if (!_bt_itemcmp (rel ,keysz ,previtem ,chkitem ,
379+ if (!_bt_itemcmp (rel ,keysz ,scankey ,
380+ previtem ,chkitem ,
377381BTEqualStrategyNumber ))
378382{
379383if (currsize > maxsize )
@@ -471,9 +475,10 @@ _bt_insertonpg(Relation rel,
471475MAXALIGN (sizeof (BTPageOpaqueData ))
472476+ sizeof (ItemIdData );
473477llimit /=2 ;
474- firstright = _bt_findsplitloc (rel ,page ,start ,maxoff ,llimit );
478+ firstright = _bt_findsplitloc (rel ,keysz ,scankey ,
479+ page ,start ,maxoff ,llimit );
475480
476- if (_bt_itemcmp (rel ,keysz ,
481+ if (_bt_itemcmp (rel ,keysz ,scankey ,
477482 (BTItem )PageGetItem (page ,PageGetItemId (page ,start )),
478483 (BTItem )PageGetItem (page ,PageGetItemId (page ,firstright )),
479484BTEqualStrategyNumber ))
@@ -503,7 +508,8 @@ _bt_insertonpg(Relation rel,
503508ItemPointerSet (& (stack -> bts_btitem -> bti_itup .t_tid ),
504509bknum ,P_HIKEY );
505510pbuf = _bt_getstackbuf (rel ,stack ,BT_WRITE );
506- if (_bt_itemcmp (rel ,keysz ,stack -> bts_btitem ,
511+ if (_bt_itemcmp (rel ,keysz ,scankey ,
512+ stack -> bts_btitem ,
507513(BTItem )PageGetItem (page ,
508514PageGetItemId (page ,start )),
509515BTLessStrategyNumber ))
@@ -519,7 +525,7 @@ _bt_insertonpg(Relation rel,
519525}
520526
521527/* split the buffer into left and right halves */
522- rbuf = _bt_split (rel ,buf ,firstright );
528+ rbuf = _bt_split (rel ,keysz , scankey , buf ,firstright );
523529
524530/* which new page (left half or right half) gets the tuple? */
525531if (_bt_goesonpg (rel ,buf ,keysz ,scankey ,afteritem ))
@@ -550,7 +556,7 @@ _bt_insertonpg(Relation rel,
550556elog (FATAL ,"btree: un-shifted page is empty" );
551557lowLeftItem = (BTItem )PageGetItem (page ,
552558PageGetItemId (page ,P_FIRSTKEY ));
553- if (_bt_itemcmp (rel ,keysz ,lowLeftItem ,
559+ if (_bt_itemcmp (rel ,keysz ,scankey , lowLeftItem ,
554560(BTItem )PageGetItem (page ,PageGetItemId (page ,P_HIKEY )),
555561BTEqualStrategyNumber ))
556562lpageop -> btpo_flags |=BTP_CHAIN ;
@@ -613,7 +619,8 @@ l_spl:;
613619{
614620ritem = (BTItem )PageGetItem (rpage ,
615621PageGetItemId (rpage ,P_FIRSTKEY ));
616- if (_bt_itemcmp (rel ,keysz ,ritem ,
622+ if (_bt_itemcmp (rel ,keysz ,scankey ,
623+ ritem ,
617624(BTItem )PageGetItem (rpage ,
618625PageGetItemId (rpage ,P_HIKEY )),
619626BTEqualStrategyNumber ))
@@ -663,13 +670,16 @@ l_spl:;
663670 * possible in splitting leftmost page) and current parent
664671 * item == new_item.- vadim 05/27/97
665672 */
666- if (_bt_itemcmp (rel ,keysz ,stack -> bts_btitem ,new_item ,
673+ if (_bt_itemcmp (rel ,keysz ,scankey ,
674+ stack -> bts_btitem ,new_item ,
667675BTGreaterStrategyNumber )||
668676(!shifted &&
669- _bt_itemcmp (rel ,keysz ,stack -> bts_btitem ,
670- new_item ,BTEqualStrategyNumber )&&
671- _bt_itemcmp (rel ,keysz ,lowLeftItem ,
672- new_item ,BTLessStrategyNumber )))
677+ _bt_itemcmp (rel ,keysz ,scankey ,
678+ stack -> bts_btitem ,new_item ,
679+ BTEqualStrategyNumber )&&
680+ _bt_itemcmp (rel ,keysz ,scankey ,
681+ lowLeftItem ,new_item ,
682+ BTLessStrategyNumber )))
673683{
674684do_update = true;
675685
@@ -831,7 +841,8 @@ l_spl:;
831841 *pin and lock on buf are maintained.
832842 */
833843static Buffer
834- _bt_split (Relation rel ,Buffer buf ,OffsetNumber firstright )
844+ _bt_split (Relation rel ,Size keysz ,ScanKey scankey ,
845+ Buffer buf ,OffsetNumber firstright )
835846{
836847Buffer rbuf ;
837848Page origpage ;
@@ -915,7 +926,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
915926{
916927Size llimit = PageGetFreeSpace (leftpage ) /2 ;
917928
918- firstright = _bt_findsplitloc (rel ,origpage ,start ,maxoff ,llimit );
929+ firstright = _bt_findsplitloc (rel ,keysz ,scankey ,
930+ origpage ,start ,maxoff ,llimit );
919931}
920932
921933for (i = start ;i <=maxoff ;i = OffsetNumberNext (i ))
@@ -1027,6 +1039,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
10271039 */
10281040static OffsetNumber
10291041_bt_findsplitloc (Relation rel ,
1042+ Size keysz ,
1043+ ScanKey scankey ,
10301044Page page ,
10311045OffsetNumber start ,
10321046OffsetNumber maxoff ,
@@ -1039,12 +1053,10 @@ _bt_findsplitloc(Relation rel,
10391053BTItem safeitem ,
10401054nxtitem ;
10411055Size nbytes ;
1042- int natts ;
10431056
10441057if (start >=maxoff )
10451058elog (FATAL ,"btree: cannot split if start (%d) >= maxoff (%d)" ,
10461059start ,maxoff );
1047- natts = rel -> rd_rel -> relnatts ;
10481060saferight = start ;
10491061safeitemid = PageGetItemId (page ,saferight );
10501062nbytes = ItemIdGetLength (safeitemid )+ sizeof (ItemIdData );
@@ -1064,7 +1076,7 @@ _bt_findsplitloc(Relation rel,
10641076 * at isn't equal to the last safe one we saw, then it's our new
10651077 * safe tuple.
10661078 */
1067- if (!_bt_itemcmp (rel ,natts ,
1079+ if (!_bt_itemcmp (rel ,keysz , scankey ,
10681080safeitem ,nxtitem ,BTEqualStrategyNumber ))
10691081{
10701082safeitem = nxtitem ;
@@ -1345,92 +1357,94 @@ _bt_goesonpg(Relation rel,
13451357}
13461358
13471359/*
1348- *_bt_itemcmp () -- compareitem1 to item2 using a requested
1349- * strategy (<, <=, =, >=, >)
1360+ *_bt_tuplecompare () -- comparetwo IndexTuples,
1361+ * return -1, 0, or +1
13501362 *
13511363 */
1352- bool
1353- _bt_itemcmp (Relation rel ,
1354- Size keysz ,
1355- BTItem item1 ,
1356- BTItem item2 ,
1357- StrategyNumber strat )
1364+ int32
1365+ _bt_tuplecompare (Relation rel ,
1366+ Size keysz ,
1367+ ScanKey scankey ,
1368+ IndexTuple tuple1 ,
1369+ IndexTuple tuple2 )
13581370{
13591371TupleDesc tupDes ;
1360- IndexTuple indexTuple1 ,
1361- indexTuple2 ;
1362- Datum attrDatum1 ,
1363- attrDatum2 ;
13641372int i ;
1365- bool isFirstNull ,
1366- isSecondNull ;
1367- bool compare ;
1368- bool useEqual = false;
1369-
1370- if (strat == BTLessEqualStrategyNumber )
1371- {
1372- useEqual = true;
1373- strat = BTLessStrategyNumber ;
1374- }
1375- else if (strat == BTGreaterEqualStrategyNumber )
1376- {
1377- useEqual = true;
1378- strat = BTGreaterStrategyNumber ;
1379- }
1373+ int32 compare = 0 ;
13801374
13811375tupDes = RelationGetDescr (rel );
1382- indexTuple1 = & (item1 -> bti_itup );
1383- indexTuple2 = & (item2 -> bti_itup );
13841376
13851377for (i = 1 ;i <=keysz ;i ++ )
13861378{
1387- attrDatum1 = index_getattr (indexTuple1 ,i ,tupDes ,& isFirstNull );
1388- attrDatum2 = index_getattr (indexTuple2 ,i ,tupDes ,& isSecondNull );
1379+ ScanKey entry = & scankey [i - 1 ];
1380+ Datum attrDatum1 ,
1381+ attrDatum2 ;
1382+ bool isFirstNull ,
1383+ isSecondNull ;
1384+
1385+ attrDatum1 = index_getattr (tuple1 ,i ,tupDes ,& isFirstNull );
1386+ attrDatum2 = index_getattr (tuple2 ,i ,tupDes ,& isSecondNull );
13891387
13901388/* see comments about NULLs handling in btbuild */
1391- if (isFirstNull )/* attr initem1 is NULL */
1389+ if (isFirstNull )/* attr intuple1 is NULL */
13921390{
1393- if (isSecondNull )/* attr initem2 is NULL too */
1394- compare = ( strat == BTEqualStrategyNumber ) ? true : false ;
1391+ if (isSecondNull )/* attr intuple2 is NULL too */
1392+ compare = 0 ;
13951393else
1396- compare = ( strat == BTGreaterStrategyNumber ) ? true : false;
1394+ compare = 1 ; /* NULL ">" not-NULL */
13971395}
1398- else if (isSecondNull )/* attr initem1 is NOT_NULL and */
1399- {/*and attr initem2 is NULL */
1400- compare = ( strat == BTLessStrategyNumber ) ? true : false;
1396+ else if (isSecondNull )/* attr intuple1 is NOT_NULL and */
1397+ {/* attr intuple2 is NULL */
1398+ compare = -1 ; /* not-NULL "<" NULL */
14011399}
14021400else
1403- compare = _bt_invokestrat (rel ,i ,strat ,attrDatum1 ,attrDatum2 );
1404-
1405- if (compare )/* true for one of ">, <, =" */
14061401{
1407- if ( strat != BTEqualStrategyNumber )
1408- return true ;
1402+ compare = ( int32 ) FMGR_PTR2 ( & entry -> sk_func ,
1403+ attrDatum1 , attrDatum2 ) ;
14091404}
1410- else
1411- /* false for one of ">, <, =" */
1412- {
1413- if (strat == BTEqualStrategyNumber )
1414- return false;
14151405
1416- /*
1417- * if original strat was "<=, >=" OR "<, >" but some
1418- * attribute(s) left - need to test for Equality
1419- */
1420- if (useEqual || i < keysz )
1421- {
1422- if (isFirstNull || isSecondNull )
1423- compare = (isFirstNull && isSecondNull ) ? true : false;
1424- else
1425- compare = _bt_invokestrat (rel ,i ,BTEqualStrategyNumber ,
1426- attrDatum1 ,attrDatum2 );
1427- if (compare )/* item1' and item2' attributes are equal */
1428- continue ;/* - try to compare next attributes */
1429- }
1430- return false;
1431- }
1406+ if (compare != 0 )
1407+ break ;/* done when we find unequal attributes */
14321408}
1433- return true;
1409+
1410+ return compare ;
1411+ }
1412+
1413+ /*
1414+ *_bt_itemcmp() -- compare two BTItems using a requested
1415+ * strategy (<, <=, =, >=, >)
1416+ *
1417+ */
1418+ bool
1419+ _bt_itemcmp (Relation rel ,
1420+ Size keysz ,
1421+ ScanKey scankey ,
1422+ BTItem item1 ,
1423+ BTItem item2 ,
1424+ StrategyNumber strat )
1425+ {
1426+ int32 compare ;
1427+
1428+ compare = _bt_tuplecompare (rel ,keysz ,scankey ,
1429+ & (item1 -> bti_itup ),
1430+ & (item2 -> bti_itup ));
1431+
1432+ switch (strat )
1433+ {
1434+ case BTLessStrategyNumber :
1435+ return (bool ) (compare < 0 );
1436+ case BTLessEqualStrategyNumber :
1437+ return (bool ) (compare <=0 );
1438+ case BTEqualStrategyNumber :
1439+ return (bool ) (compare == 0 );
1440+ case BTGreaterEqualStrategyNumber :
1441+ return (bool ) (compare >=0 );
1442+ case BTGreaterStrategyNumber :
1443+ return (bool ) (compare > 0 );
1444+ }
1445+
1446+ elog (ERROR ,"_bt_itemcmp: bogus strategy %d" , (int )strat );
1447+ return false;
14341448}
14351449
14361450/*
@@ -1585,7 +1599,7 @@ _bt_shift(Relation rel, Buffer buf, BTStack stack, int keysz,
15851599/* init old page opaque */
15861600pageop -> btpo_flags = npageop -> btpo_flags ;/* restore flags */
15871601pageop -> btpo_flags &= ~BTP_CHAIN ;
1588- if (_bt_itemcmp (rel ,keysz ,hikey ,btitem ,BTEqualStrategyNumber ))
1602+ if (_bt_itemcmp (rel ,keysz ,scankey , hikey ,btitem ,BTEqualStrategyNumber ))
15891603pageop -> btpo_flags |=BTP_CHAIN ;
15901604pageop -> btpo_prev = npageop -> btpo_prev ;/* restore prev */
15911605pageop -> btpo_next = nbknum ;/* next points to the new page */