88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.68 2006/01/17 00:09:01 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.69 2006/01/23 22:31:40 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -178,20 +178,21 @@ _bt_formitem(IndexTuple itup)
178178 * within each attribute may be done as a byproduct of the processing here,
179179 * but no other code depends on that.
180180 *
181- *Aside from preparing so->keyData[], this routine sets
182- *so->numberOfRequiredKeys to the number of quals that must be satisfied to
183- *continue the scan . _bt_checkkeys usesthis . For example, if the quals
181+ *The output keys are marked with flags SK_BT_REQFWD and/or SK_BT_REQBKWD
182+ *if they must be satisfied in order to continue the scan forward or backward
183+ *respectively . _bt_checkkeys usesthese flags . For example, if the quals
184184 * are "x = 1 AND y < 4 AND z < 5", then _bt_checkkeys will reject a tuple
185185 * (1,2,7), but we must continue the scan in case there are tuples (1,3,z).
186186 * But once we reach tuples like (1,4,z) we can stop scanning because no
187- * later tuples could match. This is reflected by setting
188- * so->numberOfRequiredKeys to 2, the number of leading keys that must be
189- * matched to continue the scan. In general, numberOfRequiredKeys is equal
190- * to the number of keys for leading attributes with "=" keys, plus the
191- * key(s) for the first non "=" attribute, which can be seen to be correct
192- * by considering the above example. Note in particular that if there are no
193- * keys for a given attribute, the keys for subsequent attributes can never
194- * be required; for instance "WHERE y = 4" requires a full-index scan.
187+ * later tuples could match. This is reflected by marking the x and y keys,
188+ * but not the z key, with SK_BT_REQFWD. In general, the keys for leading
189+ * attributes with "=" keys are marked both SK_BT_REQFWD and SK_BT_REQBKWD.
190+ * For the first attribute without an "=" key, any "<" and "<=" keys are
191+ * marked SK_BT_REQFWD while any ">" and ">=" keys are marked SK_BT_REQBKWD.
192+ * This can be seen to be correct by considering the above example. Note
193+ * in particular that if there are no keys for a given attribute, the keys for
194+ * subsequent attributes can never be required; for instance "WHERE y = 4"
195+ * requires a full-index scan.
195196 *
196197 * If possible, redundant keys are eliminated: we keep only the tightest
197198 * >/>= bound and the tightest </<= bound, and if there's an = key then
@@ -203,8 +204,9 @@ _bt_formitem(IndexTuple itup)
203204 * we could handle comparison of a RHS of the index datatype with a RHS of
204205 * another type, but that seems too much pain for too little gain.) So,
205206 * keys whose operator has a nondefault subtype (ie, its RHS is not of the
206- * index datatype) are ignored here, except for noting whether they impose
207- * an "=" condition or not.
207+ * index datatype) are ignored here, except for noting whether they include
208+ * an "=" condition or not. The logic about required keys still works if
209+ * we don't eliminate redundant keys.
208210 *
209211 * As a byproduct of this work, we can detect contradictory quals such
210212 * as "x = 1 AND x > 2". If we see that, we return so->quals_ok = FALSE,
@@ -239,7 +241,6 @@ _bt_preprocess_keys(IndexScanDesc scan)
239241/* initialize result variables */
240242so -> qual_ok = true;
241243so -> numberOfKeys = 0 ;
242- so -> numberOfRequiredKeys = 0 ;
243244scan -> keys_are_unique = false;
244245
245246if (numberOfKeys < 1 )
@@ -271,8 +272,27 @@ _bt_preprocess_keys(IndexScanDesc scan)
271272}
272273memcpy (outkeys ,inkeys ,sizeof (ScanKeyData ));
273274so -> numberOfKeys = 1 ;
274- if (cur -> sk_attno == 1 )
275- so -> numberOfRequiredKeys = 1 ;
275+ /* We can mark the qual as required if it's for first index col */
276+ if (outkeys -> sk_attno == 1 )
277+ {
278+ switch (outkeys -> sk_strategy )
279+ {
280+ case BTLessStrategyNumber :
281+ case BTLessEqualStrategyNumber :
282+ outkeys -> sk_flags |=SK_BT_REQFWD ;
283+ break ;
284+ case BTEqualStrategyNumber :
285+ outkeys -> sk_flags |= (SK_BT_REQFWD |SK_BT_REQBKWD );
286+ break ;
287+ case BTGreaterEqualStrategyNumber :
288+ case BTGreaterStrategyNumber :
289+ outkeys -> sk_flags |=SK_BT_REQBKWD ;
290+ break ;
291+ default :
292+ elog (ERROR ,"unrecognized StrategyNumber: %d" ,
293+ (int )outkeys -> sk_strategy );
294+ }
295+ }
276296return ;
277297}
278298
@@ -400,21 +420,40 @@ _bt_preprocess_keys(IndexScanDesc scan)
400420}
401421
402422/*
403- * Emit the cleaned-up keys into the outkeys[] array.
423+ * Emit the cleaned-up keys into the outkeys[] array, and then
424+ * mark them if they are required. They are required (possibly
425+ * only in one direction) if all attrs before this one had "=".
404426 */
405427for (j = BTMaxStrategyNumber ;-- j >=0 ;)
406428{
407429if (xform [j ])
408- memcpy (& outkeys [new_numberOfKeys ++ ],xform [j ],
409- sizeof (ScanKeyData ));
410- }
430+ {
431+ ScanKey outkey = & outkeys [new_numberOfKeys ++ ];
411432
412- /*
413- * If all attrs before this one had "=", include these keys into
414- * the required-keys count.
415- */
416- if (priorNumberOfEqualCols == attno - 1 )
417- so -> numberOfRequiredKeys = new_numberOfKeys ;
433+ memcpy (outkey ,xform [j ],sizeof (ScanKeyData ));
434+ if (priorNumberOfEqualCols == attno - 1 )
435+ {
436+ switch (outkey -> sk_strategy )
437+ {
438+ case BTLessStrategyNumber :
439+ case BTLessEqualStrategyNumber :
440+ outkey -> sk_flags |=SK_BT_REQFWD ;
441+ break ;
442+ case BTEqualStrategyNumber :
443+ outkey -> sk_flags |= (SK_BT_REQFWD |
444+ SK_BT_REQBKWD );
445+ break ;
446+ case BTGreaterEqualStrategyNumber :
447+ case BTGreaterStrategyNumber :
448+ outkey -> sk_flags |=SK_BT_REQBKWD ;
449+ break ;
450+ default :
451+ elog (ERROR ,"unrecognized StrategyNumber: %d" ,
452+ (int )outkey -> sk_strategy );
453+ }
454+ }
455+ }
456+ }
418457
419458/*
420459 * Exit loop here if done.
@@ -578,8 +617,7 @@ _bt_checkkeys(IndexScanDesc scan,
578617 * match" subset. On a backward scan, however, we should keep
579618 * going.
580619 */
581- if (ikey < so -> numberOfRequiredKeys &&
582- ScanDirectionIsForward (dir ))
620+ if ((key -> sk_flags & SK_BT_REQFWD )&& ScanDirectionIsForward (dir ))
583621* continuescan = false;
584622
585623/*
@@ -593,45 +631,21 @@ _bt_checkkeys(IndexScanDesc scan,
593631if (!DatumGetBool (test ))
594632{
595633/*
596- * Tuple fails this qual. If it's a required qual, then we may be
597- * able to conclude no further tuples will pass, either. We have
598- * to look at the scan direction and the qual type.
599- *
600- * Note: the only case in which we would keep going after failing
601- * a required qual is if there are partially-redundant quals that
602- * _bt_preprocess_keys() was unable to eliminate. For example,
603- * given "x > 4 AND x > 10" where both are cross-type comparisons
604- * and so not removable, we might start the scan at the x = 4
605- * boundary point.The "x > 10" condition will fail until we pass
606- * x = 10, but we must not stop the scan on its account.
634+ * Tuple fails this qual. If it's a required qual for the current
635+ * scan direction, then we can conclude no further tuples will
636+ * pass, either.
607637 *
608638 * Note: because we stop the scan as soon as any required equality
609639 * qual fails, it is critical that equality quals be used for the
610640 * initial positioning in _bt_first() when they are available. See
611641 * comments in _bt_first().
612642 */
613- if (ikey < so -> numberOfRequiredKeys )
614- {
615- switch (key -> sk_strategy )
616- {
617- case BTLessStrategyNumber :
618- case BTLessEqualStrategyNumber :
619- if (ScanDirectionIsForward (dir ))
620- * continuescan = false;
621- break ;
622- case BTEqualStrategyNumber :
623- * continuescan = false;
624- break ;
625- case BTGreaterEqualStrategyNumber :
626- case BTGreaterStrategyNumber :
627- if (ScanDirectionIsBackward (dir ))
628- * continuescan = false;
629- break ;
630- default :
631- elog (ERROR ,"unrecognized StrategyNumber: %d" ,
632- key -> sk_strategy );
633- }
634- }
643+ if ((key -> sk_flags & SK_BT_REQFWD )&&
644+ ScanDirectionIsForward (dir ))
645+ * continuescan = false;
646+ else if ((key -> sk_flags & SK_BT_REQBKWD )&&
647+ ScanDirectionIsBackward (dir ))
648+ * continuescan = false;
635649
636650/*
637651 * In any case, this indextuple doesn't match the qual.