From 4ced4898fd0a713c54c5d698a5dc893945bb5b30 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 7 Dec 2023 17:44:43 +0400 Subject: [PATCH] MDEV-32958 Unusable key notes do not get reported for some operations Enable unusable key notes for non-equality predicates: <, <=, =>, >, BETWEEN, IN, LIKE Note, in some scenarios it displays duplicate notes, e.g. for queries with ORDER BY: SELECT * FROM t1 WHERE indexed_string_column >= 10 ORDER BY indexed_string_column LIMIT 5; This should be tolarable. Getting rid of the diplicate note completely would need a much more complex patch, which is not desiable in 10.6. Details: - Changing RANGE_OPT_PARAM::note_unusable_keys from bool to a new data type Item_func::Bitmap, so the caller can choose with a better granuality which predicates should raise unusable key notes inside the range optimizer: a. all predicates (=, <=>, <, <=, =>, >, BETWEEN, IN, LIKE) b. all predicates except equality (=, <=>) c. none of the predicates "b." is needed because in some scenarios equality predicates (=, <=>) send unusable key notes at an earlier stage, before the range optimizer, during update_ref_and_keys(). Calling the range optimizer with "all predicates" would produce duplicate notes for = and <=> in such cases. - Fixing get_quick_record_count() to call the range optimizer with "all predicates except equality" instead of "none of the predicates". Before this change the range optimizer suppressed all notes for non-equality predicates: <, <=, =>, >, BETWEEN, IN, LIKE. This actually fixes the reported problem. - Fixing JOIN::make_range_rowid_filters() to call the range optimizer with "all predicates except equality" instead of "all predicates". Before this change the range optimizer produced duplicate notes for = and <=> during a rowid_filter optimization. - Cleanup: Adding the op_collation argument to Field::raise_note_cannot_use_key_part() and displaying the operation collation rather than the argument collation in the unusable key note. This is important for operations with more than two arguments: BETWEEN and IN, e.g.: SELECT * FROM t1 WHERE column_utf8mb3_general_ci BETWEEN 'a' AND 'b' COLLATE utf8mb3_unicode_ci; SELECT * FROM t1 WHERE column_utf8mb3_general_ci IN ('a', 'b' COLLATE utf8mb3_unicode_ci); The note for 'a' now prints utf8mb3_unicode_ci as the collation. which is the collation of the entire operation: Cannot use key key1 part[0] for lookup: "`column_utf8mb3_general_ci`" of collation `utf8mb3_general_ci` >= "'a'" of collation `utf8mb3_unicode_ci` Before this change it printed the collation of 'a', so the note was confusing: Cannot use key key1 part[0] for lookup: "`column_utf8mb3_general_ci`" of collation `utf8mb3_general_ci` >= "'a'" of collation `utf8mb3_general_ci`" --- mysql-test/main/ctype_collate.result | 6 + mysql-test/main/func_in.result | 2 + mysql-test/main/group_min_max.result | 8 + mysql-test/main/mrr_icp_extra.result | 6 + .../main/myisam_explain_non_select_all.result | 6 + mysql-test/main/subselect4.result | 4 + mysql-test/main/type_varchar.result | 207 ++++++++++++++++++ mysql-test/main/type_varchar.test | 64 ++++++ mysql-test/main/view.result | 4 + mysql-test/suite/innodb/r/innodb_mysql.result | 12 + .../type_inet/type_inet6_myisam.result | 2 + sql/field.cc | 3 +- sql/field.h | 1 + sql/item_func.h | 32 +++ sql/opt_range.cc | 26 ++- sql/opt_range.h | 13 +- sql/sql_delete.cc | 3 +- sql/sql_help.cc | 3 +- sql/sql_select.cc | 32 ++- sql/sql_update.cc | 3 +- 20 files changed, 412 insertions(+), 25 deletions(-) diff --git a/mysql-test/main/ctype_collate.result b/mysql-test/main/ctype_collate.result index d53efe89b40..eafe7ff3d7b 100644 --- a/mysql-test/main/ctype_collate.result +++ b/mysql-test/main/ctype_collate.result @@ -614,18 +614,24 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` >= "'a'" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 IN ('a','b' COLLATE latin1_german1_ci); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 2 Using index condition EXPLAIN SELECT * FROM t1 WHERE s2 IN ('a','b' COLLATE latin1_german1_ci); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` = "'a'" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 1 Using index condition EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` like "'a' collate latin1_german1_ci" of collation `latin1_german1_ci` DROP TABLE t1; create table t1(f1 varchar(10) character set latin2 collate latin2_hungarian_ci, key(f1)); insert into t1 set f1=0x3F3F9DC73F; diff --git a/mysql-test/main/func_in.result b/mysql-test/main/func_in.result index 58dfcbcf31f..3a7a34e1011 100644 --- a/mysql-test/main/func_in.result +++ b/mysql-test/main/func_in.result @@ -531,6 +531,8 @@ Warning 1292 Truncated incorrect DECIMAL value: 'b' explain select f1 from t1 where f1 in (2,1); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index t1f1_idx t1f1_idx 2 NULL 3 Using where; Using index +Warnings: +Note 1105 Cannot use key `t1f1_idx` part[0] for lookup: `test`.`t1`.`f1` of type `char` = "2" of type `int` create table t2(f2 int, index t2f2(f2)); insert into t2 values(0),(1),(2); select f2 from t2 where f2 in ('a',2); diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result index e44d59bb6e9..dcc9d984a5c 100644 --- a/mysql-test/main/group_min_max.result +++ b/mysql-test/main/group_min_max.result @@ -3298,6 +3298,8 @@ explain SELECT b, min(a) FROM t1 WHERE a > ('0' = b) AND b = 'z' GROUP BY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref b b 4 const 1 Using where; Using index +Warnings: +Note 1105 Cannot use key `b` part[1] for lookup: `test`.`t1`.`a` of type `varchar` > "'0' = 'z'" of type `boolean` SELECT b, min(a) FROM t1 WHERE a > ('0' = b) AND b = 'z' GROUP BY b; b min(a) explain @@ -3984,12 +3986,18 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND DATE'2001-01-05' GROUP BY id; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL id 27 NULL 64 Using where; Using index +Warnings: +Note 1105 Cannot use key `id` part[1] for lookup: `test`.`t1`.`a` of type `varchar` >= "DATE'2001-01-04'" of type `date` EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND '2001-01-05' GROUP BY id; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL id 27 NULL 64 Using where; Using index +Warnings: +Note 1105 Cannot use key `id` part[1] for lookup: `test`.`t1`.`a` of type `varchar` >= "DATE'2001-01-04'" of type `date` EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND DATE'2001-01-05' GROUP BY id; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL id 27 NULL 64 Using where; Using index +Warnings: +Note 1105 Cannot use key `id` part[1] for lookup: `test`.`t1`.`a` of type `varchar` >= "('2001-01-04')" of type `date` DROP TABLE t1; # # MIN() optimization didn't work correctly with BETWEEN when using too diff --git a/mysql-test/main/mrr_icp_extra.result b/mysql-test/main/mrr_icp_extra.result index 1b33b008f35..48b3b91d271 100644 --- a/mysql-test/main/mrr_icp_extra.result +++ b/mysql-test/main/mrr_icp_extra.result @@ -38,18 +38,24 @@ id select_type table type possible_keys key key_len ref rows Extra EXPLAIN SELECT * FROM t1 WHERE s2 BETWEEN 'a' AND 'b' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` >= "'a'" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 IN ('a','b' COLLATE latin1_german1_ci); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 2 Using index condition; Rowid-ordered scan EXPLAIN SELECT * FROM t1 WHERE s2 IN ('a','b' COLLATE latin1_german1_ci); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` = "'a'" of collation `latin1_german1_ci` EXPLAIN SELECT * FROM t1 WHERE s1 LIKE 'a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range s1 s1 11 NULL 1 Using index condition; Rowid-ordered scan EXPLAIN SELECT * FROM t1 WHERE s2 LIKE 'a' COLLATE latin1_german1_ci; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL s2 NULL NULL NULL 10 Using where +Warnings: +Note 1105 Cannot use key `s2` part[0] for lookup: `test`.`t1`.`s2` of collation `latin1_swedish_ci` like "'a' collate latin1_german1_ci" of collation `latin1_german1_ci` DROP TABLE t1; # # diff --git a/mysql-test/main/myisam_explain_non_select_all.result b/mysql-test/main/myisam_explain_non_select_all.result index b72df544a3f..e28c2a0fec3 100644 --- a/mysql-test/main/myisam_explain_non_select_all.result +++ b/mysql-test/main/myisam_explain_non_select_all.result @@ -1528,6 +1528,8 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` <= "18" of type `int` Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` > 10 and `test`.`t1`.`i` <= 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -1591,6 +1593,8 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "18" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "18" of type `int` Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`i` AS `i` from `test`.`t1` where `test`.`t1`.`i` >= 10 and `test`.`t1`.`i` < 18 order by `test`.`t1`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value @@ -2142,6 +2146,8 @@ id select_type table type possible_keys key key_len ref rows filtered Extra Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` > "10" of type `int` Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` > "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t2`.`i` of type `char` <= "18" of type `int` Note 1003 select `test`.`t2`.`a` AS `a`,`test`.`t2`.`i` AS `i` from `test`.`t2` where `test`.`t2`.`i` > 10 and `test`.`t2`.`i` <= 18 order by `test`.`t2`.`i` limit 5 # Status of EXPLAIN EXTENDED "equivalent" SELECT query execution Variable_name Value diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result index 7a3c7b76ee4..6ef175bbfd4 100644 --- a/mysql-test/main/subselect4.result +++ b/mysql-test/main/subselect4.result @@ -1892,6 +1892,8 @@ id select_type table type possible_keys key key_len ref rows Extra 2 SUBQUERY SUBQUERY2_t1 index NULL col_int_key 5 NULL 2 Using index 2 SUBQUERY SUBQUERY2_t2 ALL col_varchar_key NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) 3 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 +Warnings: +Note 1105 Cannot use key `col_varchar_key` part[0] for lookup: `test`.`t1`.`col_varchar_key` of type `varchar` < "0" of type `bigint` SELECT col_int_key FROM t2 WHERE (SELECT SUBQUERY2_t1.col_int_key @@ -1917,6 +1919,8 @@ id select_type table type possible_keys key key_len ref rows Extra 2 SUBQUERY SUBQUERY2_t1 index NULL col_int_key 5 NULL 2 Using index 2 SUBQUERY SUBQUERY2_t2 ALL col_varchar_key NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join) 3 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1105 Cannot use key `col_varchar_key` part[0] for lookup: `test`.`t1`.`col_varchar_key` of type `varchar` < "0" of type `bigint` SELECT col_int_key FROM t2 WHERE (SELECT SUBQUERY2_t1.col_int_key diff --git a/mysql-test/main/type_varchar.result b/mysql-test/main/type_varchar.result index cc3ccc00907..6c0339a6010 100644 --- a/mysql-test/main/type_varchar.result +++ b/mysql-test/main/type_varchar.result @@ -967,10 +967,217 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL i NULL NULL NULL 31 Using where; Using filesort Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "30" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` > "30" of type `int` EXPLAIN SELECT * FROM t1 WHERE i>=30 ORDER BY i LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL i NULL NULL NULL 31 Using where; Using filesort Warnings: Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "30" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "30" of type `int` +DROP TABLE t1; +SET note_verbosity=DEFAULT; +# +# MDEV-32958 Unusable key notes do not get reported for some operations +# +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (c1 varchar(10), KEY(c1)) CHARACTER SET latin1; +INSERT INTO t1 VALUES ('a'); +INSERT INTO t1 VALUES ('b'); +INSERT INTO t1 VALUES ('c'); +INSERT INTO t1 VALUES ('d'); +INSERT INTO t1 VALUES ('e'); +INSERT INTO t1 VALUES ('f'); +INSERT INTO t1 VALUES ('g'); +INSERT INTO t1 VALUES ('h'); +INSERT INTO t1 VALUES ('i'); +INSERT INTO t1 VALUES ('j'); +EXPLAIN SELECT * FROM t1 WHERE c1=10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` = "10" of type `int` +SELECT * FROM t1 WHERE c1=10; +c1 +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` = "10" of type `int` +Warning 1292 Truncated incorrect DECIMAL value: 'a' +Warning 1292 Truncated incorrect DECIMAL value: 'b' +Warning 1292 Truncated incorrect DECIMAL value: 'c' +Warning 1292 Truncated incorrect DECIMAL value: 'd' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'f' +Warning 1292 Truncated incorrect DECIMAL value: 'g' +Warning 1292 Truncated incorrect DECIMAL value: 'h' +Warning 1292 Truncated incorrect DECIMAL value: 'i' +Warning 1292 Truncated incorrect DECIMAL value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1<10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` < "10" of type `int` +SELECT * FROM t1 WHERE c1<10; +c1 +a +b +c +d +e +f +g +h +i +j +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` < "10" of type `int` +Warning 1292 Truncated incorrect DECIMAL value: 'a' +Warning 1292 Truncated incorrect DECIMAL value: 'b' +Warning 1292 Truncated incorrect DECIMAL value: 'c' +Warning 1292 Truncated incorrect DECIMAL value: 'd' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'f' +Warning 1292 Truncated incorrect DECIMAL value: 'g' +Warning 1292 Truncated incorrect DECIMAL value: 'h' +Warning 1292 Truncated incorrect DECIMAL value: 'i' +Warning 1292 Truncated incorrect DECIMAL value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 10 AND 11; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` >= "10" of type `int` +SELECT * FROM t1 WHERE c1 BETWEEN 10 AND 11; +c1 +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` >= "10" of type `int` +Warning 1292 Truncated incorrect DECIMAL value: 'a' +Warning 1292 Truncated incorrect DECIMAL value: 'b' +Warning 1292 Truncated incorrect DECIMAL value: 'c' +Warning 1292 Truncated incorrect DECIMAL value: 'd' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'f' +Warning 1292 Truncated incorrect DECIMAL value: 'g' +Warning 1292 Truncated incorrect DECIMAL value: 'h' +Warning 1292 Truncated incorrect DECIMAL value: 'i' +Warning 1292 Truncated incorrect DECIMAL value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 10 AND '11'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` >= "10" of type `int` +SELECT * FROM t1 WHERE c1 BETWEEN 10 AND '11'; +c1 +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` >= "10" of type `int` +Warning 1292 Truncated incorrect DOUBLE value: 'a' +Warning 1292 Truncated incorrect DOUBLE value: 'b' +Warning 1292 Truncated incorrect DOUBLE value: 'c' +Warning 1292 Truncated incorrect DOUBLE value: 'd' +Warning 1292 Truncated incorrect DOUBLE value: 'e' +Warning 1292 Truncated incorrect DOUBLE value: 'f' +Warning 1292 Truncated incorrect DOUBLE value: 'g' +Warning 1292 Truncated incorrect DOUBLE value: 'h' +Warning 1292 Truncated incorrect DOUBLE value: 'i' +Warning 1292 Truncated incorrect DOUBLE value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1 IN (10,20); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` = "10" of type `int` +SELECT * FROM t1 WHERE c1 IN (10,20); +c1 +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of type `varchar` = "10" of type `int` +Warning 1292 Truncated incorrect DECIMAL value: 'a' +Warning 1292 Truncated incorrect DECIMAL value: 'b' +Warning 1292 Truncated incorrect DECIMAL value: 'c' +Warning 1292 Truncated incorrect DECIMAL value: 'd' +Warning 1292 Truncated incorrect DECIMAL value: 'e' +Warning 1292 Truncated incorrect DECIMAL value: 'f' +Warning 1292 Truncated incorrect DECIMAL value: 'g' +Warning 1292 Truncated incorrect DECIMAL value: 'h' +Warning 1292 Truncated incorrect DECIMAL value: 'i' +Warning 1292 Truncated incorrect DECIMAL value: 'j' +EXPLAIN SELECT * FROM t1 WHERE c1 IN (_latin1'a' COLLATE latin1_german2_ci,'b'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of collation `latin1_swedish_ci` = "_latin1'a' collate latin1_german2_ci" of collation `latin1_german2_ci` +SELECT * FROM t1 WHERE c1 IN (_latin1'a' COLLATE latin1_german2_ci,'b'); +c1 +a +b +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of collation `latin1_swedish_ci` = "_latin1'a' collate latin1_german2_ci" of collation `latin1_german2_ci` +EXPLAIN SELECT * FROM t1 WHERE c1 IN ('a',_latin1'b' COLLATE latin1_german2_ci); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index c1 c1 13 NULL 10 Using where; Using index +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of collation `latin1_swedish_ci` = "'a'" of collation `latin1_german2_ci` +SELECT * FROM t1 WHERE c1 IN ('a',_latin1'b' COLLATE latin1_german2_ci); +c1 +a +b +Warnings: +Note 1105 Cannot use key `c1` part[0] for lookup: `test`.`t1`.`c1` of collation `latin1_swedish_ci` = "'a'" of collation `latin1_german2_ci` +DROP TABLE t1; +CREATE TABLE t1(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), +(20),(21),(22),(23),(24),(25),(26),(27),(28),(29), +(30),(31),(32),(33),(34),(35); +EXPLAIN SELECT * FROM t1 WHERE i >= 10 ORDER BY i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL i NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +SELECT * FROM t1 WHERE i >= 10 ORDER BY i LIMIT 5; +a i +NULL 10 +NULL 11 +NULL 12 +NULL 13 +NULL 14 +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` >= "10" of type `int` +EXPLAIN UPDATE t1 SET a = 1 WHERE i = 10 ORDER BY a, i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` = "10" of type `int` +EXPLAIN UPDATE t1 SET a = 1 WHERE i < 10 ORDER BY a, i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "10" of type `int` +EXPLAIN DELETE FROM t1 WHERE i = 10 ORDER BY a, i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` = "10" of type `int` +EXPLAIN DELETE FROM t1 WHERE i < 10 ORDER BY a, i LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where; Using filesort +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "10" of type `int` +EXPLAIN UPDATE t1 SET a = 1 WHERE i = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` = "10" of type `int` +EXPLAIN UPDATE t1 SET a = 1 WHERE i < 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "10" of type `int` +EXPLAIN DELETE FROM t1 WHERE i = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` = "10" of type `int` +EXPLAIN DELETE FROM t1 WHERE i < 10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 26 Using where +Warnings: +Note 1105 Cannot use key `i` part[0] for lookup: `test`.`t1`.`i` of type `char` < "10" of type `int` DROP TABLE t1; SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/type_varchar.test b/mysql-test/main/type_varchar.test index 620d25f3f7f..feb270272c1 100644 --- a/mysql-test/main/type_varchar.test +++ b/mysql-test/main/type_varchar.test @@ -434,3 +434,67 @@ EXPLAIN SELECT * FROM t1 WHERE i>30 ORDER BY i LIMIT 5; EXPLAIN SELECT * FROM t1 WHERE i>=30 ORDER BY i LIMIT 5; DROP TABLE t1; SET note_verbosity=DEFAULT; + + +--echo # +--echo # MDEV-32958 Unusable key notes do not get reported for some operations +--echo # + +SET note_verbosity=unusable_keys; +CREATE TABLE t1 (c1 varchar(10), KEY(c1)) CHARACTER SET latin1; +INSERT INTO t1 VALUES ('a'); +INSERT INTO t1 VALUES ('b'); +INSERT INTO t1 VALUES ('c'); +INSERT INTO t1 VALUES ('d'); +INSERT INTO t1 VALUES ('e'); +INSERT INTO t1 VALUES ('f'); +INSERT INTO t1 VALUES ('g'); +INSERT INTO t1 VALUES ('h'); +INSERT INTO t1 VALUES ('i'); +INSERT INTO t1 VALUES ('j'); + +EXPLAIN SELECT * FROM t1 WHERE c1=10; +SELECT * FROM t1 WHERE c1=10; + +EXPLAIN SELECT * FROM t1 WHERE c1<10; +SELECT * FROM t1 WHERE c1<10; + +EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 10 AND 11; +SELECT * FROM t1 WHERE c1 BETWEEN 10 AND 11; + +EXPLAIN SELECT * FROM t1 WHERE c1 BETWEEN 10 AND '11'; +SELECT * FROM t1 WHERE c1 BETWEEN 10 AND '11'; + +EXPLAIN SELECT * FROM t1 WHERE c1 IN (10,20); +SELECT * FROM t1 WHERE c1 IN (10,20); + +EXPLAIN SELECT * FROM t1 WHERE c1 IN (_latin1'a' COLLATE latin1_german2_ci,'b'); +SELECT * FROM t1 WHERE c1 IN (_latin1'a' COLLATE latin1_german2_ci,'b'); + +EXPLAIN SELECT * FROM t1 WHERE c1 IN ('a',_latin1'b' COLLATE latin1_german2_ci); +SELECT * FROM t1 WHERE c1 IN ('a',_latin1'b' COLLATE latin1_german2_ci); + +DROP TABLE t1; + + +CREATE TABLE t1(a INT, i CHAR(2), INDEX(i(1))); +INSERT INTO t1 (i) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19), + (20),(21),(22),(23),(24),(25),(26),(27),(28),(29), + (30),(31),(32),(33),(34),(35); + +EXPLAIN SELECT * FROM t1 WHERE i >= 10 ORDER BY i LIMIT 5; +SELECT * FROM t1 WHERE i >= 10 ORDER BY i LIMIT 5; + +EXPLAIN UPDATE t1 SET a = 1 WHERE i = 10 ORDER BY a, i LIMIT 5; +EXPLAIN UPDATE t1 SET a = 1 WHERE i < 10 ORDER BY a, i LIMIT 5; +EXPLAIN DELETE FROM t1 WHERE i = 10 ORDER BY a, i LIMIT 5; +EXPLAIN DELETE FROM t1 WHERE i < 10 ORDER BY a, i LIMIT 5; + +EXPLAIN UPDATE t1 SET a = 1 WHERE i = 10; +EXPLAIN UPDATE t1 SET a = 1 WHERE i < 10; +EXPLAIN DELETE FROM t1 WHERE i = 10; +EXPLAIN DELETE FROM t1 WHERE i < 10; + +DROP TABLE t1; + +SET note_verbosity=DEFAULT; diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result index 0f47c47bc32..a962776a4dc 100644 --- a/mysql-test/main/view.result +++ b/mysql-test/main/view.result @@ -4422,12 +4422,14 @@ SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` < "0" of type `int` Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 'JJ' or `test`.`t1`.`a` = 'VV' and `test`.`t1`.`a` <> 0 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` < "0" of type `int` Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 'JJ' or `test`.`t1`.`a` = 'VV' and `test`.`t1`.`a` <> 0 # t1 and v1 should return the same result set SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; @@ -4448,12 +4450,14 @@ SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` < "0" of type `int` Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 'JJ' or `test`.`t1`.`a` = 'VV' and `test`.`t1`.`a` <> 0 EXPLAIN EXTENDED SELECT * FROM t1 WHERE a > 'JJ' OR a AND a = 'VV'; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index Warnings: +Note 1105 Cannot use key `a` part[0] for lookup: `test`.`t1`.`a` of type `varchar` < "0" of type `int` Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 'JJ' or `test`.`t1`.`a` = 'VV' and `test`.`t1`.`a` <> 0 DROP VIEW v1; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index aa8cc118ce6..d142c0e499e 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2382,6 +2382,10 @@ key_len NULL ref NULL rows 6 Extra Using where +Warnings: +Level Note +Code 1105 +Message Cannot use key `PRIMARY` part[0] for lookup: `test`.`bar`.`c` of type `char` > "2" of type `int` EXPLAIN SELECT c FROM foo WHERE c>2;; id 1 select_type SIMPLE @@ -2393,6 +2397,10 @@ key_len NULL ref NULL rows 6 Extra Using where +Warnings: +Level Note +Code 1105 +Message Cannot use key `PRIMARY` part[0] for lookup: `test`.`foo`.`c` of type `char` > "2" of type `int` EXPLAIN SELECT c FROM foo2 WHERE c>2;; id 1 select_type SIMPLE @@ -2404,6 +2412,10 @@ key_len 5 ref NULL rows 6 Extra Using where; Using index +Warnings: +Level Note +Code 1105 +Message Cannot use key `PRIMARY` part[0] for lookup: `test`.`foo2`.`c` of type `char` > "2" of type `int` DROP TABLE foo, bar, foo2; # # Bug#41348: INSERT INTO tbl SELECT * FROM temp_tbl overwrites locking type of temp table diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result index da67e05a163..0f20e16db9c 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_myisam.result @@ -98,6 +98,8 @@ c EXPLAIN SELECT * FROM t1 WHERE c>CAST('::1' AS INET6); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index c c 67 NULL 3 Using where; Using index +Warnings: +Note 1105 Cannot use key `c` part[0] for lookup: `test`.`t1`.`c` of type `varchar` > "cast('::1' as inet6)" of type `inet6` SELECT * FROM t1 WHERE c=CAST('::1' AS INET6); c 0::1 diff --git a/sql/field.cc b/sql/field.cc index 4a6b6616340..e4b814924e4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -11284,6 +11284,7 @@ void Field::set_warning_truncated_wrong_value(const char *type_arg, void Field::raise_note_cannot_use_key_part(THD *thd, uint keynr, uint part, const LEX_CSTRING &op, + CHARSET_INFO *op_collation, Item *value, Data_type_compatibility reason) const @@ -11304,7 +11305,7 @@ void Field::raise_note_cannot_use_key_part(THD *thd, case Data_type_compatibility::INCOMPATIBLE_COLLATION: { const LEX_CSTRING colf(charset()->coll_name); - const LEX_CSTRING colv(value->collation.collation->coll_name); + const LEX_CSTRING colv(op_collation->coll_name); push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_UNKNOWN_ERROR, "Cannot use key %`.*s part[%u] for lookup: " diff --git a/sql/field.h b/sql/field.h index 1f31d6042cd..51fdc8124e6 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1642,6 +1642,7 @@ public: void print_key_value_binary(String *out, const uchar* key, uint32 length); void raise_note_cannot_use_key_part(THD *thd, uint keynr, uint part, const LEX_CSTRING &op, + CHARSET_INFO *op_collation, Item *value, const Data_type_compatibility reason) const; diff --git a/sql/item_func.h b/sql/item_func.h index 1390fab014f..aa5bbd4bb96 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -79,6 +79,38 @@ public: CASE_SEARCHED_FUNC, // Used by ColumnStore/Spider CASE_SIMPLE_FUNC, // Used by ColumnStore/spider, }; + + /* + A function bitmap. Useful when some operation needs to be applied only + to certain functions. For now we only need to distinguish some + comparison predicates. + */ + enum Bitmap : ulonglong + { + BITMAP_NONE= 0, + BITMAP_EQ= 1ULL << EQ_FUNC, + BITMAP_EQUAL= 1ULL << EQUAL_FUNC, + BITMAP_NE= 1ULL << NE_FUNC, + BITMAP_LT= 1ULL << LT_FUNC, + BITMAP_LE= 1ULL << LE_FUNC, + BITMAP_GE= 1ULL << GE_FUNC, + BITMAP_GT= 1ULL << GT_FUNC, + BITMAP_LIKE= 1ULL << LIKE_FUNC, + BITMAP_BETWEEN= 1ULL << BETWEEN, + BITMAP_IN= 1ULL << IN_FUNC, + BITMAP_MULT_EQUAL= 1ULL << MULT_EQUAL_FUNC, + BITMAP_OTHER= 1ULL << 63, + BITMAP_ALL= 0xFFFFFFFFFFFFFFFFULL, + BITMAP_ANY_EQUALITY= BITMAP_EQ | BITMAP_EQUAL | BITMAP_MULT_EQUAL, + BITMAP_EXCEPT_ANY_EQUALITY= BITMAP_ALL & ~BITMAP_ANY_EQUALITY, + }; + + ulonglong bitmap_bit() const + { + Functype type= functype(); + return 1ULL << (type > 63 ? 63 : type); + } + static scalar_comparison_op functype_to_scalar_comparison_op(Functype type) { switch (type) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index b7800e83bd8..72703a018ad 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2690,7 +2690,7 @@ SQL_SELECT::test_quick_select(THD *thd, bool ordered_output, bool remove_false_parts_of_where, bool only_single_index_range_scan, - bool suppress_unusable_key_notes) + Item_func::Bitmap note_unusable_keys) { uint idx; double scan_time; @@ -2784,9 +2784,9 @@ SQL_SELECT::test_quick_select(THD *thd, param.max_key_parts= 0; param.remove_false_where_parts= remove_false_parts_of_where; param.force_default_mrr= ordered_output; - param.note_unusable_keys= (!suppress_unusable_key_notes && - thd->give_notes_for_unusable_keys()); - + param.note_unusable_keys= thd->give_notes_for_unusable_keys() ? + note_unusable_keys : + Item_func::BITMAP_NONE; param.possible_keys.clear_all(); thd->no_errors=1; // Don't warn about NULL @@ -3993,7 +3993,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) range_par->remove_jump_scans= FALSE; range_par->real_keynr[0]= 0; range_par->alloced_sel_args= 0; - range_par->note_unusable_keys= 0; + range_par->note_unusable_keys= Item_func::BITMAP_NONE; thd->no_errors=1; // Don't warn about NULL thd->mem_root=&alloc; @@ -8756,9 +8756,11 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param, if (field->result_type() == STRING_RESULT && field->charset() != compare_collation()) { - if (param->note_unusable_keys) + if (param->note_unusable_keys & BITMAP_LIKE) field->raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, - func_name_cstring(), value, + func_name_cstring(), + compare_collation(), + value, Data_type_compatibility:: INCOMPATIBLE_COLLATION); DBUG_RETURN(0); @@ -8774,9 +8776,11 @@ Item_func_like::get_mm_leaf(RANGE_OPT_PARAM *param, field->type_handler() == &type_handler_enum || field->type_handler() == &type_handler_set) { - if (param->note_unusable_keys) + if (param->note_unusable_keys & BITMAP_LIKE) field->raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, - func_name_cstring(), value, + func_name_cstring(), + compare_collation(), + value, Data_type_compatibility:: INCOMPATIBLE_DATA_TYPE); DBUG_RETURN(0); @@ -8881,7 +8885,8 @@ Field::can_optimize_scalar_range(const RANGE_OPT_PARAM *param, TODO: Perhaps we also need to raise a similar note when a partition could not be used (when using_real_indexes==false). */ - if (param->using_real_indexes && param->note_unusable_keys) + if (param->using_real_indexes && param->note_unusable_keys && + (param->note_unusable_keys & cond->bitmap_bit())) { DBUG_ASSERT(keynr < table->s->keys); /* @@ -8895,6 +8900,7 @@ Field::can_optimize_scalar_range(const RANGE_OPT_PARAM *param, */ raise_note_cannot_use_key_part(param->thd, keynr, key_part->part, scalar_comparison_op_to_lex_cstring(op), + cond->compare_collation(), value, compat); } return compat; diff --git a/sql/opt_range.h b/sql/opt_range.h index de9a9464447..18b3c33cafa 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -713,7 +713,10 @@ public: */ bool remove_false_where_parts; - bool note_unusable_keys; // Give SQL notes for unusable keys + /* + Which functions should give SQL notes for unusable keys. + */ + Item_func::Bitmap note_unusable_keys; /* used_key_no -> table_key_no translation table. Only makes sense if @@ -1718,12 +1721,14 @@ class SQL_SELECT :public Sql_alloc { true - for ERROR and IMPOSSIBLE_RANGE false - Ok */ - bool check_quick(THD *thd, bool force_quick_range, ha_rows limit) + bool check_quick(THD *thd, bool force_quick_range, ha_rows limit, + Item_func::Bitmap note_unusable_keys) { key_map tmp; tmp.set_all(); return test_quick_select(thd, tmp, 0, limit, force_quick_range, - FALSE, FALSE, FALSE) != OK; + FALSE, FALSE, FALSE, + note_unusable_keys) != OK; } /* @@ -1753,7 +1758,7 @@ class SQL_SELECT :public Sql_alloc { bool ordered_output, bool remove_false_parts_of_where, bool only_single_index_range_scan, - bool suppress_unusable_key_notes = 0); + Item_func::Bitmap note_unusable_keys); }; typedef enum SQL_SELECT::quick_select_return_type quick_select_return; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 296d075d7f9..5de19084b0f 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -530,7 +530,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, select=make_select(table, 0, 0, conds, (SORT_INFO*) 0, 0, &error); if (unlikely(error)) DBUG_RETURN(TRUE); - if ((select && select->check_quick(thd, safe_update, limit)) || !limit) + if ((select && select->check_quick(thd, safe_update, limit, + Item_func::BITMAP_ALL)) || !limit) { query_plan.set_impossible_where(); if (thd->lex->describe || thd->lex->analyze_stmt) diff --git a/sql/sql_help.cc b/sql/sql_help.cc index f9932f11798..34e77e3773f 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -667,7 +667,8 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, SQL_SELECT *res= make_select(table, 0, 0, cond, 0, 0, error); if (unlikely(*error) || - (likely(res) && unlikely(res->check_quick(thd, 0, HA_POS_ERROR))) || + (likely(res) && unlikely(res->check_quick(thd, 0, HA_POS_ERROR, + Item_func::BITMAP_ALL))) || (likely(res) && res->quick && unlikely(res->quick->reset()))) { delete res; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fcd640dd9b2..74e2c74f597 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1958,9 +1958,14 @@ bool JOIN::make_range_rowid_filters() bool force_index_save= tab->table->force_index; tab->table->force_index= true; quick_select_return rc; + /* + EQ_FUNC and EQUAL_FUNC already sent unusable key notes (if any) + during update_ref_and_keys(). Have only other functions raise notes + from can_optimize_scalar_range(). + */ rc= sel->test_quick_select(thd, filter_map, (table_map) 0, (ha_rows) HA_POS_ERROR, true, false, true, - true); + true, Item_func::BITMAP_EXCEPT_ANY_EQUALITY); tab->table->force_index= force_index_save; if (rc == SQL_SELECT::ERROR || thd->is_error()) { @@ -5188,10 +5193,16 @@ static bool get_quick_record_count(THD *thd, SQL_SELECT *select, { select->head=table; table->reginfo.impossible_range=0; + /* + EQ_FUNC and EQUAL_FUNC already sent unusable key notes (if any) + during update_ref_and_keys(). Have only other functions raise notes + from can_optimize_scalar_range(). + */ error= select->test_quick_select(thd, *(key_map *)keys, (table_map) 0, limit, 0, FALSE, TRUE, /* remove_where_parts*/ - FALSE, TRUE); + FALSE, + Item_func::BITMAP_EXCEPT_ANY_EQUALITY); if (error == SQL_SELECT::OK && select->quick) { @@ -7000,6 +7011,7 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field) { field->raise_note_cannot_use_key_part(thd, key, part, equal_str, + key_field->cond->compare_collation(), key_field->val, compat); } @@ -12706,7 +12718,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) HA_POS_ERROR : join->unit->lim.get_select_limit()), 0, - FALSE, FALSE, FALSE)) == + FALSE, FALSE, FALSE, + Item_func::BITMAP_ALL)) == SQL_SELECT::IMPOSSIBLE_RANGE) { /* @@ -12721,7 +12734,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) OPTION_FOUND_ROWS ? HA_POS_ERROR : join->unit->lim.get_select_limit()), - 0, FALSE, FALSE, FALSE, TRUE)) == + 0, FALSE, FALSE, FALSE, + Item_func::BITMAP_NONE)) == SQL_SELECT::IMPOSSIBLE_RANGE) DBUG_RETURN(1); // Impossible WHERE } @@ -22746,7 +22760,9 @@ test_if_quick_select(JOIN_TAB *tab) res= tab->select->test_quick_select(tab->join->thd, tab->keys, (table_map) 0, HA_POS_ERROR, 0, FALSE, /*remove where parts*/FALSE, - FALSE, /* no warnings */ TRUE); + FALSE, + /* no unusable key notes */ + Item_func::BITMAP_NONE); if (tab->explain_plan && tab->explain_plan->range_checked_fer) tab->explain_plan->range_checked_fer->collect_data(tab->select->quick); @@ -24797,7 +24813,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, HA_POS_ERROR : tab->join->unit-> lim.get_select_limit(), - TRUE, TRUE, FALSE, FALSE); + TRUE, TRUE, FALSE, FALSE, + Item_func::BITMAP_ALL); // if we cannot use quick select if (res != SQL_SELECT::OK || !tab->select->quick) { @@ -24902,7 +24919,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, join->select_options & OPTION_FOUND_ROWS ? HA_POS_ERROR : join->unit->lim.get_select_limit(), - TRUE, FALSE, FALSE, FALSE); + TRUE, FALSE, FALSE, FALSE, + Item_func::BITMAP_ALL); if (res == SQL_SELECT::ERROR) { *fatal_error= true; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c36556df534..7fd5c864c06 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -579,7 +579,8 @@ int mysql_update(THD *thd, select= make_select(table, 0, 0, conds, (SORT_INFO*) 0, 0, &error); if (unlikely(error || !limit || thd->is_error() || - (select && select->check_quick(thd, safe_update, limit)))) + (select && select->check_quick(thd, safe_update, limit, + Item_func::BITMAP_ALL)))) { query_plan.set_impossible_where(); if (thd->lex->describe || thd->lex->analyze_stmt)