Fix for bug#49199: Optimizer handles incorrectly:
field='const1' AND field='const2' in some cases Building multiple equality predicates containing a constant which is compared as a datetime (with a field) we should take this fact into account and compare the constant with another possible constatns as datetimes as well. E.g. for the SELECT ... WHERE a='2001-01-01' AND a='2001-01-01 00:00:00' we should compare '2001-01-01' with '2001-01-01 00:00:00' as datetimes but not as strings. mysql-test/r/select.result: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - test result. mysql-test/t/select.test: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - test case. sql/item_cmpfunc.cc: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - adding a constant to Item_equal compare it as a datetime value with stored one if there's a date[time] field in a equality predicate. sql/item_cmpfunc.h: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - adding a constant to Item_equal compare it as a datetime value with stored one if there's a date[time] field in a equality predicate. sql/sql_select.cc: Fix for bug#49199: Optimizer handles incorrectly: field='const1' AND field='const2' in some cases - adding a constant to Item_equal compare it as a datetime value with stored one if there's a date[time] field in a equality predicate.
This commit is contained in:
parent
026541c662
commit
f5b51bc1e2
@ -4456,4 +4456,88 @@ SELECT 1 FROM t2 JOIN t1 ON 1=1
|
|||||||
WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a);
|
WHERE a != '1' AND NOT a >= b OR NOT ROW(b,a )<> ROW(a,a);
|
||||||
1
|
1
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
#
|
||||||
|
# Bug #49199: Optimizer handles incorrectly:
|
||||||
|
# field='const1' AND field='const2' in some cases
|
||||||
|
|
||||||
|
CREATE TABLE t1(a DATETIME NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
a
|
||||||
|
2001-01-01 00:00:00
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 system NULL NULL NULL NULL 1
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1(a DATE NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
a
|
||||||
|
2001-01-01
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 system NULL NULL NULL NULL 1
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select '2001-01-01' AS `a` from `test`.`t1` where 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1(a TIMESTAMP NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
a
|
||||||
|
2001-01-01 00:00:00
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 system NULL NULL NULL NULL 1
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select '2001-01-01 00:00:00' AS `a` from `test`.`t1` where 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
|
||||||
|
a b
|
||||||
|
2001-01-01 00:00:00 2001-01-01
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 system NULL NULL NULL NULL 1
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
|
||||||
|
a b
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 0
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01';
|
||||||
|
a b
|
||||||
|
2001-01-01 00:00:00 2001-01-01
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 system NULL NULL NULL NULL 1
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01' AS `b` from `test`.`t1` where 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
|
||||||
|
SELECT x.a, y.a, z.a FROM t1 x
|
||||||
|
JOIN t1 y ON x.a=y.a
|
||||||
|
JOIN t1 z ON y.a=z.a
|
||||||
|
WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00';
|
||||||
|
a a a
|
||||||
|
2001-01-01 00:00:00 2001-01-01 00:00:00 2001-01-01 00:00:00
|
||||||
|
EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x
|
||||||
|
JOIN t1 y ON x.a=y.a
|
||||||
|
JOIN t1 z ON y.a=z.a
|
||||||
|
WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00';
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE x system NULL NULL NULL NULL 1
|
||||||
|
1 SIMPLE y system NULL NULL NULL NULL 1
|
||||||
|
1 SIMPLE z system NULL NULL NULL NULL 1
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select '2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a`,'2001-01-01 00:00:00' AS `a` from `test`.`t1` `x` join `test`.`t1` `y` join `test`.`t1` `z` where 1
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
|
@ -3797,4 +3797,53 @@ SELECT 1 FROM t2 JOIN t1 ON 1=1
|
|||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug #49199: Optimizer handles incorrectly:
|
||||||
|
--echo # field='const1' AND field='const2' in some cases
|
||||||
|
--echo
|
||||||
|
CREATE TABLE t1(a DATETIME NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1(a DATE NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1(a TIMESTAMP NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a='2001-01-01 00:00:00';
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1(a DATETIME NOT NULL, b VARCHAR(20) NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a=b AND b='2001-01-01 00:00:00';
|
||||||
|
|
||||||
|
SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01';
|
||||||
|
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01 00:00:00' AND a=b AND b='2001-01-01';
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1(a DATETIME NOT NULL, b DATE NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES('2001-01-01', '2001-01-01');
|
||||||
|
SELECT x.a, y.a, z.a FROM t1 x
|
||||||
|
JOIN t1 y ON x.a=y.a
|
||||||
|
JOIN t1 z ON y.a=z.a
|
||||||
|
WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00';
|
||||||
|
EXPLAIN EXTENDED SELECT x.a, y.a, z.a FROM t1 x
|
||||||
|
JOIN t1 y ON x.a=y.a
|
||||||
|
JOIN t1 z ON y.a=z.a
|
||||||
|
WHERE x.a='2001-01-01' AND z.a='2001-01-01 00:00:00';
|
||||||
|
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
--echo End of 5.0 tests
|
||||||
|
@ -4903,7 +4903,8 @@ Item *Item_bool_rowready_func2::negated_item()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item_equal::Item_equal(Item_field *f1, Item_field *f2)
|
Item_equal::Item_equal(Item_field *f1, Item_field *f2)
|
||||||
: Item_bool_func(), const_item(0), eval_item(0), cond_false(0)
|
: Item_bool_func(), const_item(0), eval_item(0), cond_false(0),
|
||||||
|
compare_as_dates(FALSE)
|
||||||
{
|
{
|
||||||
const_item_cache= 0;
|
const_item_cache= 0;
|
||||||
fields.push_back(f1);
|
fields.push_back(f1);
|
||||||
@ -4916,6 +4917,7 @@ Item_equal::Item_equal(Item *c, Item_field *f)
|
|||||||
const_item_cache= 0;
|
const_item_cache= 0;
|
||||||
fields.push_back(f);
|
fields.push_back(f);
|
||||||
const_item= c;
|
const_item= c;
|
||||||
|
compare_as_dates= f->is_datetime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4930,9 +4932,45 @@ Item_equal::Item_equal(Item_equal *item_equal)
|
|||||||
fields.push_back(item);
|
fields.push_back(item);
|
||||||
}
|
}
|
||||||
const_item= item_equal->const_item;
|
const_item= item_equal->const_item;
|
||||||
|
compare_as_dates= item_equal->compare_as_dates;
|
||||||
cond_false= item_equal->cond_false;
|
cond_false= item_equal->cond_false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_equal::compare_const(Item *c)
|
||||||
|
{
|
||||||
|
if (compare_as_dates)
|
||||||
|
{
|
||||||
|
cmp.set_datetime_cmp_func(&c, &const_item);
|
||||||
|
cond_false= cmp.compare();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Item_func_eq *func= new Item_func_eq(c, const_item);
|
||||||
|
func->set_cmp_func();
|
||||||
|
func->quick_fix_field();
|
||||||
|
cond_false= !func->val_int();
|
||||||
|
}
|
||||||
|
if (cond_false)
|
||||||
|
const_item_cache= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_equal::add(Item *c, Item_field *f)
|
||||||
|
{
|
||||||
|
if (cond_false)
|
||||||
|
return;
|
||||||
|
if (!const_item)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(f);
|
||||||
|
const_item= c;
|
||||||
|
compare_as_dates= f->is_datetime();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
compare_const(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_equal::add(Item *c)
|
void Item_equal::add(Item *c)
|
||||||
{
|
{
|
||||||
if (cond_false)
|
if (cond_false)
|
||||||
@ -4942,11 +4980,7 @@ void Item_equal::add(Item *c)
|
|||||||
const_item= c;
|
const_item= c;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Item_func_eq *func= new Item_func_eq(c, const_item);
|
compare_const(c);
|
||||||
func->set_cmp_func();
|
|
||||||
func->quick_fix_field();
|
|
||||||
if ((cond_false= !func->val_int()))
|
|
||||||
const_item_cache= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item_equal::add(Item_field *f)
|
void Item_equal::add(Item_field *f)
|
||||||
|
@ -1477,7 +1477,9 @@ class Item_equal: public Item_bool_func
|
|||||||
List<Item_field> fields; /* list of equal field items */
|
List<Item_field> fields; /* list of equal field items */
|
||||||
Item *const_item; /* optional constant item equal to fields items */
|
Item *const_item; /* optional constant item equal to fields items */
|
||||||
cmp_item *eval_item;
|
cmp_item *eval_item;
|
||||||
|
Arg_comparator cmp;
|
||||||
bool cond_false;
|
bool cond_false;
|
||||||
|
bool compare_as_dates;
|
||||||
public:
|
public:
|
||||||
inline Item_equal()
|
inline Item_equal()
|
||||||
: Item_bool_func(), const_item(0), eval_item(0), cond_false(0)
|
: Item_bool_func(), const_item(0), eval_item(0), cond_false(0)
|
||||||
@ -1486,6 +1488,8 @@ public:
|
|||||||
Item_equal(Item *c, Item_field *f);
|
Item_equal(Item *c, Item_field *f);
|
||||||
Item_equal(Item_equal *item_equal);
|
Item_equal(Item_equal *item_equal);
|
||||||
inline Item* get_const() { return const_item; }
|
inline Item* get_const() { return const_item; }
|
||||||
|
void compare_const(Item *c);
|
||||||
|
void add(Item *c, Item_field *f);
|
||||||
void add(Item *c);
|
void add(Item *c);
|
||||||
void add(Item_field *f);
|
void add(Item_field *f);
|
||||||
uint members();
|
uint members();
|
||||||
|
@ -7237,7 +7237,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
|
|||||||
already contains a constant and its value is not equal to
|
already contains a constant and its value is not equal to
|
||||||
the value of const_item.
|
the value of const_item.
|
||||||
*/
|
*/
|
||||||
item_equal->add(const_item);
|
item_equal->add(const_item, field_item);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user