diff options
Diffstat (limited to 'src/backend/access/nbtree/nbtsearch.c')
-rw-r--r-- | src/backend/access/nbtree/nbtsearch.c | 131 |
1 files changed, 98 insertions, 33 deletions
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 2e802ee8527..99fb38f18ce 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.15 1997/03/18 18:38:41 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.16 1997/03/24 08:48:12 vadim Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ #include <storage/bufpage.h> #include <storage/bufmgr.h> #include <access/nbtree.h> +#include <catalog/pg_proc.h> #ifndef HAVE_MEMMOVE # include <regex/utils.h> @@ -238,7 +239,20 @@ _bt_skeycmp(Relation rel, Datum keyDatum; bool compare; bool isNull; + bool useEqual = false; + bool keyNull; + if ( strat == BTLessEqualStrategyNumber ) + { + useEqual = true; + strat = BTLessStrategyNumber; + } + else if ( strat == BTGreaterEqualStrategyNumber ) + { + useEqual = true; + strat = BTGreaterStrategyNumber; + } + item = (BTItem) PageGetItem(page, itemid); indexTuple = &(item->bti_itup); @@ -248,27 +262,60 @@ _bt_skeycmp(Relation rel, for (i=1; i <= keysz; i++) { entry = &scankey[i-1]; + Assert ( entry->sk_attno == i ); attrDatum = index_getattr(indexTuple, entry->sk_attno, tupDes, &isNull); keyDatum = entry->sk_argument; - - /* - * This may happen in a nested loop if an attribute used - * as scan key is null. DZ 29-10-1996 - */ - if ((entry->sk_flags & SK_ISNULL) || (isNull)) { - if ((entry->sk_flags & SK_ISNULL) && (isNull)) { - return (true); - } else { - return (false); - } + + /* see comments about NULLs handling in btbuild */ + if ( entry->sk_flags & SK_ISNULL ) /* key is NULL */ + { + Assert ( entry->sk_procedure == NullValueRegProcedure ); + keyNull = true; + if ( isNull ) + compare = ( strat == BTEqualStrategyNumber ) ? true : false; + else + compare = ( strat == BTGreaterStrategyNumber ) ? true : false; + } + else if ( isNull ) /* key is NOT_NULL and item is NULL */ + { + keyNull = false; + compare = ( strat == BTLessStrategyNumber ) ? true : false; + } + else + { + keyNull = false; + compare = _bt_invokestrat(rel, i, strat, keyDatum, attrDatum); } - compare = _bt_invokestrat(rel, i, strat, keyDatum, attrDatum); - if (!compare) + if ( compare ) /* true for one of ">, <, =" */ + { + if ( strat != BTEqualStrategyNumber ) + return (true); + } + 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 ( keyNull || isNull ) + compare = ( keyNull && isNull ) ? true : false; + else + compare = _bt_invokestrat(rel, i, BTEqualStrategyNumber, + keyDatum, attrDatum); + if ( compare ) /* key' and item' attributes are equal */ + continue; /* - try to compare next attributes */ + } return (false); + } } return (true); @@ -520,20 +567,24 @@ _bt_compare(Relation rel, attno = entry->sk_attno; datum = index_getattr(itup, attno, itupdesc, &null); - /* - * This may happen in a nested loop if an attribute used - * as scan key is null. DZ 29-10-1996 - */ - if ((entry->sk_flags & SK_ISNULL) || (null)) { - if ((entry->sk_flags & SK_ISNULL) && (null)) { - return (0); - } else { - return (null ? +1 : -1); - } + /* see comments about NULLs handling in btbuild */ + if ( entry->sk_flags & SK_ISNULL ) /* key is NULL */ + { + Assert ( entry->sk_procedure == NullValueRegProcedure ); + if ( null ) + tmpres = (long) 0; /* NULL "=" NULL */ + else + tmpres = (long) 1; /* NULL ">" NOT_NULL */ + } + else if ( null ) /* key is NOT_NULL and item is NULL */ + { + tmpres = (long) -1; /* NOT_NULL "<" NULL */ + } + else + { + tmpres = (long) FMGR_PTR2(entry->sk_func, entry->sk_procedure, + entry->sk_argument, datum); } - - tmpres = (long) FMGR_PTR2(entry->sk_func, entry->sk_procedure, - entry->sk_argument, datum); result = tmpres; /* if the keys are unequal, return the difference */ @@ -566,6 +617,7 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) BTItem btitem; IndexTuple itup; BTScanOpaque so; + Size keysok; rel = scan->relation; so = (BTScanOpaque) scan->opaque; @@ -596,8 +648,9 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = &btitem->bti_itup; - if (_bt_checkqual(scan, itup)) + if ( _bt_checkkeys (scan, itup, &keysok) ) { + Assert (keysok == so->numberOfKeys); res = FormRetrieveIndexResult(current, &(itup->t_tid)); /* remember which buffer we have pinned and locked */ @@ -605,7 +658,7 @@ _bt_next(IndexScanDesc scan, ScanDirection dir) return (res); } - } while ( _bt_checkforkeys (scan, itup, so->numberOfFirstKeys) ); + } while ( keysok >= so->numberOfFirstKeys ); ItemPointerSetInvalid(current); so->btso_curbuf = InvalidBuffer; @@ -644,6 +697,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) int result; BTScanOpaque so; ScanKeyData skdata; + Size keysok; so = (BTScanOpaque) scan->opaque; if ( so->qual_ok == 0 ) /* may be set by _bt_orderkeys */ @@ -663,6 +717,12 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * ordered to take advantage of index ordering) to position ourselves * at the right place in the scan. */ + /* _bt_orderkeys disallows it, but it's place to add some code latter */ + if ( so->keyData[0].sk_flags & SK_ISNULL ) + { + elog (WARN, "_bt_first: btree doesn't support is(not)null, yet"); + return ((RetrieveIndexResult) NULL); + } proc = index_getprocid(rel, 1, BTORDER_PROC); ScanKeyEntryInitialize(&skdata, so->keyData[0].sk_flags, 1, proc, so->keyData[0].sk_argument); @@ -706,6 +766,9 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) */ result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum); + + /* it's yet other place to add some code latter for is(not)null */ + strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure); switch (strat) { @@ -798,14 +861,14 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = &btitem->bti_itup; - if ( _bt_checkqual(scan, itup) ) + if ( _bt_checkkeys (scan, itup, &keysok) ) { res = FormRetrieveIndexResult(current, &(itup->t_tid)); /* remember which buffer we have pinned */ so->btso_curbuf = buf; } - else if ( _bt_checkforkeys (scan, itup, so->numberOfFirstKeys) ) + else if ( keysok >= so->numberOfFirstKeys ) { so->btso_curbuf = buf; return (_bt_next (scan, dir)); @@ -1081,6 +1144,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) IndexTuple itup; BTScanOpaque so; RetrieveIndexResult res; + Size keysok; rel = scan->relation; current = &(scan->currentItemData); @@ -1223,13 +1287,14 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) itup = &(btitem->bti_itup); /* see if we picked a winner */ - if (_bt_checkqual(scan, itup)) { + if ( _bt_checkkeys (scan, itup, &keysok) ) + { res = FormRetrieveIndexResult(current, &(itup->t_tid)); /* remember which buffer we have pinned */ so->btso_curbuf = buf; } - else if ( _bt_checkforkeys (scan, itup, so->numberOfFirstKeys) ) + else if ( keysok >= so->numberOfFirstKeys ) { so->btso_curbuf = buf; return (_bt_next (scan, dir)); |