Commit 1b1464ba authored by evgen@moonbone.local's avatar evgen@moonbone.local

Bug#29739: Incorrect time comparison in BETWEEN.

Time values were compared by the BETWEEN function as strings. This led to a
wrong result in cases when some of arguments are less than 100 hours and other
are greater.

Now if all 3 arguments of the BETWEEN function are of the TIME type then
they are compared as integers.
parent c118fe53
...@@ -103,3 +103,9 @@ cast('100:55:50' as time) > cast('024:00:00' as time) ...@@ -103,3 +103,9 @@ 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); 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) cast('300:55:50' as time) > cast('240:00:00' as time)
1 1
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;
1
1
drop table t1;
...@@ -50,3 +50,11 @@ select cast('300:55:50' as time) < cast('240:00:00' as time); ...@@ -50,3 +50,11 @@ 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('24:00:00' as time);
select cast('100:55:50' as time) > cast('024: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); select cast('300:55:50' as time) > cast('240:00:00' as time);
#
# Bug#29739: Incorrect time comparison in BETWEEN.
#
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;
drop table t1;
...@@ -1728,6 +1728,7 @@ void Item_func_between::fix_length_and_dec() ...@@ -1728,6 +1728,7 @@ void Item_func_between::fix_length_and_dec()
THD *thd= current_thd; THD *thd= current_thd;
int i; int i;
bool datetime_found= FALSE; bool datetime_found= FALSE;
int time_items_found= 0;
compare_as_dates= TRUE; compare_as_dates= TRUE;
/* /*
...@@ -1747,6 +1748,8 @@ void Item_func_between::fix_length_and_dec() ...@@ -1747,6 +1748,8 @@ void Item_func_between::fix_length_and_dec()
At least one of items should be a DATE/DATETIME item and other items At least one of items should be a DATE/DATETIME item and other items
should return the STRING result. should return the STRING result.
*/ */
if (cmp_type == STRING_RESULT)
{
for (i= 0; i < 3; i++) for (i= 0; i < 3; i++)
{ {
if (args[i]->is_datetime()) if (args[i]->is_datetime())
...@@ -1754,10 +1757,10 @@ void Item_func_between::fix_length_and_dec() ...@@ -1754,10 +1757,10 @@ void Item_func_between::fix_length_and_dec()
datetime_found= TRUE; datetime_found= TRUE;
continue; continue;
} }
if (args[i]->result_type() == STRING_RESULT) if (args[i]->field_type() == MYSQL_TYPE_TIME &&
continue; args[i]->result_as_longlong())
compare_as_dates= FALSE; time_items_found++;
break; }
} }
if (!datetime_found) if (!datetime_found)
compare_as_dates= FALSE; compare_as_dates= FALSE;
...@@ -1767,6 +1770,11 @@ void Item_func_between::fix_length_and_dec() ...@@ -1767,6 +1770,11 @@ void Item_func_between::fix_length_and_dec()
ge_cmp.set_datetime_cmp_func(args, args + 1); ge_cmp.set_datetime_cmp_func(args, args + 1);
le_cmp.set_datetime_cmp_func(args, args + 2); le_cmp.set_datetime_cmp_func(args, args + 2);
} }
else if (time_items_found == 3)
{
/* Compare TIME items as integers. */
cmp_type= INT_RESULT;
}
else if (args[0]->real_item()->type() == FIELD_ITEM && else if (args[0]->real_item()->type() == FIELD_ITEM &&
thd->lex->sql_command != SQLCOM_CREATE_VIEW && thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
thd->lex->sql_command != SQLCOM_SHOW_CREATE) thd->lex->sql_command != SQLCOM_SHOW_CREATE)
......
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