Commit dfd8f021 authored by igor@rurik.mysql.com's avatar igor@rurik.mysql.com

Fixed bug #18618.

If the second or the third argument of a BETWEEN predicate was
a constant expression, like '2005.09.01' - INTERVAL 6 MONTH,
while the other two arguments were fields then the predicate 
was evaluated incorrectly and the query returned a wrong
result set.
The bug was introduced in 5.0.17 when in the fix for 12612.
parent e2feeb88
...@@ -847,3 +847,28 @@ timestampdiff(year,'2004-02-28','2005-02-28') ...@@ -847,3 +847,28 @@ timestampdiff(year,'2004-02-28','2005-02-28')
select timestampdiff(year,'2004-02-29','2005-02-28'); select timestampdiff(year,'2004-02-29','2005-02-28');
timestampdiff(year,'2004-02-29','2005-02-28') timestampdiff(year,'2004-02-29','2005-02-28')
0 0
CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, day date);
CREATE TABLE t2 (id int NOT NULL PRIMARY KEY, day date);
INSERT INTO t1 VALUES
(1, '2005-06-01'), (2, '2005-02-01'), (3, '2005-07-01');
INSERT INTO t2 VALUES
(1, '2005-08-01'), (2, '2005-06-15'), (3, '2005-07-15');
SELECT * FROM t1, t2
WHERE t1.day BETWEEN
'2005.09.01' - INTERVAL 6 MONTH AND t2.day;
id day id day
1 2005-06-01 1 2005-08-01
3 2005-07-01 1 2005-08-01
1 2005-06-01 2 2005-06-15
1 2005-06-01 3 2005-07-15
3 2005-07-01 3 2005-07-15
SELECT * FROM t1, t2
WHERE CAST(t1.day AS DATE) BETWEEN
'2005.09.01' - INTERVAL 6 MONTH AND t2.day;
id day id day
1 2005-06-01 1 2005-08-01
3 2005-07-01 1 2005-08-01
1 2005-06-01 2 2005-06-15
1 2005-06-01 3 2005-07-15
3 2005-07-01 3 2005-07-15
DROP TABLE t1,t2;
...@@ -446,4 +446,26 @@ select timestampdiff(year,'1999-09-11','2001-9-11'); ...@@ -446,4 +446,26 @@ select timestampdiff(year,'1999-09-11','2001-9-11');
select timestampdiff(year,'2004-02-28','2005-02-28'); select timestampdiff(year,'2004-02-28','2005-02-28');
select timestampdiff(year,'2004-02-29','2005-02-28'); select timestampdiff(year,'2004-02-29','2005-02-28');
#
# Bug #18618: BETWEEN for dates with the second argument being a constant
# expression and the first and the third arguments being fields
#
CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, day date);
CREATE TABLE t2 (id int NOT NULL PRIMARY KEY, day date);
INSERT INTO t1 VALUES
(1, '2005-06-01'), (2, '2005-02-01'), (3, '2005-07-01');
INSERT INTO t2 VALUES
(1, '2005-08-01'), (2, '2005-06-15'), (3, '2005-07-15');
SELECT * FROM t1, t2
WHERE t1.day BETWEEN
'2005.09.01' - INTERVAL 6 MONTH AND t2.day;
SELECT * FROM t1, t2
WHERE CAST(t1.day AS DATE) BETWEEN
'2005.09.01' - INTERVAL 6 MONTH AND t2.day;
DROP TABLE t1,t2;
# End of 5.0 tests # End of 5.0 tests
...@@ -52,7 +52,6 @@ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) ...@@ -52,7 +52,6 @@ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
{ {
uint i; uint i;
Field *field= NULL; Field *field= NULL;
bool all_constant= TRUE;
/* If the first argument is a FIELD_ITEM, pull out the field. */ /* If the first argument is a FIELD_ITEM, pull out the field. */
if (items[0]->real_item()->type() == Item::FIELD_ITEM) if (items[0]->real_item()->type() == Item::FIELD_ITEM)
...@@ -65,16 +64,9 @@ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) ...@@ -65,16 +64,9 @@ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
for (i= 1; i < nitems; i++) for (i= 1; i < nitems; i++)
{ {
type[0]= item_cmp_type(type[0], items[i]->result_type()); type[0]= item_cmp_type(type[0], items[i]->result_type());
if (field && !convert_constant_item(thd, field, &items[i])) if (field && convert_constant_item(thd, field, &items[i]))
all_constant= FALSE; type[0]= INT_RESULT;
} }
/*
If we had a field that can be compared as a longlong, and all constant
items, then the aggregate result will be an INT_RESULT.
*/
if (field && all_constant)
type[0]= INT_RESULT;
} }
......
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