Skip to content

Commit 893761b

Browse files
Olernovvuvova
authored andcommitted
MDEV-37292 Hint NO_INDEX() disables all indexes if none of given index names is resolved
When a hint has a list of index names, for example, `NO_INDEX(t1 idx1, idx2)` there is a possibility that some or all of the listed index names will not be resolved. If none of them are resolved, the hint becomes a table-level hint, for example, `NO_INDEX(t1)`, which erroneously disables all indexes of `t1` instead of disabling only some of them. This commit addresses this issue by adding an additional check: a hint containing a list of index names is considered resolved only when at least one of the listed names is resolved successfully.
1 parent c329c43 commit 893761b

File tree

6 files changed

+175
-9
lines changed

6 files changed

+175
-9
lines changed

mysql-test/main/opt_hints_index.result

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,96 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
272272
Warnings:
273273
Note 1003 delete /*+ NO_INDEX(`t1`@`select#1` `i_ab`) */ from `test`.`t1` using dual where `test`.`t1`.`a` = 1 and `test`.`t1`.`b` = 2 and `test`.`t1`.`c` = 3
274274
DROP TABLE t1;
275+
#
276+
# Hint NO_INDEX() disables all indexes if none of given index names is not resolved
277+
#
278+
CREATE TABLE t1 (
279+
a INT,
280+
b INT,
281+
PRIMARY KEY(a),
282+
KEY ab(a, b)
283+
);
284+
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4);
285+
ANALYZE TABLE t1;
286+
Table Op Msg_type Msg_text
287+
test.t1 analyze status Engine-independent statistics collected
288+
test.t1 analyze status OK
289+
# By default, the index `ab` is used for grouping
290+
EXPLAIN EXTENDED SELECT a FROM t1 GROUP BY a;
291+
id select_type table type possible_keys key key_len ref rows filtered Extra
292+
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
293+
Warnings:
294+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
295+
# Invalid index names are ignored, index `ab` is still used
296+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a;
297+
id select_type table type possible_keys key key_len ref rows filtered Extra
298+
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
299+
Warnings:
300+
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint
301+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
302+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a;
303+
id select_type table type possible_keys key key_len ref rows filtered Extra
304+
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
305+
Warnings:
306+
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint
307+
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_GROUP_INDEX hint
308+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
309+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a;
310+
id select_type table type possible_keys key key_len ref rows filtered Extra
311+
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
312+
Warnings:
313+
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint
314+
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_GROUP_INDEX hint
315+
Note 1003 select /*+ NO_GROUP_INDEX(`t1`@`select#1` `bbb`,`abcd`,`PRIMARY`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
316+
# This hint disables all indexes for grouping, so effectively it is the same
317+
# as table-level hint NO_GROUP_INDEX(t1)
318+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, dcba, PRIMARY, ab)*/ a FROM t1 GROUP BY a;
319+
id select_type table type possible_keys key key_len ref rows filtered Extra
320+
1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 100.00 Using index; Using filesort
321+
Warnings:
322+
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint
323+
Warning 4222 Unresolved index name `t1`@`select#1` `dcba` for NO_GROUP_INDEX hint
324+
Note 1003 select /*+ NO_GROUP_INDEX(`t1`@`select#1` `bbb`,`dcba`,`PRIMARY`,`ab`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
325+
# Compare the previous case with the table-level hint, results are the same:
326+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1)*/ a FROM t1 GROUP BY a;
327+
id select_type table type possible_keys key key_len ref rows filtered Extra
328+
1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 100.00 Using index; Using filesort
329+
Warnings:
330+
Note 1003 select /*+ NO_GROUP_INDEX(`t1`@`select#1`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
331+
# Same set of tests as above but for the global `NO_INDEX()` hint
332+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a;
333+
id select_type table type possible_keys key key_len ref rows filtered Extra
334+
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
335+
Warnings:
336+
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint
337+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
338+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a;
339+
id select_type table type possible_keys key key_len ref rows filtered Extra
340+
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
341+
Warnings:
342+
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint
343+
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint
344+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
345+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a;
346+
id select_type table type possible_keys key key_len ref rows filtered Extra
347+
1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by
348+
Warnings:
349+
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint
350+
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint
351+
Note 1003 select /*+ NO_INDEX(`t1`@`select#1` `bbb`,`abcd`,`PRIMARY`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
352+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY, ab)*/ a FROM t1 GROUP BY a;
353+
id select_type table type possible_keys key key_len ref rows filtered Extra
354+
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using filesort
355+
Warnings:
356+
Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint
357+
Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint
358+
Note 1003 select /*+ NO_INDEX(`t1`@`select#1` `bbb`,`abcd`,`PRIMARY`,`ab`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
359+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1)*/ a FROM t1 GROUP BY a;
360+
id select_type table type possible_keys key key_len ref rows filtered Extra
361+
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using filesort
362+
Warnings:
363+
Note 1003 select /*+ NO_INDEX(`t1`@`select#1`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a`
364+
DROP TABLE t1;
365+
#
366+
# End of 12.1 tests
367+
#

mysql-test/main/opt_hints_index.test

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,48 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE a = 1 AND b = 2 AND c = 3;
112112
EXPLAIN EXTENDED DELETE /*+ NO_INDEX(t1 i_ab) */ FROM t1 WHERE a = 1 AND b = 2 AND c = 3;
113113

114114
DROP TABLE t1;
115+
116+
--echo #
117+
--echo # Hint NO_INDEX() disables all indexes if none of given index names is not resolved
118+
--echo #
119+
120+
CREATE TABLE t1 (
121+
a INT,
122+
b INT,
123+
PRIMARY KEY(a),
124+
KEY ab(a, b)
125+
);
126+
INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4);
127+
128+
ANALYZE TABLE t1;
129+
130+
# Warnings "Unresolved table/index name..." are generated during both prepare
131+
# and execution stages. So disable PS protocol to avoid duplication
132+
--disable_ps_protocol
133+
134+
--echo # By default, the index `ab` is used for grouping
135+
EXPLAIN EXTENDED SELECT a FROM t1 GROUP BY a;
136+
--echo # Invalid index names are ignored, index `ab` is still used
137+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a;
138+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a;
139+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a;
140+
141+
--echo # This hint disables all indexes for grouping, so effectively it is the same
142+
--echo # as table-level hint NO_GROUP_INDEX(t1)
143+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, dcba, PRIMARY, ab)*/ a FROM t1 GROUP BY a;
144+
--echo # Compare the previous case with the table-level hint, results are the same:
145+
EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1)*/ a FROM t1 GROUP BY a;
146+
147+
--echo # Same set of tests as above but for the global `NO_INDEX()` hint
148+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a;
149+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a;
150+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a;
151+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY, ab)*/ a FROM t1 GROUP BY a;
152+
EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1)*/ a FROM t1 GROUP BY a;
153+
154+
--enable_ps_protocol
155+
DROP TABLE t1;
156+
157+
--echo #
158+
--echo # End of 12.1 tests
159+
--echo #

sql/opt_hints.cc

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -552,14 +552,6 @@ bool Opt_hints_table::fix_key_hints(TABLE *table)
552552
fixing the child objects.
553553
*/
554554
set_fixed();
555-
if (is_specified(INDEX_HINT_ENUM))
556-
global_index_map.set_fixed();
557-
if (is_specified(JOIN_INDEX_HINT_ENUM))
558-
join_index_map.set_fixed();
559-
if (is_specified(GROUP_INDEX_HINT_ENUM))
560-
group_index_map.set_fixed();
561-
if (is_specified(ORDER_INDEX_HINT_ENUM))
562-
order_index_map.set_fixed();
563555

564556
/* Make sure that adjustment is called only once. */
565557
DBUG_ASSERT(keyinfo_array.size() == 0);
@@ -582,6 +574,26 @@ bool Opt_hints_table::fix_key_hints(TABLE *table)
582574
}
583575
}
584576

577+
/*
578+
Fixing compound index hints. A compound hint is fixed in two cases:
579+
- it is a table-level hint, i.e. does not have a list of index names
580+
(like ORDER_INDEX(t1);
581+
- it has a list of index names, and at least one of listed
582+
index names is resolved successfully. So, NO_INDEX(t1 bad_idx) does not
583+
become a table-level hint NO_INDEX(t1) if `bad_idx` cannnot be resolved.
584+
*/
585+
for (opt_hints_enum
586+
hint_type : { INDEX_HINT_ENUM, JOIN_INDEX_HINT_ENUM,
587+
GROUP_INDEX_HINT_ENUM, ORDER_INDEX_HINT_ENUM })
588+
{
589+
if (is_specified(hint_type))
590+
{
591+
Opt_hints_key_bitmap *bitmap= get_key_hint_bitmap(hint_type);
592+
if (bitmap->is_table_level() || bitmap->bits_set() > 0)
593+
bitmap->set_fixed();
594+
}
595+
}
596+
585597
if (are_children_fully_fixed())
586598
return false;
587599

sql/opt_hints.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +648,12 @@ class Opt_hints_key_bitmap
648648

649649
void set_fixed() { fixed= true; }
650650
bool is_fixed() const { return fixed; }
651+
bool is_table_level() const { return parsed_hint->is_table_level_hint(); }
651652

652653
void set_key_map(uint i) { key_map.set_bit(i); }
653654
bool is_set_key_map(uint i) { return key_map.is_set(i); }
654655
bool is_key_map_clear_all() { return key_map.is_clear_all(); }
656+
uint bits_set() { return key_map.bits_set(); }
655657
Key_map *get_key_map() { return &key_map; }
656658
};
657659

sql/opt_hints_parser.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,13 @@ bool Parser::Index_level_hint::resolve(Parse_context *pc) const
588588
const Lex_ident_sys key_conflict(
589589
STRING_WITH_LEN("another hint was already specified for this index"));
590590

591-
if (is_empty()) // Empty list of index names, i.e. it is a table level hint
591+
/*
592+
If no index names are given, this is a table level hint, for example:
593+
GROUP_INDEX(t1), NO_MRR(t2).
594+
Otherwise this is a group of index-level hints:
595+
NO_INDEX(t1 idx1, idx2) NO_ICP(t2 idx_a, idx_b, idx_c)
596+
*/
597+
if (is_empty())
592598
{
593599
uint warn_code= 0;
594600
if (is_compound_hint(hint_type) &&

sql/opt_hints_parser.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,14 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
656656
public:
657657
using AND4::AND4;
658658

659+
/*
660+
If no index names are given, this is a table level hint, for example:
661+
GROUP_INDEX(t1), NO_MRR(t2).
662+
Otherwise this is an index-level hints:
663+
NO_INDEX(t1 idx1, idx2) NO_ICP(t2 idx_a, idx_b, idx_c)
664+
*/
665+
bool is_table_level_hint() const { return is_empty(); }
666+
659667
bool resolve(Parse_context *pc) const;
660668
void append_args(THD *thd, String *str) const override;
661669
};

0 commit comments

Comments
 (0)