diff --git a/mysql-test/main/opt_hints_index.result b/mysql-test/main/opt_hints_index.result index 94ed697d12b..8d70e388cae 100644 --- a/mysql-test/main/opt_hints_index.result +++ b/mysql-test/main/opt_hints_index.result @@ -272,3 +272,96 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: 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 DROP TABLE t1; +# +# Hint NO_INDEX() disables all indexes if none of given index names is not resolved +# +CREATE TABLE t1 ( +a INT, +b INT, +PRIMARY KEY(a), +KEY ab(a, b) +); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +# By default, the index `ab` is used for grouping +EXPLAIN EXTENDED SELECT a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` +# Invalid index names are ignored, index `ab` is still used +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by +Warnings: +Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by +Warnings: +Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint +Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_GROUP_INDEX hint +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by +Warnings: +Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint +Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_GROUP_INDEX hint +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` +# This hint disables all indexes for grouping, so effectively it is the same +# as table-level hint NO_GROUP_INDEX(t1) +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, dcba, PRIMARY, ab)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 100.00 Using index; Using filesort +Warnings: +Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_GROUP_INDEX hint +Warning 4222 Unresolved index name `t1`@`select#1` `dcba` for NO_GROUP_INDEX hint +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` +# Compare the previous case with the table-level hint, results are the same: +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 4 100.00 Using index; Using filesort +Warnings: +Note 1003 select /*+ NO_GROUP_INDEX(`t1`@`select#1`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` +# Same set of tests as above but for the global `NO_INDEX()` hint +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by +Warnings: +Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by +Warnings: +Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint +Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 range NULL ab 4 NULL 4 100.00 Using index for group-by +Warnings: +Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint +Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint +Note 1003 select /*+ NO_INDEX(`t1`@`select#1` `bbb`,`abcd`,`PRIMARY`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY, ab)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using filesort +Warnings: +Warning 4222 Unresolved index name `t1`@`select#1` `bbb` for NO_INDEX hint +Warning 4222 Unresolved index name `t1`@`select#1` `abcd` for NO_INDEX hint +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` +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1)*/ a FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using filesort +Warnings: +Note 1003 select /*+ NO_INDEX(`t1`@`select#1`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` group by `test`.`t1`.`a` +DROP TABLE t1; +# +# End of 12.1 tests +# diff --git a/mysql-test/main/opt_hints_index.test b/mysql-test/main/opt_hints_index.test index abe704b4693..ef33264c30e 100644 --- a/mysql-test/main/opt_hints_index.test +++ b/mysql-test/main/opt_hints_index.test @@ -112,3 +112,48 @@ EXPLAIN EXTENDED DELETE FROM t1 WHERE a = 1 AND b = 2 AND c = 3; EXPLAIN EXTENDED DELETE /*+ NO_INDEX(t1 i_ab) */ FROM t1 WHERE a = 1 AND b = 2 AND c = 3; DROP TABLE t1; + +--echo # +--echo # Hint NO_INDEX() disables all indexes if none of given index names is not resolved +--echo # + +CREATE TABLE t1 ( + a INT, + b INT, + PRIMARY KEY(a), + KEY ab(a, b) +); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4); + +ANALYZE TABLE t1; + +# Warnings "Unresolved table/index name..." are generated during both prepare +# and execution stages. So disable PS protocol to avoid duplication +--disable_ps_protocol + +--echo # By default, the index `ab` is used for grouping +EXPLAIN EXTENDED SELECT a FROM t1 GROUP BY a; +--echo # Invalid index names are ignored, index `ab` is still used +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a; + +--echo # This hint disables all indexes for grouping, so effectively it is the same +--echo # as table-level hint NO_GROUP_INDEX(t1) +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1 bbb, dcba, PRIMARY, ab)*/ a FROM t1 GROUP BY a; +--echo # Compare the previous case with the table-level hint, results are the same: +EXPLAIN EXTENDED SELECT /*+ NO_GROUP_INDEX(t1)*/ a FROM t1 GROUP BY a; + +--echo # Same set of tests as above but for the global `NO_INDEX()` hint +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb)*/ a FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd)*/ a FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY)*/ a FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1 bbb, abcd, PRIMARY, ab)*/ a FROM t1 GROUP BY a; +EXPLAIN EXTENDED SELECT/*+ NO_INDEX(t1)*/ a FROM t1 GROUP BY a; + +--enable_ps_protocol +DROP TABLE t1; + +--echo # +--echo # End of 12.1 tests +--echo # diff --git a/sql/opt_hints.cc b/sql/opt_hints.cc index 661651fe04a..5d39bac4e70 100644 --- a/sql/opt_hints.cc +++ b/sql/opt_hints.cc @@ -552,14 +552,6 @@ bool Opt_hints_table::fix_key_hints(TABLE *table) fixing the child objects. */ set_fixed(); - if (is_specified(INDEX_HINT_ENUM)) - global_index_map.set_fixed(); - if (is_specified(JOIN_INDEX_HINT_ENUM)) - join_index_map.set_fixed(); - if (is_specified(GROUP_INDEX_HINT_ENUM)) - group_index_map.set_fixed(); - if (is_specified(ORDER_INDEX_HINT_ENUM)) - order_index_map.set_fixed(); /* Make sure that adjustment is called only once. */ DBUG_ASSERT(keyinfo_array.size() == 0); @@ -582,6 +574,26 @@ bool Opt_hints_table::fix_key_hints(TABLE *table) } } + /* + Fixing compound index hints. A compound hint is fixed in two cases: + - it is a table-level hint, i.e. does not have a list of index names + (like ORDER_INDEX(t1); + - it has a list of index names, and at least one of listed + index names is resolved successfully. So, NO_INDEX(t1 bad_idx) does not + become a table-level hint NO_INDEX(t1) if `bad_idx` cannnot be resolved. + */ + for (opt_hints_enum + hint_type : { INDEX_HINT_ENUM, JOIN_INDEX_HINT_ENUM, + GROUP_INDEX_HINT_ENUM, ORDER_INDEX_HINT_ENUM }) + { + if (is_specified(hint_type)) + { + Opt_hints_key_bitmap *bitmap= get_key_hint_bitmap(hint_type); + if (bitmap->is_table_level() || bitmap->bits_set() > 0) + bitmap->set_fixed(); + } + } + if (are_children_fully_fixed()) return false; diff --git a/sql/opt_hints.h b/sql/opt_hints.h index 30336558e3f..f03a37e50c3 100644 --- a/sql/opt_hints.h +++ b/sql/opt_hints.h @@ -648,10 +648,12 @@ public: void set_fixed() { fixed= true; } bool is_fixed() const { return fixed; } + bool is_table_level() const { return parsed_hint->is_table_level_hint(); } void set_key_map(uint i) { key_map.set_bit(i); } bool is_set_key_map(uint i) { return key_map.is_set(i); } bool is_key_map_clear_all() { return key_map.is_clear_all(); } + uint bits_set() { return key_map.bits_set(); } Key_map *get_key_map() { return &key_map; } }; diff --git a/sql/opt_hints_parser.cc b/sql/opt_hints_parser.cc index fb14006cabd..6dd6adfe2d5 100644 --- a/sql/opt_hints_parser.cc +++ b/sql/opt_hints_parser.cc @@ -588,7 +588,13 @@ bool Parser::Index_level_hint::resolve(Parse_context *pc) const const Lex_ident_sys key_conflict( STRING_WITH_LEN("another hint was already specified for this index")); - if (is_empty()) // Empty list of index names, i.e. it is a table level hint + /* + If no index names are given, this is a table level hint, for example: + GROUP_INDEX(t1), NO_MRR(t2). + Otherwise this is a group of index-level hints: + NO_INDEX(t1 idx1, idx2) NO_ICP(t2 idx_a, idx_b, idx_c) + */ + if (is_empty()) { uint warn_code= 0; if (is_compound_hint(hint_type) && diff --git a/sql/opt_hints_parser.h b/sql/opt_hints_parser.h index 0b26d2f3e1b..423593aef20 100644 --- a/sql/opt_hints_parser.h +++ b/sql/opt_hints_parser.h @@ -656,6 +656,14 @@ public: public: using AND4::AND4; + /* + If no index names are given, this is a table level hint, for example: + GROUP_INDEX(t1), NO_MRR(t2). + Otherwise this is an index-level hints: + NO_INDEX(t1 idx1, idx2) NO_ICP(t2 idx_a, idx_b, idx_c) + */ + bool is_table_level_hint() const { return is_empty(); } + bool resolve(Parse_context *pc) const; void append_args(THD *thd, String *str) const override; };