Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit14f6b38

Browse files
committed
+ NULLs handling
Actually required by multi-column indices support.We still don't use btree for 'A is (not) null', butnow btree keep items with NULL attrs using single rulefor placing/finding items on pages:NULLs greater NOT_NULLs and NULL = NULL.+ Bulkload code (nbtsort.c) support for multi-column indicesbuilding and NULLs.+ Fix for btendscan()->pfree(scanopaque) from Chris Dunlop.
1 parent427a879 commit14f6b38

File tree

5 files changed

+432
-107
lines changed

5 files changed

+432
-107
lines changed

‎src/backend/access/nbtree/nbtinsert.c

Lines changed: 112 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.10 1997/01/25 21:08:09momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.11 1997/03/2408:48:09vadim Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -19,6 +19,7 @@
1919
#include<access/nbtree.h>
2020
#include<access/heapam.h>
2121
#include<storage/bufmgr.h>
22+
#include<fmgr.h>
2223

2324
#ifndefHAVE_MEMMOVE
2425
# include<regex/utils.h>
@@ -33,6 +34,7 @@ static void _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
3334
staticOffsetNumber_bt_pgaddtup(Relationrel,Bufferbuf,intkeysz,ScanKeyitup_scankey,Sizeitemsize,BTItembtitem,BTItemafteritem);
3435
staticbool_bt_goesonpg(Relationrel,Bufferbuf,Sizekeysz,ScanKeyscankey,BTItemafteritem);
3536
staticvoid_bt_updateitem(Relationrel,Sizekeysz,Bufferbuf,Oidbti_oid,BTItemnewItem);
37+
staticbool_bt_isequal (TupleDescitupdesc,Pagepage,OffsetNumberoffnum,intkeysz,ScanKeyscankey);
3638

3739
/*
3840
* _bt_doinsert() -- Handle insertion of a single btitem in the tree.
@@ -104,8 +106,16 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, Relation heapRel
104106
itupdesc=RelationGetTupleDescriptor(rel);
105107
nbuf=InvalidBuffer;
106108
opaque= (BTPageOpaque)PageGetSpecialPointer(page);
109+
/*
110+
* _bt_compare returns 0 for (1,NULL) and (1,NULL) -
111+
* this's how we handling NULLs - and so we must not use
112+
* _bt_compare in real comparison, but only for
113+
* ordering/finding items on pages.- vadim 03/24/97
114+
107115
while ( !_bt_compare (rel, itupdesc, page,
108116
natts, itup_scankey, offset) )
117+
*/
118+
while (_bt_isequal (itupdesc,page,offset,natts,itup_scankey) )
109119
{/* they're equal */
110120
btitem= (BTItem)PageGetItem(page,PageGetItemId(page,offset));
111121
itup=&(btitem->bti_itup);
@@ -123,8 +133,8 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, Relation heapRel
123133
{/* move right ? */
124134
if (P_RIGHTMOST (opaque) )
125135
break;
126-
if (_bt_compare (rel,itupdesc,page,
127-
natts,itup_scankey,P_HIKEY) )
136+
if (!_bt_isequal (itupdesc,page,P_HIKEY,
137+
natts,itup_scankey) )
128138
break;
129139
/*
130140
* min key of the right page is the same,
@@ -939,18 +949,70 @@ _bt_itemcmp(Relation rel,
939949
IndexTupleindexTuple1,indexTuple2;
940950
DatumattrDatum1,attrDatum2;
941951
inti;
942-
boolisNull;
952+
boolisFirstNull,isSecondNull;
943953
boolcompare;
954+
booluseEqual= false;
955+
956+
if (strat==BTLessEqualStrategyNumber )
957+
{
958+
useEqual= true;
959+
strat=BTLessStrategyNumber;
960+
}
961+
elseif (strat==BTGreaterEqualStrategyNumber )
962+
{
963+
useEqual= true;
964+
strat=BTGreaterStrategyNumber;
965+
}
944966

945967
tupDes=RelationGetTupleDescriptor(rel);
946968
indexTuple1=&(item1->bti_itup);
947969
indexTuple2=&(item2->bti_itup);
948970

949971
for (i=1;i <=keysz;i++) {
950-
attrDatum1=index_getattr(indexTuple1,i,tupDes,&isNull);
951-
attrDatum2=index_getattr(indexTuple2,i,tupDes,&isNull);
952-
compare=_bt_invokestrat(rel,i,strat,attrDatum1,attrDatum2);
953-
if (!compare) {
972+
attrDatum1=index_getattr(indexTuple1,i,tupDes,&isFirstNull);
973+
attrDatum2=index_getattr(indexTuple2,i,tupDes,&isSecondNull);
974+
975+
/* see comments about NULLs handling in btbuild */
976+
if (isFirstNull )/* attr in item1 is NULL */
977+
{
978+
if (isSecondNull )/* attr in item2 is NULL too */
979+
compare= (strat==BTEqualStrategyNumber ) ? true : false;
980+
else
981+
compare= (strat==BTGreaterStrategyNumber ) ? true : false;
982+
}
983+
elseif (isSecondNull )/* attr in item1 is NOT_NULL and */
984+
{/* and attr in item2 is NULL */
985+
compare= (strat==BTLessStrategyNumber ) ? true : false;
986+
}
987+
else
988+
{
989+
compare=_bt_invokestrat(rel,i,strat,attrDatum1,attrDatum2);
990+
}
991+
992+
if (compare )/* true for one of ">, <, =" */
993+
{
994+
if (strat!=BTEqualStrategyNumber )
995+
return (true);
996+
}
997+
else/* false for one of ">, <, =" */
998+
{
999+
if (strat==BTEqualStrategyNumber )
1000+
return (false);
1001+
/*
1002+
* if original strat was "<=, >=" OR
1003+
* "<, >" but some attribute(s) left
1004+
* - need to test for Equality
1005+
*/
1006+
if (useEqual||i<keysz )
1007+
{
1008+
if (isFirstNull||isSecondNull )
1009+
compare= (isFirstNull&&isSecondNull ) ? true : false;
1010+
else
1011+
compare=_bt_invokestrat(rel,i,BTEqualStrategyNumber,
1012+
attrDatum1,attrDatum2);
1013+
if (compare )/* item1' and item2' attributes are equal */
1014+
continue;/* - try to compare next attributes */
1015+
}
9541016
return (false);
9551017
}
9561018
}
@@ -1015,3 +1077,45 @@ _bt_updateitem(Relation rel,
10151077
ItemPointerCopy(&itemPtrData,&(oldIndexTuple->t_tid));
10161078

10171079
}
1080+
1081+
/*
1082+
* _bt_isequal - used in _bt_doinsert in check for duplicates.
1083+
*
1084+
* Rule is simple: NOT_NULL not equal NULL, NULL not_equal NULL too.
1085+
*/
1086+
staticbool
1087+
_bt_isequal (TupleDescitupdesc,Pagepage,OffsetNumberoffnum,
1088+
intkeysz,ScanKeyscankey)
1089+
{
1090+
Datumdatum;
1091+
BTItembtitem;
1092+
IndexTupleitup;
1093+
ScanKeyentry;
1094+
AttrNumberattno;
1095+
longresult;
1096+
inti;
1097+
boolnull;
1098+
1099+
btitem= (BTItem)PageGetItem(page,PageGetItemId(page,offnum));
1100+
itup=&(btitem->bti_itup);
1101+
1102+
for (i=1;i <=keysz;i++)
1103+
{
1104+
entry=&scankey[i-1];
1105+
attno=entry->sk_attno;
1106+
Assert (attno==i);
1107+
datum=index_getattr(itup,attno,itupdesc,&null);
1108+
1109+
/* NULLs are not equal */
1110+
if (entry->sk_flags&SK_ISNULL||null )
1111+
return (false);
1112+
1113+
result= (long)FMGR_PTR2(entry->sk_func,entry->sk_procedure,
1114+
entry->sk_argument,datum);
1115+
if (result!=0)
1116+
return (false);
1117+
}
1118+
1119+
/* by here, the keys are equal */
1120+
return (true);
1121+
}

‎src/backend/access/nbtree/nbtree.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.16 1997/03/18 18:38:35 scrappy Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.17 1997/03/24 08:48:11 vadim Exp $
1212
*
1313
* NOTES
1414
* This file contains only the public interface routines.
@@ -219,11 +219,21 @@ btbuild(Relation heap,
219219
* artifact of the strategy map architecture chosen in 1986, not
220220
* of the way nulls are handled here.
221221
*/
222-
222+
/*
223+
* New comments: NULLs handling.
224+
* While we can't do NULL comparison, we can follow simple
225+
* rule for ordering items on btree pages - NULLs greater
226+
* NOT_NULLs and NULL = NULL is TRUE. Sure, it's just rule
227+
* for placing/finding items and no more - keytest'll return
228+
* FALSE for a = 5 for items having 'a' isNULL.
229+
* Look at _bt_skeycmp, _bt_compare and _bt_itemcmp for
230+
* how it works.- vadim 03/23/97
231+
223232
if (itup->t_info & INDEX_NULL_MASK) {
224233
pfree(itup);
225234
continue;
226235
}
236+
*/
227237

228238
itup->t_tid=htup->t_ctid;
229239
btitem=_bt_formitem(itup);
@@ -328,8 +338,12 @@ btinsert(Relation rel, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation
328338
itup=index_formtuple(RelationGetTupleDescriptor(rel),datum,nulls);
329339
itup->t_tid=*ht_ctid;
330340

341+
/*
342+
* See comments in btbuild.
343+
331344
if (itup->t_info & INDEX_NULL_MASK)
332345
return ((InsertIndexResult) NULL);
346+
*/
333347

334348
btitem=_bt_formitem(itup);
335349

@@ -423,7 +437,7 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
423437

424438
/* reset the scan key */
425439
so->numberOfKeys=scan->numberOfKeys;
426-
so->numberOfFirstKeys=0;
440+
so->numberOfFirstKeys=0;/* may be changed by _bt_orderkeys */
427441
so->qual_ok=1;/* may be changed by _bt_orderkeys */
428442
if (scan->numberOfKeys>0) {
429443
memmove(scan->keyData,
@@ -433,10 +447,7 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
433447
scankey,
434448
so->numberOfKeys*sizeof(ScanKeyData));
435449
/* order the keys in the qualification */
436-
if (so->numberOfKeys>1)
437-
_bt_orderkeys(scan->relation,so);
438-
else
439-
so->numberOfFirstKeys=1;
450+
_bt_orderkeys(scan->relation,so);
440451
}
441452

442453
/* finally, be sure that the scan exploits the tree order */
@@ -499,9 +510,10 @@ btendscan(IndexScanDesc scan)
499510
ItemPointerSetInvalid(iptr);
500511
}
501512

502-
pfree (scan->opaque);
503513
if (so->keyData!= (ScanKey)NULL )
504514
pfree (so->keyData);
515+
pfree (so);
516+
505517
_bt_dropscan(scan);
506518
}
507519

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp