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

Commit5b76bb1

Browse files
committed
Dept of second thoughts: my first cut at supporting "x IS NOT NULL" btree
indexscans would do the wrong thing if index_rescan() was called with aNULL instead of a new set of scankeys and the index was DESC order,because sk_strategy would not get flipped a second time. I thinkthat those provisions for a NULL argument are dead code now as far as thecore backend goes, but possibly somebody somewhere is still using it.In any case, this refactoring seems clearer, and it's definitely shorter.
1 parentc3705d8 commit5b76bb1

File tree

1 file changed

+75
-80
lines changed

1 file changed

+75
-80
lines changed

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

Lines changed: 75 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.96 2010/01/02 16:57:35 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.97 2010/01/03 05:39:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -32,7 +32,7 @@
3232
staticbool_bt_compare_scankey_args(IndexScanDescscan,ScanKeyop,
3333
ScanKeyleftarg,ScanKeyrightarg,
3434
bool*result);
35-
staticvoid_bt_mark_scankey_with_indoption(ScanKeyskey,int16*indoption);
35+
staticbool_bt_fix_scankey_strategy(ScanKeyskey,int16*indoption);
3636
staticvoid_bt_mark_scankey_required(ScanKeyskey);
3737
staticbool_bt_check_rowcompare(ScanKeyskey,
3838
IndexTupletuple,TupleDesctupdesc,
@@ -265,49 +265,9 @@ _bt_preprocess_keys(IndexScanDesc scan)
265265
/* We can short-circuit most of the work if there's just one key */
266266
if (numberOfKeys==1)
267267
{
268-
/*
269-
* We treat all btree operators as strict (even if they're not so
270-
* marked in pg_proc).This means that it is impossible for an
271-
* operator condition with a NULL comparison constant to succeed, and
272-
* we can reject it right away.
273-
*
274-
* However, we now also support "x IS NULL" clauses as search
275-
* conditions, so in that case keep going.The planner has not filled
276-
* in any particular strategy in this case, so set it to
277-
* BTEqualStrategyNumber --- we can treat IS NULL as an equality
278-
* operator for purposes of search strategy.
279-
*
280-
* Likewise, "x IS NOT NULL" is supported. We treat that as either
281-
* "less than NULL" in a NULLS LAST index, or "greater than NULL"
282-
* in a NULLS FIRST index. However, we have to flip those around in
283-
* a DESC index, to allow for the re-flipping that occurs elsewhere.
284-
*/
285-
if (cur->sk_flags&SK_ISNULL)
286-
{
287-
if (cur->sk_flags&SK_SEARCHNULL)
288-
{
289-
cur->sk_strategy=BTEqualStrategyNumber;
290-
cur->sk_subtype=InvalidOid;
291-
}
292-
elseif (cur->sk_flags&SK_SEARCHNOTNULL)
293-
{
294-
switch (indoption[cur->sk_attno-1]&
295-
(INDOPTION_DESC |INDOPTION_NULLS_FIRST))
296-
{
297-
case0:/* ASC / NULLS LAST */
298-
caseINDOPTION_DESC |INDOPTION_NULLS_FIRST:
299-
cur->sk_strategy=BTLessStrategyNumber;
300-
break;
301-
default:
302-
cur->sk_strategy=BTGreaterStrategyNumber;
303-
break;
304-
}
305-
cur->sk_subtype=InvalidOid;
306-
}
307-
else
308-
so->qual_ok= false;
309-
}
310-
_bt_mark_scankey_with_indoption(cur,indoption);
268+
/* Apply indoption to scankey (might change sk_strategy!) */
269+
if (!_bt_fix_scankey_strategy(cur,indoption))
270+
so->qual_ok= false;
311271
memcpy(outkeys,cur,sizeof(ScanKeyData));
312272
so->numberOfKeys=1;
313273
/* We can mark the qual as required if it's for first index col */
@@ -340,35 +300,12 @@ _bt_preprocess_keys(IndexScanDesc scan)
340300
{
341301
if (i<numberOfKeys)
342302
{
343-
/* See comments above about NULLs and IS NULL/NOT NULL handling */
344-
/* Note: we assume SK_ISNULL is never set in a row header key */
345-
if (cur->sk_flags&SK_ISNULL)
303+
/* Apply indoption to scankey (might change sk_strategy!) */
304+
if (!_bt_fix_scankey_strategy(cur,indoption))
346305
{
347-
if (cur->sk_flags&SK_SEARCHNULL)
348-
{
349-
cur->sk_strategy=BTEqualStrategyNumber;
350-
cur->sk_subtype=InvalidOid;
351-
}
352-
elseif (cur->sk_flags&SK_SEARCHNOTNULL)
353-
{
354-
switch (indoption[cur->sk_attno-1]&
355-
(INDOPTION_DESC |INDOPTION_NULLS_FIRST))
356-
{
357-
case0:/* ASC / NULLS LAST */
358-
caseINDOPTION_DESC |INDOPTION_NULLS_FIRST:
359-
cur->sk_strategy=BTLessStrategyNumber;
360-
break;
361-
default:
362-
cur->sk_strategy=BTGreaterStrategyNumber;
363-
break;
364-
}
365-
cur->sk_subtype=InvalidOid;
366-
}
367-
else
368-
{
369-
so->qual_ok= false;
370-
return;
371-
}
306+
/* NULL can't be matched, so give up */
307+
so->qual_ok= false;
308+
return;
372309
}
373310
}
374311

@@ -480,9 +417,6 @@ _bt_preprocess_keys(IndexScanDesc scan)
480417
memset(xform,0,sizeof(xform));
481418
}
482419

483-
/* apply indoption to scankey (might change sk_strategy!) */
484-
_bt_mark_scankey_with_indoption(cur,indoption);
485-
486420
/* check strategy this key's operator corresponds to */
487421
j=cur->sk_strategy-1;
488422

@@ -678,7 +612,7 @@ _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op,
678612
* indexscan initiated by syscache lookup will use cross-data-type
679613
* operators.)
680614
*
681-
* If the sk_strategy was flipped by_bt_mark_scankey_with_indoption, we
615+
* If the sk_strategy was flipped by_bt_fix_scankey_strategy, we
682616
* have to un-flip it to get the correct opfamily member.
683617
*/
684618
strat=op->sk_strategy;
@@ -708,29 +642,88 @@ _bt_compare_scankey_args(IndexScanDesc scan, ScanKey op,
708642
}
709643

710644
/*
711-
*Mark a scankey with info from the index's indoption array.
645+
*Adjust a scankey's strategy and flags setting as needed for indoptions.
712646
*
713647
* We copy the appropriate indoption value into the scankey sk_flags
714648
* (shifting to avoid clobbering system-defined flag bits). Also, if
715649
* the DESC option is set, commute (flip) the operator strategy number.
716650
*
651+
* A secondary purpose is to check for IS NULL/NOT NULL scankeys and set up
652+
* the strategy field correctly for them.
653+
*
654+
* Lastly, for ordinary scankeys (not IS NULL/NOT NULL), we check for a
655+
* NULL comparison value. Since all btree operators are assumed strict,
656+
* a NULL means that the qual cannot be satisfied. We return TRUE if the
657+
* comparison value isn't NULL, or FALSE if the scan should be abandoned.
658+
*
717659
* This function is applied to the *input* scankey structure; therefore
718660
* on a rescan we will be looking at already-processed scankeys. Hence
719661
* we have to be careful not to re-commute the strategy if we already did it.
720662
* It's a bit ugly to modify the caller's copy of the scankey but in practice
721663
* there shouldn't be any problem, since the index's indoptions are certainly
722664
* not going to change while the scankey survives.
723665
*/
724-
staticvoid
725-
_bt_mark_scankey_with_indoption(ScanKeyskey,int16*indoption)
666+
staticbool
667+
_bt_fix_scankey_strategy(ScanKeyskey,int16*indoption)
726668
{
727669
intaddflags;
728670

729671
addflags=indoption[skey->sk_attno-1] <<SK_BT_INDOPTION_SHIFT;
672+
673+
/*
674+
* We treat all btree operators as strict (even if they're not so marked
675+
* in pg_proc). This means that it is impossible for an operator condition
676+
* with a NULL comparison constant to succeed, and we can reject it right
677+
* away.
678+
*
679+
* However, we now also support "x IS NULL" clauses as search conditions,
680+
* so in that case keep going. The planner has not filled in any
681+
* particular strategy in this case, so set it to BTEqualStrategyNumber
682+
* --- we can treat IS NULL as an equality operator for purposes of search
683+
* strategy.
684+
*
685+
* Likewise, "x IS NOT NULL" is supported. We treat that as either "less
686+
* than NULL" in a NULLS LAST index, or "greater than NULL" in a NULLS
687+
* FIRST index.
688+
*/
689+
if (skey->sk_flags&SK_ISNULL)
690+
{
691+
/* SK_ISNULL shouldn't be set in a row header scankey */
692+
Assert(!(skey->sk_flags&SK_ROW_HEADER));
693+
694+
/* Set indoption flags in scankey (might be done already) */
695+
skey->sk_flags |=addflags;
696+
697+
/* Set correct strategy for IS NULL or NOT NULL search */
698+
if (skey->sk_flags&SK_SEARCHNULL)
699+
{
700+
skey->sk_strategy=BTEqualStrategyNumber;
701+
skey->sk_subtype=InvalidOid;
702+
}
703+
elseif (skey->sk_flags&SK_SEARCHNOTNULL)
704+
{
705+
if (skey->sk_flags&SK_BT_NULLS_FIRST)
706+
skey->sk_strategy=BTGreaterStrategyNumber;
707+
else
708+
skey->sk_strategy=BTLessStrategyNumber;
709+
skey->sk_subtype=InvalidOid;
710+
}
711+
else
712+
{
713+
/* regular qual, so it cannot be satisfied */
714+
return false;
715+
}
716+
717+
/* Needn't do the rest */
718+
return true;
719+
}
720+
721+
/* Adjust strategy for DESC, if we didn't already */
730722
if ((addflags&SK_BT_DESC)&& !(skey->sk_flags&SK_BT_DESC))
731723
skey->sk_strategy=BTCommuteStrategyNumber(skey->sk_strategy);
732724
skey->sk_flags |=addflags;
733725

726+
/* If it's a row header, fix row member flags and strategies similarly */
734727
if (skey->sk_flags&SK_ROW_HEADER)
735728
{
736729
ScanKeysubkey= (ScanKey)DatumGetPointer(skey->sk_argument);
@@ -747,6 +740,8 @@ _bt_mark_scankey_with_indoption(ScanKey skey, int16 *indoption)
747740
subkey++;
748741
}
749742
}
743+
744+
return true;
750745
}
751746

752747
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp