@@ -608,11 +608,11 @@ _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir)
608
608
* Also, for a DESC column, we commute (flip) all the sk_strategy numbers
609
609
* so that the index sorts in the desired direction.
610
610
*
611
- * One key purpose of this routine is to discover how many scan keys
612
- * must be satisfied to continue the scan. It also attempts to eliminate
613
- * redundant keys and detect contradictory keys. (If the index opfamily
614
- * provides incomplete sets of cross-type operators, we may fail to detect
615
- * redundant or contradictory keys, but we can survive that.)
611
+ * One key purpose of this routine is to discover which scan keys must be
612
+ * satisfied to continue the scan. It also attempts to eliminate redundant
613
+ * keys and detect contradictory keys. (If the index opfamily provides
614
+ * incomplete sets of cross-type operators, we may fail to detect redundant
615
+ * or contradictory keys, but we can survive that.)
616
616
*
617
617
* The output keys must be sorted by index attribute. Presently we expect
618
618
* (but verify) that the input keys are already so sorted --- this is done
@@ -647,6 +647,16 @@ _bt_advance_array_keys(IndexScanDesc scan, ScanDirection dir)
647
647
* </<= keys if we can't compare them. The logic about required keys still
648
648
* works if we don't eliminate redundant keys.
649
649
*
650
+ * Note that the reason we need direction-sensitive required-key flags is
651
+ * precisely that we may not be able to eliminate redundant keys. Suppose
652
+ * we have "x > 4::int AND x > 10::bigint", and we are unable to determine
653
+ * which key is more restrictive for lack of a suitable cross-type operator.
654
+ * _bt_first will arbitrarily pick one of the keys to do the initial
655
+ * positioning with. If it picks x > 4, then the x > 10 condition will fail
656
+ * until we reach index entries > 10; but we can't stop the scan just because
657
+ * x > 10 is failing. On the other hand, if we are scanning backwards, then
658
+ * failure of either key is indeed enough to stop the scan.
659
+ *
650
660
* As a byproduct of this work, we can detect contradictory quals such
651
661
* as "x = 1 AND x > 2". If we see that, we return so->qual_ok = FALSE,
652
662
* indicating the scan need not be run at all since no tuples can match.
@@ -1384,15 +1394,16 @@ _bt_checkkeys(IndexScanDesc scan,
1384
1394
}
1385
1395
1386
1396
/*
1387
- * Tuple fails this qual. If it's a required qual for the current
1388
- * scan direction, then we can conclude no further tuples will
1389
- * pass, either.
1397
+ * Tuple fails this qual. If it's a required qual, then we can
1398
+ * conclude no further tuples will pass, either. We can stop
1399
+ * regardless of the scan direction, because we know that NULLs
1400
+ * sort to one end or the other of the range of values. If this
1401
+ * tuple doesn't pass, then no future ones will either, until we
1402
+ * reach the next set of values of the higher-order index attrs
1403
+ * (if any) ... and those attrs must have equality quals, else
1404
+ * this one wouldn't be marked required.
1390
1405
*/
1391
- if ((key -> sk_flags & SK_BT_REQFWD ) &&
1392
- ScanDirectionIsForward (dir ))
1393
- * continuescan = false;
1394
- else if ((key -> sk_flags & SK_BT_REQBKWD ) &&
1395
- ScanDirectionIsBackward (dir ))
1406
+ if (key -> sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD ))
1396
1407
* continuescan = false;
1397
1408
1398
1409
/*
@@ -1403,32 +1414,15 @@ _bt_checkkeys(IndexScanDesc scan,
1403
1414
1404
1415
if (isNull )
1405
1416
{
1406
- if (key -> sk_flags & SK_BT_NULLS_FIRST )
1407
- {
1408
- /*
1409
- * Since NULLs are sorted before non-NULLs, we know we have
1410
- * reached the lower limit of the range of values for this
1411
- * index attr. On a backward scan, we can stop if this qual
1412
- * is one of the "must match" subset. On a forward scan,
1413
- * however, we should keep going.
1414
- */
1415
- if ((key -> sk_flags & SK_BT_REQBKWD ) &&
1416
- ScanDirectionIsBackward (dir ))
1417
- * continuescan = false;
1418
- }
1419
- else
1420
- {
1421
- /*
1422
- * Since NULLs are sorted after non-NULLs, we know we have
1423
- * reached the upper limit of the range of values for this
1424
- * index attr. On a forward scan, we can stop if this qual is
1425
- * one of the "must match" subset. On a backward scan,
1426
- * however, we should keep going.
1427
- */
1428
- if ((key -> sk_flags & SK_BT_REQFWD ) &&
1429
- ScanDirectionIsForward (dir ))
1430
- * continuescan = false;
1431
- }
1417
+ /*
1418
+ * The index entry is NULL, so it must fail this qual (we assume
1419
+ * all btree operators are strict). Furthermore, we know that
1420
+ * all remaining entries with the same higher-order index attr
1421
+ * values must be NULLs too. So, just as above, we can stop the
1422
+ * scan regardless of direction, if the qual is required.
1423
+ */
1424
+ if (key -> sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD ))
1425
+ * continuescan = false;
1432
1426
1433
1427
/*
1434
1428
* In any case, this indextuple doesn't match the qual.
@@ -1508,32 +1502,15 @@ _bt_check_rowcompare(ScanKey skey, IndexTuple tuple, TupleDesc tupdesc,
1508
1502
1509
1503
if (isNull )
1510
1504
{
1511
- if (subkey -> sk_flags & SK_BT_NULLS_FIRST )
1512
- {
1513
- /*
1514
- * Since NULLs are sorted before non-NULLs, we know we have
1515
- * reached the lower limit of the range of values for this
1516
- * index attr. On a backward scan, we can stop if this qual is
1517
- * one of the "must match" subset. On a forward scan,
1518
- * however, we should keep going.
1519
- */
1520
- if ((subkey -> sk_flags & SK_BT_REQBKWD ) &&
1521
- ScanDirectionIsBackward (dir ))
1522
- * continuescan = false;
1523
- }
1524
- else
1525
- {
1526
- /*
1527
- * Since NULLs are sorted after non-NULLs, we know we have
1528
- * reached the upper limit of the range of values for this
1529
- * index attr. On a forward scan, we can stop if this qual is
1530
- * one of the "must match" subset. On a backward scan,
1531
- * however, we should keep going.
1532
- */
1533
- if ((subkey -> sk_flags & SK_BT_REQFWD ) &&
1534
- ScanDirectionIsForward (dir ))
1535
- * continuescan = false;
1536
- }
1505
+ /*
1506
+ * The index entry is NULL, so it must fail this qual (we assume
1507
+ * all btree operators are strict). Furthermore, we know that
1508
+ * all remaining entries with the same higher-order index attr
1509
+ * values must be NULLs too. So, just as above, we can stop the
1510
+ * scan regardless of direction, if the qual is required.
1511
+ */
1512
+ if (subkey -> sk_flags & (SK_BT_REQFWD | SK_BT_REQBKWD ))
1513
+ * continuescan = false;
1537
1514
1538
1515
/*
1539
1516
* In any case, this indextuple doesn't match the qual.
0 commit comments