diff options
author | Sergei Golubchik <serg@mariadb.org> | 2018-03-12 20:16:33 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2018-03-14 12:45:28 +0100 |
commit | d390e501eb812138db8963098a66d888f8adf490 (patch) | |
tree | 3d67911e2e24129626da8c372ced57a5a58c174b | |
parent | 1c6f6dc8924f144770a862d74667d7fa0eba55c1 (diff) | |
download | mariadb-git-d390e501eb812138db8963098a66d888f8adf490.tar.gz |
MDEV-11839 move value caching from get_datetime_value to fix_fields time
Refactor get_datetime_value() not to create Item_cache_temporal(),
but do it always in ::fix_fields() or ::fix_length_and_dec().
Creating items at the execution time doesn't work very well with
virtual columns and check constraints that are fixed and executed
in different THDs.
-rw-r--r-- | mysql-test/r/cache_temporal_4265.result | 1 | ||||
-rw-r--r-- | mysql-test/r/case.result | 34 | ||||
-rw-r--r-- | mysql-test/r/range.result | 2 | ||||
-rw-r--r-- | mysql-test/r/range_mrr_icp.result | 2 | ||||
-rw-r--r-- | mysql-test/t/case.test | 19 | ||||
-rw-r--r-- | sql/item.cc | 49 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 112 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 14 | ||||
-rw-r--r-- | storage/mroonga/mysql-test/mroonga/storage/r/column_time_fractional_seconds_with_index.result | 2 | ||||
-rw-r--r-- | storage/mroonga/mysql-test/mroonga/storage/r/column_time_with_index.result | 2 | ||||
-rw-r--r-- | storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result | 4 |
11 files changed, 139 insertions, 102 deletions
diff --git a/mysql-test/r/cache_temporal_4265.result b/mysql-test/r/cache_temporal_4265.result index 980bb957e19..7f215de43fb 100644 --- a/mysql-test/r/cache_temporal_4265.result +++ b/mysql-test/r/cache_temporal_4265.result @@ -7,7 +7,6 @@ a 2002-03-04 Warnings: Note 1003 2000-01-01 -Note 1003 2000-01-06 set debug_dbug=''; drop table t1; create table t1 (id int not null, ut timestamp(6) not null); diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index 4d5edbda1ce..5a453ebe815 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -403,3 +403,37 @@ DROP TABLE t1; # # End of 10.1 test # +select case 'foo' when time'10:00:00' then 'never' when '0' then 'bug' else 'ok' end; +case 'foo' when time'10:00:00' then 'never' when '0' then 'bug' else 'ok' end +ok +Warnings: +Warning 1292 Truncated incorrect time value: 'foo' +select 'foo' in (time'10:00:00','0'); +'foo' in (time'10:00:00','0') +0 +Warnings: +Warning 1292 Truncated incorrect time value: 'foo' +create table t1 (a time); +insert t1 values (100000), (102030), (203040); +select case 'foo' when a then 'never' when '0' then 'bug' else 'ok' end from t1; +case 'foo' when a then 'never' when '0' then 'bug' else 'ok' end +ok +ok +ok +Warnings: +Warning 1292 Truncated incorrect time value: 'foo' +Warning 1292 Truncated incorrect time value: 'foo' +Warning 1292 Truncated incorrect time value: 'foo' +select 'foo' in (a,'0') from t1; +'foo' in (a,'0') +0 +0 +0 +Warnings: +Warning 1292 Truncated incorrect time value: 'foo' +Warning 1292 Truncated incorrect time value: 'foo' +Warning 1292 Truncated incorrect time value: 'foo' +drop table t1; +select case '20:10:05' when date'2020-10-10' then 'never' when time'20:10:5' then 'ok' else 'bug' end; +case '20:10:05' when date'2020-10-10' then 'never' when time'20:10:5' then 'ok' else 'bug' end +bug diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 28f5cf635d0..3a71d08eb38 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -1595,8 +1595,6 @@ NULL Warnings: Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date -Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date -Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'; str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20' 1 diff --git a/mysql-test/r/range_mrr_icp.result b/mysql-test/r/range_mrr_icp.result index f2860aaab76..799a299e33f 100644 --- a/mysql-test/r/range_mrr_icp.result +++ b/mysql-test/r/range_mrr_icp.result @@ -1597,8 +1597,6 @@ NULL Warnings: Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date -Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date -Warning 1411 Incorrect datetime value: '2007-20-00' for function str_to_date SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'; str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20' 1 diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index 702592374b6..550b89aab0d 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -287,3 +287,22 @@ DROP TABLE t1; --echo # --echo # End of 10.1 test --echo # + +# +# caching of first argument in CASE/IN for temporal types +# +# + +# should not convert all values to time +select case 'foo' when time'10:00:00' then 'never' when '0' then 'bug' else 'ok' end; +select 'foo' in (time'10:00:00','0'); + +create table t1 (a time); +insert t1 values (100000), (102030), (203040); +# only one warning, TIME('foo') should be cached +select case 'foo' when a then 'never' when '0' then 'bug' else 'ok' end from t1; +select 'foo' in (a,'0') from t1; +drop table t1; + +# first comparison should be as date, second as time +select case '20:10:05' when date'2020-10-10' then 'never' when time'20:10:5' then 'ok' else 'bug' end; diff --git a/sql/item.cc b/sql/item.cc index 0e6135d64f8..8dce7f7c64a 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -9361,13 +9361,16 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) switch (res_type) { case TIME_RESULT: { - bool is_null; - Item **ref_copy= ref; - /* the following call creates a constant and puts it in new_item */ enum_field_types type= item->field_type_for_temporal_comparison(comp_item); - get_datetime_value(thd, &ref_copy, &new_item, type, &is_null); - if (is_null) + longlong value= item->val_temporal_packed(type); + if (item->null_value) new_item= new (mem_root) Item_null(thd, name); + else + { + Item_cache_temporal *cache= new (mem_root) Item_cache_temporal(thd, type); + cache->store_packed(value, item); + new_item= cache; + } break; } case STRING_RESULT: @@ -9702,8 +9705,7 @@ Item_cache_temporal::Item_cache_temporal(THD *thd, longlong Item_cache_temporal::val_datetime_packed() { DBUG_ASSERT(fixed == 1); - if (Item_cache_temporal::field_type() == MYSQL_TYPE_TIME) - return Item::val_datetime_packed(); // TIME-to-DATETIME conversion needed + DBUG_ASSERT(Item_cache_temporal::field_type() != MYSQL_TYPE_TIME); if ((!value_cached && !cache_value()) || null_value) { null_value= TRUE; @@ -9716,8 +9718,7 @@ longlong Item_cache_temporal::val_datetime_packed() longlong Item_cache_temporal::val_time_packed() { DBUG_ASSERT(fixed == 1); - if (Item_cache_temporal::field_type() != MYSQL_TYPE_TIME) - return Item::val_time_packed(); // DATETIME-to-TIME conversion needed + DBUG_ASSERT(Item_cache_temporal::field_type() == MYSQL_TYPE_TIME); if ((!value_cached && !cache_value()) || null_value) { null_value= TRUE; @@ -9775,18 +9776,26 @@ double Item_cache_temporal::val_real() } -bool Item_cache_temporal::cache_value() +bool Item_cache_temporal::cache_value() { if (!example) return false; - value_cached= true; - + MYSQL_TIME ltime; - if (example->get_date_result(<ime, 0)) - value=0; - else + uint fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES; + if (Item_cache_temporal::field_type() == MYSQL_TYPE_TIME) + fuzzydate|= TIME_TIME_ONLY; + + value= 0; + if (!example->get_date_result(<ime, fuzzydate)) + { + if (ltime.time_type == MYSQL_TIMESTAMP_TIME && + !(fuzzydate & TIME_TIME_ONLY) && + convert_time_to_datetime(current_thd, <ime, fuzzydate)) + return true; value= pack_time(<ime); + } null_value= example->null_value; return true; } @@ -9806,11 +9815,15 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) ltime->time_type= mysql_type_to_time_type(field_type()); if (ltime->time_type == MYSQL_TIMESTAMP_TIME) { - ltime->hour+= (ltime->month*32+ltime->day)*24; - ltime->month= ltime->day= 0; + if (fuzzydate & TIME_TIME_ONLY) + { + ltime->hour+= (ltime->month*32+ltime->day)*24; + ltime->month= ltime->day= 0; + } + else if (convert_time_to_datetime(current_thd, ltime, fuzzydate)) + return true; } return 0; - } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 75ed765ea7d..42b94e4daee 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -41,10 +41,14 @@ static Item** cache_converted_constant(THD *thd, Item **value, find an temporal type (item) that others will be converted to for the purpose of comparison. + for IN/CASE conversion only happens if the first item defines the + comparison context. + this is the type that will be used in warnings like "Incorrect <<TYPE>> value". */ -static Item *find_date_time_item(Item **args, uint nargs, uint col) +static Item *find_date_time_item(THD *thd, Item **args, uint nargs, uint col, + bool in_case) { Item *date_arg= 0, **arg, **arg_end; for (arg= args, arg_end= args + nargs; arg != arg_end ; arg++) @@ -52,10 +56,22 @@ static Item *find_date_time_item(Item **args, uint nargs, uint col) Item *item= arg[0]->element_index(col); if (item->cmp_type() != TIME_RESULT) continue; - if (item->field_type() == MYSQL_TYPE_DATETIME) - return item; if (!date_arg) date_arg= item; + if (item->field_type() == MYSQL_TYPE_DATETIME) + break; + } + if (in_case ? date_arg == args[0]->element_index(col) : date_arg != NULL) + { + enum_field_types f_type= date_arg->field_type(); + for (arg= args, arg_end= args + nargs; arg != arg_end ; arg++) + { + Item *cache, **a= arg[0]->addr(col); + if (!a) + a= arg; + if (cache_converted_constant(thd, a, &cache, TIME_RESULT, f_type) != a) + thd->change_item_tree(a, cache); + } } return date_arg; } @@ -658,6 +674,8 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg, func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime : &Arg_comparator::compare_datetime; } + a= cache_converted_constant(thd, a, &a_cache, m_compare_type, f_type); + b= cache_converted_constant(thd, b, &b_cache, m_compare_type, f_type); return 0; } @@ -685,9 +703,11 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg, func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime : &Arg_comparator::compare_datetime; } - - a= cache_converted_constant(thd, a, &a_cache, m_compare_type); - b= cache_converted_constant(thd, b, &b_cache, m_compare_type); + else + { + a= cache_converted_constant(thd, a, &a_cache, m_compare_type, (*a)->field_type()); + b= cache_converted_constant(thd, b, &b_cache, m_compare_type, (*b)->field_type()); + } return set_compare_func(owner_arg, m_compare_type); } @@ -710,18 +730,13 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg, */ static Item** cache_converted_constant(THD *thd, Item **value, - Item **cache_item, Item_result type) + Item **cache_item, Item_result type, enum_field_types f_type) { - /* - Don't need cache if doing context analysis only. - Also, get_datetime_value creates Item_cache internally. - Unless fixed, we should not do it here. - */ + /* Don't need cache if doing context analysis only. */ if (!thd->lex->is_ps_or_view_context_analysis() && - (*value)->const_item() && type != (*value)->result_type() && - type != TIME_RESULT) + (*value)->const_item() && type != (*value)->result_type()) { - Item_cache *cache= Item_cache::get_cache(thd, *value, type); + Item_cache *cache= Item_cache::get_cache(thd, *value, type, f_type); cache->setup(thd, *value); *cache_item= cache; return cache_item; @@ -761,26 +776,11 @@ static Item** cache_converted_constant(THD *thd, Item **value, MYSQL_TIME value, packed in a longlong, suitable for comparison. */ -longlong -get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, - enum_field_types f_type, bool *is_null) +longlong get_datetime_value(Item *item, enum_field_types f_type, bool *is_null) { - longlong UNINIT_VAR(value); - Item *item= **item_arg; - value= item->val_temporal_packed(f_type); + longlong value= item->val_temporal_packed(f_type); if ((*is_null= item->null_value)) return ~(ulonglong) 0; - if (cache_arg && item->const_item() && - !(item->type() == Item::CACHE_ITEM && item->cmp_type() == TIME_RESULT)) - { - if (!thd) - thd= current_thd; - - Item_cache_temporal *cache= new (thd->mem_root) Item_cache_temporal(thd, f_type); - cache->store_packed(value, item); - *cache_arg= cache; - *item_arg= cache_arg; - } return value; } @@ -811,12 +811,12 @@ int Arg_comparator::compare_temporal(enum_field_types type) owner->null_value= 1; /* Get DATE/DATETIME/TIME value of the 'a' item. */ - a_value= get_datetime_value(0, &a, &a_cache, type, &a_is_null); + a_value= get_datetime_value(*a, type, &a_is_null); if (a_is_null) return -1; /* Get DATE/DATETIME/TIME value of the 'b' item. */ - b_value= get_datetime_value(0, &b, &b_cache, type, &b_is_null); + b_value= get_datetime_value(*b, type, &b_is_null); if (b_is_null) return -1; @@ -834,10 +834,10 @@ int Arg_comparator::compare_e_temporal(enum_field_types type) longlong a_value, b_value; /* Get DATE/DATETIME/TIME value of the 'a' item. */ - a_value= get_datetime_value(0, &a, &a_cache, type, &a_is_null); + a_value= get_datetime_value(*a, type, &a_is_null); /* Get DATE/DATETIME/TIME value of the 'b' item. */ - b_value= get_datetime_value(0, &b, &b_cache, type, &b_is_null); + b_value= get_datetime_value(*b, type, &b_is_null); return a_is_null || b_is_null ? a_is_null == b_is_null : a_value == b_value; } @@ -2170,7 +2170,7 @@ void Item_func_between::fix_length_and_dec() strings as. */ if (m_compare_type == TIME_RESULT) - compare_as_dates= find_date_time_item(args, 3, 0); + compare_as_dates= find_date_time_item(thd, args, 3, 0, false); /* See the comment for Item_func::convert_const_compared_to_int_field */ if (args[0]->real_item()->type() == FIELD_ITEM && @@ -2196,29 +2196,17 @@ longlong Item_func_between::val_int() switch (m_compare_type) { case TIME_RESULT: { - THD *thd= current_thd; longlong value, a, b; - Item *cache, **ptr; bool value_is_null, a_is_null, b_is_null; - ptr= &args[0]; enum_field_types f_type= field_type_for_temporal_comparison(compare_as_dates); - value= get_datetime_value(thd, &ptr, &cache, f_type, &value_is_null); - if (ptr != &args[0]) - thd->change_item_tree(&args[0], *ptr); + value= get_datetime_value(args[0], f_type, &value_is_null); if ((null_value= value_is_null)) return 0; - ptr= &args[1]; - a= get_datetime_value(thd, &ptr, &cache, f_type, &a_is_null); - if (ptr != &args[1]) - thd->change_item_tree(&args[1], *ptr); - - ptr= &args[2]; - b= get_datetime_value(thd, &ptr, &cache, f_type, &b_is_null); - if (ptr != &args[2]) - thd->change_item_tree(&args[2], *ptr); + a= get_datetime_value(args[1], f_type, &a_is_null); + b= get_datetime_value(args[2], f_type, &b_is_null); if (!a_is_null && !b_is_null) return (longlong) ((value >= a && value <= b) != negated); @@ -3248,7 +3236,7 @@ void Item_func_case::fix_length_and_dec() Item *date_arg= 0; if (m_found_types & (1U << TIME_RESULT)) - date_arg= find_date_time_item(args, nwhens + 1, 0); + date_arg= find_date_time_item(current_thd, args, nwhens + 1, 0, true); if (m_found_types & (1U << STRING_RESULT)) { @@ -3790,10 +3778,8 @@ void in_datetime::set(uint pos,Item *item) uchar *in_datetime::get_value(Item *item) { bool is_null; - Item **tmp_item= lval_cache ? &lval_cache : &item; - enum_field_types f_type= - tmp_item[0]->field_type_for_temporal_comparison(warn_item); - tmp.val= get_datetime_value(0, &tmp_item, &lval_cache, f_type, &is_null); + enum_field_types f_type= item->field_type_for_temporal_comparison(warn_item); + tmp.val= get_datetime_value(item, f_type, &is_null); if (item->null_value) return 0; tmp.unsigned_flag= 1L; @@ -4055,10 +4041,8 @@ cmp_item* cmp_item_decimal::make_same() void cmp_item_datetime::store_value(Item *item) { bool is_null; - Item **tmp_item= lval_cache ? &lval_cache : &item; - enum_field_types f_type= - tmp_item[0]->field_type_for_temporal_comparison(warn_item); - value= get_datetime_value(0, &tmp_item, &lval_cache, f_type, &is_null); + enum_field_types f_type= item->field_type_for_temporal_comparison(warn_item); + value= get_datetime_value(item, f_type, &is_null); m_null_value= item->null_value; } @@ -4263,7 +4247,7 @@ void Item_func_in::fix_length_and_dec() for (uint col= 0; col < cols; col++) { - date_arg= find_date_time_item(args, arg_count, col); + date_arg= find_date_time_item(thd, args, arg_count, col, true); if (date_arg) { cmp_item **cmp= 0; @@ -4329,7 +4313,7 @@ void Item_func_in::fix_length_and_dec() array= new (thd->mem_root) in_decimal(thd, arg_count - 1); break; case TIME_RESULT: - date_arg= find_date_time_item(args, arg_count, 0); + date_arg= find_date_time_item(thd, args, arg_count, 0, true); array= new (thd->mem_root) in_datetime(thd, date_arg, arg_count - 1); break; } @@ -4356,7 +4340,7 @@ void Item_func_in::fix_length_and_dec() else { if (found_types & (1U << TIME_RESULT)) - date_arg= find_date_time_item(args, arg_count, 0); + date_arg= find_date_time_item(thd, args, arg_count, 0, true); if (found_types & (1U << STRING_RESULT) && agg_arg_charsets_for_comparison(cmp_collation, args, arg_count)) return; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index f833232de95..82bfd11a94d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1267,19 +1267,15 @@ public: /* Class to represent a vector of constant DATE/DATETIME values. Values are obtained with help of the get_datetime_value() function. - If the left item is a constant one then its value is cached in the - lval_cache variable. */ class in_datetime :public in_longlong { public: /* An item used to issue warnings. */ Item *warn_item; - /* Cache for the left item. */ - Item *lval_cache; in_datetime(THD *thd, Item *warn_item_arg, uint elements) - :in_longlong(thd, elements), warn_item(warn_item_arg), lval_cache(0) {}; + :in_longlong(thd, elements), warn_item(warn_item_arg) {} void set(uint pos,Item *item); uchar *get_value(Item *item); Item *create_item(THD *thd); @@ -1441,8 +1437,6 @@ public: /* Compare items in the DATETIME context. Values are obtained with help of the get_datetime_value() function. - If the left item is a constant one then its value is cached in the - lval_cache variable. */ class cmp_item_datetime : public cmp_item_scalar { @@ -1450,11 +1444,9 @@ class cmp_item_datetime : public cmp_item_scalar public: /* Item used for issuing warnings. */ Item *warn_item; - /* Cache for the left item. */ - Item *lval_cache; cmp_item_datetime(Item *warn_item_arg) - : warn_item(warn_item_arg), lval_cache(0) {} + : warn_item(warn_item_arg) {} void store_value(Item *item); int cmp(Item *arg); int compare(cmp_item *ci); @@ -2622,7 +2614,7 @@ inline bool is_cond_or(Item *item) Item *and_expressions(Item *a, Item *b, Item **org_item); -longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, +longlong get_datetime_value(Item ***item_arg, Item **cache_arg, enum_field_types f_type, bool *is_null); diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_time_fractional_seconds_with_index.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_time_fractional_seconds_with_index.result index 35434a00160..111fae77a04 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/column_time_fractional_seconds_with_index.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_time_fractional_seconds_with_index.result @@ -25,6 +25,6 @@ id title average max SELECT * FROM running_records WHERE average BETWEEN "-838:59:59.000000" AND "01:00:00.000001"; id title average max -3 record failure -838:59:59.000000 -838:59:59.000000 1 normal condition 01:00:00.000001 01:05:00.000001 +3 record failure -838:59:59.000000 -838:59:59.000000 DROP TABLE running_records; diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/column_time_with_index.result b/storage/mroonga/mysql-test/mroonga/storage/r/column_time_with_index.result index a0b0350a8e3..326c81958cc 100644 --- a/storage/mroonga/mysql-test/mroonga/storage/r/column_time_with_index.result +++ b/storage/mroonga/mysql-test/mroonga/storage/r/column_time_with_index.result @@ -25,6 +25,6 @@ id title average max SELECT * FROM running_records WHERE average BETWEEN "-838:59:59" AND "01:00:00"; id title average max -3 record failure -838:59:59 -838:59:59 1 normal condition 01:00:00 01:05:00 +3 record failure -838:59:59 -838:59:59 DROP TABLE running_records; diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result index 9b084e63cd5..0b5e512cdc9 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result @@ -2080,7 +2080,7 @@ explain select kp1,kp2 from t1 force index (kp1) where kp1 between '09:01:00' and '09:05:00'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range kp1 kp1 4 NULL # Using where; Using index +1 SIMPLE t1 index kp1 kp1 9 NULL # Using where; Using index select kp1,kp2 from t1 force index (kp1) where kp1 between '09:01:00' and '09:05:00'; kp1 kp2 @@ -2103,7 +2103,7 @@ explain select kp1,kp2 from t2 force index (kp1) where kp1 between '09:01:00' and '09:05:00'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 range kp1 kp1 3 NULL # Using where; Using index +1 SIMPLE t2 index kp1 kp1 8 NULL # Using where; Using index select kp1,kp2 from t2 force index (kp1) where kp1 between '09:01:00' and '09:05:00'; kp1 kp2 |