Commit 975d2232 authored by evgen@moonbone.local's avatar evgen@moonbone.local

Extended fix for the bug#29555.

The get_time_value function is added. It is used to obtain TIME values both
from items the can return time as an integer and from items that can return
time only as a string.
The Arg_comparator::compare_datetime function now uses pointer to a getter
function to obtain values to compare. Now this function is also used for
comparison of TIME values.
The get_value_func variable is added to the Arg_comparator class.
It points to a getter function for the DATE/DATETIME/TIME comparator.
parent 1baf8a93
......@@ -103,6 +103,12 @@ cast('100:55:50' as time) > cast('024:00:00' as time)
select cast('300:55:50' as time) > cast('240:00:00' as time);
cast('300:55:50' as time) > cast('240:00:00' as time)
1
create table t1 (f1 time);
insert into t1 values ('24:00:00');
select cast('24:00:00' as time) = (select f1 from t1);
cast('24:00:00' as time) = (select f1 from t1)
1
drop table t1;
create table t1(f1 time, f2 time);
insert into t1 values('20:00:00','150:00:00');
select 1 from t1 where cast('100:00:00' as time) between f1 and f2;
......
......@@ -50,6 +50,10 @@ select cast('300:55:50' as time) < cast('240:00:00' as time);
select cast('100:55:50' as time) > cast('24:00:00' as time);
select cast('100:55:50' as time) > cast('024:00:00' as time);
select cast('300:55:50' as time) > cast('240:00:00' as time);
create table t1 (f1 time);
insert into t1 values ('24:00:00');
select cast('24:00:00' as time) = (select f1 from t1);
drop table t1;
#
# Bug#29739: Incorrect time comparison in BETWEEN.
......
......@@ -666,6 +666,68 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value)
}
/*
Retrieves correct TIME value from the given item.
SYNOPSIS
get_time_value()
thd thread handle
item_arg [in/out] item to retrieve TIME value from
cache_arg [in/out] pointer to place to store the caching item to
warn_item [in] unused
is_null [out] TRUE <=> the item_arg is null
DESCRIPTION
Retrieves the correct TIME value from given item for comparison by the
compare_datetime() function.
If item's result can be compared as longlong then its int value is used
and a value returned by get_time function is used otherwise.
If an item is a constant one then its value is cached and it isn't
get parsed again. An Item_cache_int object is used for caching values. It
seamlessly substitutes the original item. The cache item is marked as
non-constant to prevent re-caching it again.
RETURN
obtained value
*/
ulonglong
get_time_value(THD *thd, Item ***item_arg, Item **cache_arg,
Item *warn_item, bool *is_null)
{
ulonglong value;
Item *item= **item_arg;
MYSQL_TIME ltime;
if (item->result_as_longlong())
{
value= item->val_int();
*is_null= item->null_value;
}
else
{
*is_null= item->get_time(&ltime);
if (!is_null)
value= TIME_to_ulonglong_datetime(&ltime);
}
/*
Do not cache GET_USER_VAR() function as its const_item() may return TRUE
for the current thread but it still may change during the execution.
*/
if (item->const_item() && cache_arg && (item->type() != Item::FUNC_ITEM ||
((Item_func*)item)->functype() != Item_func::GUSERVAR_FUNC))
{
Item_cache_int *cache= new Item_cache_int();
/* Mark the cache as non-const to prevent re-caching. */
cache->set_used_tables(1);
cache->store(item, value);
*cache_arg= cache;
*item_arg= cache_arg;
}
return value;
}
int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
Item **a1, Item **a2,
Item_result type)
......@@ -704,6 +766,7 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
}
is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC);
func= &Arg_comparator::compare_datetime;
get_value_func= &get_datetime_value;
return 0;
}
else if (type == STRING_RESULT && (*a)->field_type() == MYSQL_TYPE_TIME &&
......@@ -712,9 +775,11 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
/* Compare TIME values as integers. */
thd= current_thd;
owner= owner_arg;
func= ((test(owner && owner->functype() == Item_func::EQUAL_FUNC)) ?
&Arg_comparator::compare_e_int :
&Arg_comparator::compare_int_unsigned);
a_cache= 0;
b_cache= 0;
is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC);
func= &Arg_comparator::compare_datetime;
get_value_func= &get_time_value;
return 0;
}
......@@ -735,8 +800,10 @@ void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1)
b_cache= 0;
is_nulls_eq= FALSE;
func= &Arg_comparator::compare_datetime;
get_value_func= &get_datetime_value;
}
/*
Retrieves correct DATETIME value from given item.
......@@ -850,8 +917,8 @@ int Arg_comparator::compare_datetime()
bool is_null= FALSE;
ulonglong a_value, b_value;
/* Get DATE/DATETIME value of the 'a' item. */
a_value= get_datetime_value(thd, &a, &a_cache, *b, &is_null);
/* Get DATE/DATETIME/TIME value of the 'a' item. */
a_value= (*get_value_func)(thd, &a, &a_cache, *b, &is_null);
if (!is_nulls_eq && is_null)
{
if (owner)
......@@ -859,8 +926,8 @@ int Arg_comparator::compare_datetime()
return -1;
}
/* Get DATE/DATETIME value of the 'b' item. */
b_value= get_datetime_value(thd, &b, &b_cache, *a, &is_null);
/* Get DATE/DATETIME/TIME value of the 'b' item. */
b_value= (*get_value_func)(thd, &b, &b_cache, *a, &is_null);
if (is_null)
{
if (owner)
......
......@@ -42,6 +42,8 @@ class Arg_comparator: public Sql_alloc
bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC
enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE,
CMP_DATE_WITH_STR, CMP_STR_WITH_DATE };
ulonglong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg,
Item *warn_item, bool *is_null);
public:
DTCollation cmp_collation;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment