Commit 0a91c7cc authored by evgen@moonbone.local's avatar evgen@moonbone.local

Bug#28778: Wrong result of BETWEEN when comparing a DATETIME field with an

integer constants.

This bug is introduced by the fix for bug#16377. Before the fix the 
Item_func_between::fix_length_and_dec method converted the second and third
arguments to the type of the first argument if they were constant and the first
argument is of the DATE/DATETIME type. That approach worked well for integer
constants and sometimes produced bad result for string constants. The fix for
the bug#16377 wrongly removed that code at all and as a result of this the
comparison of a DATETIME field and an integer constant was carried out in a
wrong way and sometimes led to wrong result sets.

Now the Item_func_between::fix_length_and_dec method converts the second and
third arguments to the type of the first argument if they are constant, the
first argument is of the DATE/DATETIME type and the DATETIME comparator isn't
applicable.
parent d9fcc304
...@@ -411,3 +411,19 @@ if(@bug28261 = f1, '', @bug28261:= f1) ...@@ -411,3 +411,19 @@ if(@bug28261 = f1, '', @bug28261:= f1)
2001-01-01 2001-01-01
2002-02-02 2002-02-02
drop table t1; drop table t1;
create table t1(f1 datetime);
insert into t1 values('2001-01-01'),('2002-02-02');
select * from t1 where f1 between 20020101 and 20070101000000;
f1
2002-02-02 00:00:00
select * from t1 where f1 between 2002010 and 20070101000000;
f1
2001-01-01 00:00:00
2002-02-02 00:00:00
Warnings:
Warning 1292 Incorrect datetime value: '2002010' for column 'f1' at row 1
select * from t1 where f1 between 20020101 and 2007010100000;
f1
Warnings:
Warning 1292 Incorrect datetime value: '2007010100000' for column 'f1' at row 1
drop table t1;
...@@ -271,3 +271,14 @@ select if(@bug28261 = f1, '', @bug28261:= f1) from t1; ...@@ -271,3 +271,14 @@ select if(@bug28261 = f1, '', @bug28261:= f1) from t1;
select if(@bug28261 = f1, '', @bug28261:= f1) from t1; select if(@bug28261 = f1, '', @bug28261:= f1) from t1;
select if(@bug28261 = f1, '', @bug28261:= f1) from t1; select if(@bug28261 = f1, '', @bug28261:= f1) from t1;
drop table t1; drop table t1;
#
# Bug#28778: Wrong result of BETWEEN when comparing a DATETIME field with an
# integer constants.
#
create table t1(f1 datetime);
insert into t1 values('2001-01-01'),('2002-02-02');
select * from t1 where f1 between 20020101 and 20070101000000;
select * from t1 where f1 between 2002010 and 20070101000000;
select * from t1 where f1 between 20020101 and 2007010100000;
drop table t1;
...@@ -1755,6 +1755,23 @@ void Item_func_between::fix_length_and_dec() ...@@ -1755,6 +1755,23 @@ 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 (args[0]->real_item()->type() == FIELD_ITEM &&
thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
thd->lex->sql_command != SQLCOM_SHOW_CREATE)
{
Field *field=((Item_field*) (args[0]->real_item()))->field;
if (field->can_be_compared_as_longlong())
{
/*
The following can't be recoded with || as convert_constant_item
changes the argument
*/
if (convert_constant_item(thd, field,&args[1]))
cmp_type=INT_RESULT; // Works for all types.
if (convert_constant_item(thd, field,&args[2]))
cmp_type=INT_RESULT; // Works for all types.
}
}
} }
......
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