@@ -23957,6 +23957,90 @@ void compute_part_of_sort_key_for_equals(JOIN *join, TABLE *table,
23957
23957
}
23958
23958
23959
23959
23960
+ /*
23961
+ @brief
23962
+ This is called when switching table access to produce records
23963
+ in reverse order.
23964
+
23965
+ @detail
23966
+ - Disable "Range checked for each record" (Is this strictly necessary
23967
+ here?)
23968
+ - Disable Index Condition Pushdown and Rowid Filtering.
23969
+
23970
+ IndexConditionPushdownAndReverseScans, RowidFilteringAndReverseScans:
23971
+ Suppose we're computing
23972
+
23973
+ select * from t1
23974
+ where
23975
+ key1 between 10 and 20 and extra_condition
23976
+ order by key1 desc
23977
+
23978
+ here the range access uses a reverse-ordered scan on (1 <= key1 <= 10) and
23979
+ extra_condition is checked by either ICP or Rowid Filtering.
23980
+
23981
+ Also suppose that extra_condition happens to be false for rows of t1 that
23982
+ do not satisfy the "10 <= key1 <= 20" condition.
23983
+
23984
+ For forward ordered range scan, the SQL layer will make these calls:
23985
+
23986
+ h->read_range_first(RANGE(10 <= key1 <= 20));
23987
+ while (h->read_range_next()) { ... }
23988
+
23989
+ The storage engine sees the end endpoint of "key1<=20" and can stop scanning
23990
+ as soon as it encounters a row with key1>20.
23991
+
23992
+ For backward-ordered range scan, the SQL layer will make these calls:
23993
+
23994
+ h->index_read_map(key1=20, HA_READ_PREFIX_LAST_OR_PREV);
23995
+ while (h->index_prev()) {
23996
+ if (cmp_key(h->record, "key1=10" )<0)
23997
+ break; // end of range
23998
+ ...
23999
+ }
24000
+
24001
+ Note that the check whether we've walked beyond the key=10 endpoint is
24002
+ made at the SQL layer. The storage engine has no information about the left
24003
+ endpoint of the interval we're scanning. If all rows before that endpoint
24004
+ do not satisfy ICP condition or do not pass the Rowid Filter, the storage
24005
+ engine will enumerate the records until the table start.
24006
+
24007
+ In MySQL, the API is extended with set_end_range() call so that the storage
24008
+ engine "knows" when to stop scanning.
24009
+ */
24010
+
24011
+ static void prepare_for_reverse_ordered_access(JOIN_TAB *tab)
24012
+ {
24013
+ /* Cancel "Range checked for each record" */
24014
+ if (tab->use_quick == 2)
24015
+ {
24016
+ tab->use_quick= 1;
24017
+ tab->read_first_record= join_init_read_record;
24018
+ }
24019
+ /*
24020
+ Cancel Pushed Index Condition, as it doesn't work for reverse scans.
24021
+ */
24022
+ if (tab->select && tab->select->pre_idx_push_select_cond)
24023
+ {
24024
+ tab->set_cond(tab->select->pre_idx_push_select_cond);
24025
+ tab->table->file->cancel_pushed_idx_cond();
24026
+ }
24027
+ /*
24028
+ The same with Rowid Filter: it doesn't work with reverse scans so cancel
24029
+ it, too.
24030
+ */
24031
+ {
24032
+ /*
24033
+ Rowid Filter is initialized at a later stage. It is not pushed to
24034
+ the storage engine yet:
24035
+ */
24036
+ DBUG_ASSERT(!tab->table->file->pushed_rowid_filter);
24037
+ tab->range_rowid_filter_info= NULL;
24038
+ delete tab->rowid_filter;
24039
+ tab->rowid_filter= NULL;
24040
+ }
24041
+ }
24042
+
24043
+
23960
24044
/**
23961
24045
Test if we can skip the ORDER BY by using an index.
23962
24046
@@ -24409,23 +24493,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
24409
24493
tab->limit= 0;
24410
24494
goto use_filesort; // Reverse sort failed -> filesort
24411
24495
}
24412
- /*
24413
- Cancel Pushed Index Condition, as it doesn't work for reverse scans.
24414
- */
24415
- if (tab->select && tab->select->pre_idx_push_select_cond)
24416
- {
24417
- tab->set_cond(tab->select->pre_idx_push_select_cond);
24418
- tab->table->file->cancel_pushed_idx_cond();
24419
- }
24496
+ prepare_for_reverse_ordered_access(tab);
24497
+
24420
24498
if (select->quick == save_quick)
24421
24499
save_quick= 0; // make_reverse() consumed it
24422
24500
select->set_quick(tmp);
24423
- /* Cancel "Range checked for each record" */
24424
- if (tab->use_quick == 2)
24425
- {
24426
- tab->use_quick= 1;
24427
- tab->read_first_record= join_init_read_record;
24428
- }
24429
24501
}
24430
24502
else if (tab->type != JT_NEXT && tab->type != JT_REF_OR_NULL &&
24431
24503
tab->ref.key >= 0 && tab->ref.key_parts <= used_key_parts)
@@ -24438,20 +24510,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
24438
24510
*/
24439
24511
tab->read_first_record= join_read_last_key;
24440
24512
tab->read_record.read_record_func= join_read_prev_same;
24441
- /* Cancel "Range checked for each record" */
24442
- if (tab->use_quick == 2)
24443
- {
24444
- tab->use_quick= 1;
24445
- tab->read_first_record= join_init_read_record;
24446
- }
24447
- /*
24448
- Cancel Pushed Index Condition, as it doesn't work for reverse scans.
24449
- */
24450
- if (tab->select && tab->select->pre_idx_push_select_cond)
24451
- {
24452
- tab->set_cond(tab->select->pre_idx_push_select_cond);
24453
- tab->table->file->cancel_pushed_idx_cond();
24454
- }
24513
+ prepare_for_reverse_ordered_access(tab);
24455
24514
}
24456
24515
}
24457
24516
else if (select && select->quick)
0 commit comments