8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
20
20
21
21
22
22
static 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 );
25
28
static void _bt_newroot (Relation rel ,Buffer lbuf ,Buffer rbuf );
26
29
static OffsetNumber _bt_pgaddtup (Relation rel ,Buffer buf ,int keysz ,ScanKey itup_scankey ,Size itemsize ,BTItem btitem ,BTItem afteritem );
27
30
static bool _bt_goesonpg (Relation rel ,Buffer buf ,Size keysz ,ScanKey scankey ,BTItem afteritem );
@@ -297,7 +300,7 @@ _bt_insertonpg(Relation rel,
297
300
hitemid = PageGetItemId (page ,P_HIKEY );
298
301
hitem = (BTItem )PageGetItem (page ,hitemid );
299
302
if (maxoff > P_HIKEY &&
300
- !_bt_itemcmp (rel ,keysz ,hitem ,
303
+ !_bt_itemcmp (rel ,keysz ,scankey , hitem ,
301
304
(BTItem )PageGetItem (page ,PageGetItemId (page ,P_FIRSTKEY )),
302
305
BTEqualStrategyNumber ))
303
306
elog (FATAL ,"btree: bad key on the page in the chain of duplicates" );
@@ -373,7 +376,8 @@ _bt_insertonpg(Relation rel,
373
376
{
374
377
itid = PageGetItemId (page ,offnum );
375
378
chkitem = (BTItem )PageGetItem (page ,itid );
376
- if (!_bt_itemcmp (rel ,keysz ,previtem ,chkitem ,
379
+ if (!_bt_itemcmp (rel ,keysz ,scankey ,
380
+ previtem ,chkitem ,
377
381
BTEqualStrategyNumber ))
378
382
{
379
383
if (currsize > maxsize )
@@ -471,9 +475,10 @@ _bt_insertonpg(Relation rel,
471
475
MAXALIGN (sizeof (BTPageOpaqueData ))
472
476
+ sizeof (ItemIdData );
473
477
llimit /=2 ;
474
- firstright = _bt_findsplitloc (rel ,page ,start ,maxoff ,llimit );
478
+ firstright = _bt_findsplitloc (rel ,keysz ,scankey ,
479
+ page ,start ,maxoff ,llimit );
475
480
476
- if (_bt_itemcmp (rel ,keysz ,
481
+ if (_bt_itemcmp (rel ,keysz ,scankey ,
477
482
(BTItem )PageGetItem (page ,PageGetItemId (page ,start )),
478
483
(BTItem )PageGetItem (page ,PageGetItemId (page ,firstright )),
479
484
BTEqualStrategyNumber ))
@@ -503,7 +508,8 @@ _bt_insertonpg(Relation rel,
503
508
ItemPointerSet (& (stack -> bts_btitem -> bti_itup .t_tid ),
504
509
bknum ,P_HIKEY );
505
510
pbuf = _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 ,
507
513
(BTItem )PageGetItem (page ,
508
514
PageGetItemId (page ,start )),
509
515
BTLessStrategyNumber ))
@@ -519,7 +525,7 @@ _bt_insertonpg(Relation rel,
519
525
}
520
526
521
527
/* split the buffer into left and right halves */
522
- rbuf = _bt_split (rel ,buf ,firstright );
528
+ rbuf = _bt_split (rel ,keysz , scankey , buf ,firstright );
523
529
524
530
/* which new page (left half or right half) gets the tuple? */
525
531
if (_bt_goesonpg (rel ,buf ,keysz ,scankey ,afteritem ))
@@ -550,7 +556,7 @@ _bt_insertonpg(Relation rel,
550
556
elog (FATAL ,"btree: un-shifted page is empty" );
551
557
lowLeftItem = (BTItem )PageGetItem (page ,
552
558
PageGetItemId (page ,P_FIRSTKEY ));
553
- if (_bt_itemcmp (rel ,keysz ,lowLeftItem ,
559
+ if (_bt_itemcmp (rel ,keysz ,scankey , lowLeftItem ,
554
560
(BTItem )PageGetItem (page ,PageGetItemId (page ,P_HIKEY )),
555
561
BTEqualStrategyNumber ))
556
562
lpageop -> btpo_flags |=BTP_CHAIN ;
@@ -613,7 +619,8 @@ l_spl:;
613
619
{
614
620
ritem = (BTItem )PageGetItem (rpage ,
615
621
PageGetItemId (rpage ,P_FIRSTKEY ));
616
- if (_bt_itemcmp (rel ,keysz ,ritem ,
622
+ if (_bt_itemcmp (rel ,keysz ,scankey ,
623
+ ritem ,
617
624
(BTItem )PageGetItem (rpage ,
618
625
PageGetItemId (rpage ,P_HIKEY )),
619
626
BTEqualStrategyNumber ))
@@ -663,13 +670,16 @@ l_spl:;
663
670
* possible in splitting leftmost page) and current parent
664
671
* item == new_item.- vadim 05/27/97
665
672
*/
666
- if (_bt_itemcmp (rel ,keysz ,stack -> bts_btitem ,new_item ,
673
+ if (_bt_itemcmp (rel ,keysz ,scankey ,
674
+ stack -> bts_btitem ,new_item ,
667
675
BTGreaterStrategyNumber )||
668
676
(!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 )))
673
683
{
674
684
do_update = true;
675
685
@@ -831,7 +841,8 @@ l_spl:;
831
841
*pin and lock on buf are maintained.
832
842
*/
833
843
static Buffer
834
- _bt_split (Relation rel ,Buffer buf ,OffsetNumber firstright )
844
+ _bt_split (Relation rel ,Size keysz ,ScanKey scankey ,
845
+ Buffer buf ,OffsetNumber firstright )
835
846
{
836
847
Buffer rbuf ;
837
848
Page origpage ;
@@ -915,7 +926,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
915
926
{
916
927
Size llimit = PageGetFreeSpace (leftpage ) /2 ;
917
928
918
- firstright = _bt_findsplitloc (rel ,origpage ,start ,maxoff ,llimit );
929
+ firstright = _bt_findsplitloc (rel ,keysz ,scankey ,
930
+ origpage ,start ,maxoff ,llimit );
919
931
}
920
932
921
933
for (i = start ;i <=maxoff ;i = OffsetNumberNext (i ))
@@ -1027,6 +1039,8 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright)
1027
1039
*/
1028
1040
static OffsetNumber
1029
1041
_bt_findsplitloc (Relation rel ,
1042
+ Size keysz ,
1043
+ ScanKey scankey ,
1030
1044
Page page ,
1031
1045
OffsetNumber start ,
1032
1046
OffsetNumber maxoff ,
@@ -1039,12 +1053,10 @@ _bt_findsplitloc(Relation rel,
1039
1053
BTItem safeitem ,
1040
1054
nxtitem ;
1041
1055
Size nbytes ;
1042
- int natts ;
1043
1056
1044
1057
if (start >=maxoff )
1045
1058
elog (FATAL ,"btree: cannot split if start (%d) >= maxoff (%d)" ,
1046
1059
start ,maxoff );
1047
- natts = rel -> rd_rel -> relnatts ;
1048
1060
saferight = start ;
1049
1061
safeitemid = PageGetItemId (page ,saferight );
1050
1062
nbytes = ItemIdGetLength (safeitemid )+ sizeof (ItemIdData );
@@ -1064,7 +1076,7 @@ _bt_findsplitloc(Relation rel,
1064
1076
* at isn't equal to the last safe one we saw, then it's our new
1065
1077
* safe tuple.
1066
1078
*/
1067
- if (!_bt_itemcmp (rel ,natts ,
1079
+ if (!_bt_itemcmp (rel ,keysz , scankey ,
1068
1080
safeitem ,nxtitem ,BTEqualStrategyNumber ))
1069
1081
{
1070
1082
safeitem = nxtitem ;
@@ -1345,92 +1357,94 @@ _bt_goesonpg(Relation rel,
1345
1357
}
1346
1358
1347
1359
/*
1348
- *_bt_itemcmp () -- compareitem1 to item2 using a requested
1349
- * strategy (<, <=, =, >=, >)
1360
+ *_bt_tuplecompare () -- comparetwo IndexTuples,
1361
+ * return -1, 0, or +1
1350
1362
*
1351
1363
*/
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 )
1358
1370
{
1359
1371
TupleDesc tupDes ;
1360
- IndexTuple indexTuple1 ,
1361
- indexTuple2 ;
1362
- Datum attrDatum1 ,
1363
- attrDatum2 ;
1364
1372
int 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 ;
1380
1374
1381
1375
tupDes = RelationGetDescr (rel );
1382
- indexTuple1 = & (item1 -> bti_itup );
1383
- indexTuple2 = & (item2 -> bti_itup );
1384
1376
1385
1377
for (i = 1 ;i <=keysz ;i ++ )
1386
1378
{
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 );
1389
1387
1390
1388
/* see comments about NULLs handling in btbuild */
1391
- if (isFirstNull )/* attr initem1 is NULL */
1389
+ if (isFirstNull )/* attr intuple1 is NULL */
1392
1390
{
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 ;
1395
1393
else
1396
- compare = ( strat == BTGreaterStrategyNumber ) ? true : false;
1394
+ compare = 1 ; /* NULL ">" not-NULL */
1397
1395
}
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 */
1401
1399
}
1402
1400
else
1403
- compare = _bt_invokestrat (rel ,i ,strat ,attrDatum1 ,attrDatum2 );
1404
-
1405
- if (compare )/* true for one of ">, <, =" */
1406
1401
{
1407
- if ( strat != BTEqualStrategyNumber )
1408
- return true ;
1402
+ compare = ( int32 ) FMGR_PTR2 ( & entry -> sk_func ,
1403
+ attrDatum1 , attrDatum2 ) ;
1409
1404
}
1410
- else
1411
- /* false for one of ">, <, =" */
1412
- {
1413
- if (strat == BTEqualStrategyNumber )
1414
- return false;
1415
1405
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 */
1432
1408
}
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;
1434
1448
}
1435
1449
1436
1450
/*
@@ -1585,7 +1599,7 @@ _bt_shift(Relation rel, Buffer buf, BTStack stack, int keysz,
1585
1599
/* init old page opaque */
1586
1600
pageop -> btpo_flags = npageop -> btpo_flags ;/* restore flags */
1587
1601
pageop -> btpo_flags &= ~BTP_CHAIN ;
1588
- if (_bt_itemcmp (rel ,keysz ,hikey ,btitem ,BTEqualStrategyNumber ))
1602
+ if (_bt_itemcmp (rel ,keysz ,scankey , hikey ,btitem ,BTEqualStrategyNumber ))
1589
1603
pageop -> btpo_flags |=BTP_CHAIN ;
1590
1604
pageop -> btpo_prev = npageop -> btpo_prev ;/* restore prev */
1591
1605
pageop -> btpo_next = nbknum ;/* next points to the new page */