diff --git a/mysql-test/include/ctype_numconv.inc b/mysql-test/include/ctype_numconv.inc index c4a39879947..83d69cfa40d 100644 --- a/mysql-test/include/ctype_numconv.inc +++ b/mysql-test/include/ctype_numconv.inc @@ -1722,6 +1722,21 @@ DROP TABLE t1; --echo # +--echo # +--echo # Bug#58190 BETWEEN no longer uses indexes for date or datetime fields +--echo # +SELECT @@collation_connection; +CREATE TABLE t1 ( + id INT(11) DEFAULT NULL, + date_column DATE DEFAULT NULL, + KEY(date_column)); +INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01'); +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL; +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +DROP TABLE t1; + + --echo # --echo # Bug#52159 returning time type from function and empty left join causes debug assertion --echo # diff --git a/mysql-test/r/ctype_binary.result b/mysql-test/r/ctype_binary.result index d79265b29c7..4d526a86ade 100644 --- a/mysql-test/r/ctype_binary.result +++ b/mysql-test/r/ctype_binary.result @@ -2748,6 +2748,25 @@ DROP TABLE t1; # End of Bug#54916 # # +# Bug#58190 BETWEEN no longer uses indexes for date or datetime fields +# +SELECT @@collation_connection; +@@collation_connection +binary +CREATE TABLE t1 ( +id INT(11) DEFAULT NULL, +date_column DATE DEFAULT NULL, +KEY(date_column)); +INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01'); +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where +ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL; +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where +DROP TABLE t1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; diff --git a/mysql-test/r/ctype_cp1251.result b/mysql-test/r/ctype_cp1251.result index babed8951a2..d5ee7214cde 100644 --- a/mysql-test/r/ctype_cp1251.result +++ b/mysql-test/r/ctype_cp1251.result @@ -2830,6 +2830,25 @@ DROP TABLE t1; # End of Bug#54916 # # +# Bug#58190 BETWEEN no longer uses indexes for date or datetime fields +# +SELECT @@collation_connection; +@@collation_connection +cp1251_general_ci +CREATE TABLE t1 ( +id INT(11) DEFAULT NULL, +date_column DATE DEFAULT NULL, +KEY(date_column)); +INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01'); +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where +ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL; +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where +DROP TABLE t1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result index 6edddecb88f..3585f0934b0 100644 --- a/mysql-test/r/ctype_latin1.result +++ b/mysql-test/r/ctype_latin1.result @@ -3158,6 +3158,25 @@ DROP TABLE t1; # End of Bug#54916 # # +# Bug#58190 BETWEEN no longer uses indexes for date or datetime fields +# +SELECT @@collation_connection; +@@collation_connection +latin1_swedish_ci +CREATE TABLE t1 ( +id INT(11) DEFAULT NULL, +date_column DATE DEFAULT NULL, +KEY(date_column)); +INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01'); +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where +ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL; +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where +DROP TABLE t1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 1008f201366..11d5117bbe1 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -3990,6 +3990,25 @@ DROP TABLE t1; # End of Bug#54916 # # +# Bug#58190 BETWEEN no longer uses indexes for date or datetime fields +# +SELECT @@collation_connection; +@@collation_connection +ucs2_general_ci +CREATE TABLE t1 ( +id INT(11) DEFAULT NULL, +date_column DATE DEFAULT NULL, +KEY(date_column)); +INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01'); +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL; +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +DROP TABLE t1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 02ff80890e0..f207d056b51 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -4848,6 +4848,25 @@ DROP TABLE t1; # End of Bug#54916 # # +# Bug#58190 BETWEEN no longer uses indexes for date or datetime fields +# +SELECT @@collation_connection; +@@collation_connection +utf8_general_ci +CREATE TABLE t1 ( +id INT(11) DEFAULT NULL, +date_column DATE DEFAULT NULL, +KEY(date_column)); +INSERT INTO t1 VALUES (1,'2010-09-01'),(2,'2010-10-01'); +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range date_column date_column 4 NULL 1 Using where +ALTER TABLE t1 MODIFY date_column DATETIME DEFAULT NULL; +EXPLAIN SELECT * FROM t1 WHERE date_column BETWEEN '2010-09-01' AND '2010-10-01'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range date_column date_column 9 NULL 1 Using where +DROP TABLE t1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; diff --git a/sql/field.h b/sql/field.h index d854b78f9a3..e3db95260c3 100644 --- a/sql/field.h +++ b/sql/field.h @@ -746,6 +746,17 @@ public: uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, CHARSET_INFO *charset); Item_result result_type () const { return STRING_RESULT; } + /* + match_collation_to_optimize_range() is to distinguish in + range optimizer (see opt_range.cc) between real string types: + CHAR, VARCHAR, TEXT + and the other string-alike types with result_type() == STRING_RESULT: + DATE, TIME, DATETIME, TIMESTAMP + We need it to decide whether to test if collation of the operation + matches collation of the field (needed only for real string types). + QQ: shouldn't DATE/TIME types have their own XXX_RESULT types eventually? + */ + virtual bool match_collation_to_optimize_range() const=0; uint decimals() const { return NOT_FIXED_DEC; } int store(double nr); int store(longlong nr, bool unsigned_val)=0; @@ -1227,6 +1238,7 @@ public: unireg_check_arg, field_name_arg, cs) {} enum_field_types type() const { return MYSQL_TYPE_NULL;} + bool match_collation_to_optimize_range() const { return FALSE; } int store(const char *to, uint length, CHARSET_INFO *cs) { null[0]=1; return 0; } int store(double nr) { null[0]=1; return 0; } @@ -1256,6 +1268,7 @@ public: Field_timestamp(bool maybe_null_arg, const char *field_name_arg, CHARSET_INFO *cs); enum_field_types type() const { return MYSQL_TYPE_TIMESTAMP;} + bool match_collation_to_optimize_range() const { return FALSE; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum Item_result cmp_type () const { return INT_RESULT; } enum Derivation derivation(void) const { return DERIVATION_NUMERIC; } @@ -1360,6 +1373,7 @@ public: :Field_str((uchar*) 0, MAX_DATE_WIDTH, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, cs) { flags|= BINARY_FLAG; } enum_field_types type() const { return MYSQL_TYPE_DATE;} + bool match_collation_to_optimize_range() const { return FALSE; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum Item_result cmp_type () const { return INT_RESULT; } enum Derivation derivation(void) const { return DERIVATION_NUMERIC; } @@ -1409,6 +1423,7 @@ public: NONE, field_name_arg, cs) { flags|= BINARY_FLAG; } enum_field_types type() const { return MYSQL_TYPE_DATE;} enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; } + bool match_collation_to_optimize_range() const { return FALSE; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; } enum Item_result cmp_type () const { return INT_RESULT; } enum Derivation derivation(void) const { return DERIVATION_NUMERIC; } @@ -1448,6 +1463,7 @@ public: :Field_str((uchar*) 0,8, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, cs) { flags|= BINARY_FLAG; } enum_field_types type() const { return MYSQL_TYPE_TIME;} + bool match_collation_to_optimize_range() const { return FALSE; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_INT24; } enum Item_result cmp_type () const { return INT_RESULT; } enum Derivation derivation(void) const { return DERIVATION_NUMERIC; } @@ -1487,6 +1503,7 @@ public: :Field_str((uchar*) 0, MAX_DATETIME_WIDTH, maybe_null_arg ? (uchar*) "": 0,0, NONE, field_name_arg, cs) { flags|= BINARY_FLAG; } enum_field_types type() const { return MYSQL_TYPE_DATETIME;} + bool match_collation_to_optimize_range() const { return FALSE; } #ifdef HAVE_LONG_LONG enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONGLONG; } #endif @@ -1555,6 +1572,7 @@ public: orig_table->s->frm_version < FRM_VER_TRUE_VARCHAR ? MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING); } + bool match_collation_to_optimize_range() const { return TRUE; } enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; } bool zero_pack() const { return 0; } @@ -1635,6 +1653,7 @@ public: } enum_field_types type() const { return MYSQL_TYPE_VARCHAR; } + bool match_collation_to_optimize_range() const { return TRUE; } enum ha_base_keytype key_type() const; uint row_pack_length() { return field_length; } bool zero_pack() const { return 0; } @@ -1730,6 +1749,7 @@ public: :Field_longstr((uchar*) 0, 0, (uchar*) "", 0, NONE, "temp", system_charset_info), packlength(packlength_arg) {} enum_field_types type() const { return MYSQL_TYPE_BLOB;} + bool match_collation_to_optimize_range() const { return TRUE; } enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; } int store(const char *to,uint length,CHARSET_INFO *charset); @@ -1879,6 +1899,7 @@ public: { geom_type= geom_type_arg; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; } enum_field_types type() const { return MYSQL_TYPE_GEOMETRY; } + bool match_collation_to_optimize_range() const { return FALSE; } void sql_type(String &str) const; int store(const char *to, uint length, CHARSET_INFO *charset); int store(double nr); @@ -1910,6 +1931,7 @@ public: } Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); enum_field_types type() const { return MYSQL_TYPE_STRING; } + bool match_collation_to_optimize_range() const { return FALSE; } enum Item_result cmp_type () const { return INT_RESULT; } enum Item_result cast_to_int_type () const { return INT_RESULT; } enum ha_base_keytype key_type() const; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ffff9e3f6c8..2ac860d25e3 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5796,6 +5796,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, */ if (field->result_type() == STRING_RESULT && + ((Field_str*) field)->match_collation_to_optimize_range() && value->result_type() == STRING_RESULT && key_part->image_type == Field::itRAW && ((Field_str*)field)->charset() != conf_func->compare_collation() &&