Skip to content

Commit ded4ed3

Browse files
committed
MDEV-30944 Range_rowid_filter::fill() leaves file->keyread at MAX_KEY
This test case exposed 2 different bugs: - When replacing a range with an index scan on a covering key in test_if_skip_sort_order() we didn't disable filtering. Filtering does not make much sense in this case. - Fixed by disabling filtering in this case. - Range_rowid_filter::fill() did not take into account that keyread could already active, which caused an assert when it tried to activate another keyread. - Fixed by remembering old keyread state at start and restoring it at end. Other things: - ha_start_keyread() allowed multiple calls. This is wrong, especially as we do no check if the index changed! I added an assert() to ensure that we don't call it there is already an active keyread. - ha_end_keyread() always called ha_extra(), even if keyread was not active. Added a check to avoid the extra call.
1 parent 3ea8f30 commit ded4ed3

File tree

7 files changed

+58
-7
lines changed

7 files changed

+58
-7
lines changed

mysql-test/main/rowid_filter_myisam.result

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,3 +681,17 @@ drop table t0;
681681
set optimizer_switch='rowid_filter=default';
682682
drop table name, flag2;
683683
drop table t1;
684+
#
685+
# MDEV-30944 Range_rowid_filter::fill() leaves file->keyread at MAX_KEY
686+
#
687+
CREATE TABLE t1 ( a varchar(30) , i int , id int, UNIQUE KEY id (id), KEY (i ,id ,a), KEY (a(1),i)) engine=myisam;
688+
INSERT INTO t1 VALUES('fej',NULL,1),('jeyw',8,2),(NULL,181,3),('wrkovd',9,4),('',NULL,5),('ko',NULL,6),('vdgzyxkop',217,7),('',7,8),('zy',0,9),('yxkopv',8,10),('kopv',1,11),('opv',4,12),('vc',9,13),('ri',1,14),('tkcn',1,15),('cnm',6,16),('m',0,17),('d',9,18),('e',28,19),(NULL,0,20);
689+
explain SELECT i, MAX( id ) FROM t1 WHERE ( a IS NULL OR a IN ('o','h') ) AND ( id BETWEEN 6 AND 7 OR id IN ( 8, 1) ) GROUP BY i;
690+
id select_type table type possible_keys key key_len ref rows Extra
691+
1 SIMPLE t1 index id,a i 43 NULL 20 Using where; Using index
692+
SELECT i, MAX( id ) FROM t1 WHERE ( a IS NULL OR a IN ('o','h') ) AND ( id BETWEEN 6 AND 7 OR id IN ( 8, 1) ) GROUP BY i;
693+
i MAX( id )
694+
drop table t1;
695+
#
696+
# End of 11.0 tests
697+
#

mysql-test/main/rowid_filter_myisam.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2028,3 +2028,17 @@ set optimizer_switch='rowid_filter=default';
20282028

20292029
drop table name, flag2;
20302030
drop table t1;
2031+
2032+
--echo #
2033+
--echo # MDEV-30944 Range_rowid_filter::fill() leaves file->keyread at MAX_KEY
2034+
--echo #
2035+
2036+
CREATE TABLE t1 ( a varchar(30) , i int , id int, UNIQUE KEY id (id), KEY (i ,id ,a), KEY (a(1),i)) engine=myisam;
2037+
INSERT INTO t1 VALUES('fej',NULL,1),('jeyw',8,2),(NULL,181,3),('wrkovd',9,4),('',NULL,5),('ko',NULL,6),('vdgzyxkop',217,7),('',7,8),('zy',0,9),('yxkopv',8,10),('kopv',1,11),('opv',4,12),('vc',9,13),('ri',1,14),('tkcn',1,15),('cnm',6,16),('m',0,17),('d',9,18),('e',28,19),(NULL,0,20);
2038+
explain SELECT i, MAX( id ) FROM t1 WHERE ( a IS NULL OR a IN ('o','h') ) AND ( id BETWEEN 6 AND 7 OR id IN ( 8, 1) ) GROUP BY i;
2039+
SELECT i, MAX( id ) FROM t1 WHERE ( a IS NULL OR a IN ('o','h') ) AND ( id BETWEEN 6 AND 7 OR id IN ( 8, 1) ) GROUP BY i;
2040+
drop table t1;
2041+
2042+
--echo #
2043+
--echo # End of 11.0 tests
2044+
--echo #

sql/handler.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3486,19 +3486,38 @@ class handler :public Sql_alloc
34863486
inline bool keyread_enabled() { return keyread < MAX_KEY; }
34873487
inline int ha_start_keyread(uint idx)
34883488
{
3489-
if (keyread_enabled())
3490-
return 0;
3489+
DBUG_ASSERT(!keyread_enabled());
34913490
keyread= idx;
34923491
return extra_opt(HA_EXTRA_KEYREAD, idx);
34933492
}
34943493
inline int ha_end_keyread()
34953494
{
3496-
if (!keyread_enabled())
3495+
if (!keyread_enabled()) /* Enably lazy usage */
34973496
return 0;
34983497
keyread= MAX_KEY;
34993498
return extra(HA_EXTRA_NO_KEYREAD);
35003499
}
35013500

3501+
/*
3502+
End any active keyread. Return state so that we can restore things
3503+
at end.
3504+
*/
3505+
int ha_end_active_keyread()
3506+
{
3507+
int org_keyread;
3508+
if (!keyread_enabled())
3509+
return MAX_KEY;
3510+
org_keyread= keyread;
3511+
ha_end_keyread();
3512+
return org_keyread;
3513+
}
3514+
/* Restore state to before ha_end_active_keyread */
3515+
void ha_restart_keyread(int org_keyread)
3516+
{
3517+
DBUG_ASSERT(!keyread_enabled());
3518+
if (org_keyread != MAX_KEY)
3519+
ha_start_keyread(org_keyread);
3520+
}
35023521
int check_collation_compatibility();
35033522
int check_long_hash_compatibility() const;
35043523
int ha_check_for_upgrade(HA_CHECK_OPT *check_opt);

sql/opt_range.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15801,7 +15801,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::reset(void)
1580115801
DBUG_ENTER("QUICK_GROUP_MIN_MAX_SELECT::reset");
1580215802

1580315803
seen_first_key= FALSE;
15804-
head->file->ha_start_keyread(index); /* We need only the key attributes */
15804+
if (!head->file->keyread_enabled())
15805+
head->file->ha_start_keyread(index); /* We need only the key attributes */
1580515806

1580615807
if ((result= file->ha_index_init(index,1)))
1580715808
{

sql/rowid_filter.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,11 +580,11 @@ bool Range_rowid_filter::fill()
580580
handler *file= table->file;
581581
THD *thd= table->in_use;
582582
QUICK_RANGE_SELECT* quick= (QUICK_RANGE_SELECT*) select->quick;
583-
584583
uint table_status_save= table->status;
585584
Item *pushed_idx_cond_save= file->pushed_idx_cond;
586585
uint pushed_idx_cond_keyno_save= file->pushed_idx_cond_keyno;
587586
bool in_range_check_pushed_down_save= file->in_range_check_pushed_down;
587+
int org_keyread;
588588

589589
table->status= 0;
590590
file->pushed_idx_cond= 0;
@@ -594,6 +594,7 @@ bool Range_rowid_filter::fill()
594594
/* We're going to just read rowids / clustered primary keys */
595595
table->prepare_for_position();
596596

597+
org_keyread= file->ha_end_active_keyread();
597598
file->ha_start_keyread(quick->index);
598599

599600
if (quick->init() || quick->reset())
@@ -612,6 +613,7 @@ bool Range_rowid_filter::fill()
612613
end:
613614
quick->range_end();
614615
file->ha_end_keyread();
616+
file->ha_restart_keyread(org_keyread);
615617

616618
table->status= table_status_save;
617619
file->pushed_idx_cond= pushed_idx_cond_save;

sql/sql_select.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26423,7 +26423,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
2642326423
if the table is accessed by the primary key
2642426424
*/
2642526425
if (tab->rowid_filter &&
26426-
table->file->is_clustering_key(tab->index))
26426+
(table->file->is_clustering_key(tab->index) ||
26427+
table->covering_keys.is_set(best_key)))
2642726428
tab->clear_range_rowid_filter();
2642826429

2642926430
if (tab->pre_idx_push_select_cond)

sql/table.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7477,7 +7477,7 @@ MY_BITMAP *TABLE::prepare_for_keyread(uint index, MY_BITMAP *map)
74777477
{
74787478
MY_BITMAP *backup= read_set;
74797479
DBUG_ENTER("TABLE::prepare_for_keyread");
7480-
if (!no_keyread)
7480+
if (!no_keyread && !file->keyread_enabled())
74817481
file->ha_start_keyread(index);
74827482
if (map != read_set || !is_clustering_key(index))
74837483
{

0 commit comments

Comments
 (0)