Merge
This commit is contained in:
commit
752d5d022d
@ -5155,7 +5155,7 @@ a b c
|
||||
8 8 8
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# Bug mdev-4413: another manifestations of bug mdev-2474
|
||||
# Bug mdev-4413: another manifestations of bug mdev-4274
|
||||
# (valgrind complains)
|
||||
#
|
||||
CREATE TABLE t1 (a int, b int) ENGINE=MyISAM;
|
||||
@ -5167,4 +5167,54 @@ WHERE c = a AND
|
||||
( 0 OR ( b BETWEEN 45 AND 300 OR a > 45 AND a < 100 ) AND b = c );
|
||||
a b c
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Bug mdev-4355: equalities from the result of simplification of OR
|
||||
# are not propagated to lower AND levels
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,101),(2,102),(3,103),(4,104),(5,11);
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (1 != 1 OR a = 5) AND (b != 1 OR a = 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (1 != 1 OR a = 5) AND (b != 1 OR a = 1);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (1 != 1 OR a = 5);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (1 != 1 OR a = 5);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (a = 5 OR 1 != 1);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where 0
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
a b
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = 5) and (`test`.`t1`.`a` = 5))
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
a b
|
||||
DROP TABLE t1;
|
||||
End of 5.3 tests
|
||||
|
@ -5166,7 +5166,7 @@ a b c
|
||||
8 8 8
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# Bug mdev-4413: another manifestations of bug mdev-2474
|
||||
# Bug mdev-4413: another manifestations of bug mdev-4274
|
||||
# (valgrind complains)
|
||||
#
|
||||
CREATE TABLE t1 (a int, b int) ENGINE=MyISAM;
|
||||
@ -5178,6 +5178,56 @@ WHERE c = a AND
|
||||
( 0 OR ( b BETWEEN 45 AND 300 OR a > 45 AND a < 100 ) AND b = c );
|
||||
a b c
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Bug mdev-4355: equalities from the result of simplification of OR
|
||||
# are not propagated to lower AND levels
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,101),(2,102),(3,103),(4,104),(5,11);
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (1 != 1 OR a = 5) AND (b != 1 OR a = 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (1 != 1 OR a = 5) AND (b != 1 OR a = 1);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (1 != 1 OR a = 5);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (1 != 1 OR a = 5);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (a = 5 OR 1 != 1);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where 0
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
a b
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = 5) and (`test`.`t1`.`a` = 5))
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
a b
|
||||
DROP TABLE t1;
|
||||
End of 5.3 tests
|
||||
set join_cache_level=default;
|
||||
show variables like 'join_cache_level';
|
||||
|
@ -5155,7 +5155,7 @@ a b c
|
||||
8 8 8
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# Bug mdev-4413: another manifestations of bug mdev-2474
|
||||
# Bug mdev-4413: another manifestations of bug mdev-4274
|
||||
# (valgrind complains)
|
||||
#
|
||||
CREATE TABLE t1 (a int, b int) ENGINE=MyISAM;
|
||||
@ -5167,4 +5167,54 @@ WHERE c = a AND
|
||||
( 0 OR ( b BETWEEN 45 AND 300 OR a > 45 AND a < 100 ) AND b = c );
|
||||
a b c
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Bug mdev-4355: equalities from the result of simplification of OR
|
||||
# are not propagated to lower AND levels
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,101),(2,102),(3,103),(4,104),(5,11);
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (1 != 1 OR a = 5) AND (b != 1 OR a = 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (1 != 1 OR a = 5) AND (b != 1 OR a = 1);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (1 != 1 OR a = 5);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (1 != 1 OR a = 5);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and (`test`.`t1`.`b` <> 1))
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (a = 5 OR 1 != 1);
|
||||
a b
|
||||
5 11
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where 0
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
a b
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 5 100.00 Using where
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`b` = 5) and (`test`.`t1`.`a` = 5))
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
a b
|
||||
DROP TABLE t1;
|
||||
End of 5.3 tests
|
||||
|
@ -1380,7 +1380,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
|
||||
2 MATERIALIZED t3 hash_ALL NULL #hash#$hj 5 test.t2.i2 3 100.00 Using where; Using join buffer (flat, BNLH join)
|
||||
Warnings:
|
||||
Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where ((`test`.`t3`.`i3` = `test`.`t2`.`i2`) and (`test`.`t1`.`i1` = `test`.`t2`.`i2`) and (`test`.`t2`.`i2` > 0))
|
||||
Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where ((`test`.`t3`.`i3` = `test`.`t2`.`i2`) and (`test`.`t1`.`i1` = `test`.`t2`.`i2`) and (`test`.`t3`.`i3` > 0))
|
||||
SELECT * FROM t1
|
||||
WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 > 0 AND i3 = i2 OR 1=2);
|
||||
i1
|
||||
|
@ -4326,7 +4326,7 @@ SELECT * FROM t1 INNER JOIN t2 ON ( c = a )
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # Bug mdev-4413: another manifestations of bug mdev-2474
|
||||
--echo # Bug mdev-4413: another manifestations of bug mdev-4274
|
||||
--echo # (valgrind complains)
|
||||
--echo #
|
||||
|
||||
@ -4342,4 +4342,34 @@ SELECT * FROM t1, t2
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # Bug mdev-4355: equalities from the result of simplification of OR
|
||||
--echo # are not propagated to lower AND levels
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES (1,101),(2,102),(3,103),(4,104),(5,11);
|
||||
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (1 != 1 OR a = 5) AND (b != 1 OR a = 1);
|
||||
SELECT * FROM t1 WHERE (1 != 1 OR a = 5) AND (b != 1 OR a = 1);
|
||||
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (1 != 1 OR a = 5);
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (1 != 1 OR a = 5);
|
||||
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (a = 5 OR 1 != 1);
|
||||
SELECT * FROM t1 WHERE (b != 1 OR a = 1) AND (a = 5 OR 1 != 1);
|
||||
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
|
||||
EXPLAIN EXTENDED
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.3 tests
|
||||
|
@ -5608,10 +5608,12 @@ void Item_equal::merge(Item_equal *item)
|
||||
@brief
|
||||
Merge members of another Item_equal object into this one
|
||||
|
||||
@param item multiple equality whose members are to be merged
|
||||
@param item multiple equality whose members are to be merged
|
||||
@param save_merged keep the list of equalities in 'item' intact
|
||||
(e.g. for other merges)
|
||||
|
||||
@details
|
||||
If the Item_equal 'item' happened to have some elements of the list
|
||||
If the Item_equal 'item' happens to have some elements of the list
|
||||
of equal items belonging to 'this' object then the function merges
|
||||
the equal items from 'item' into this list.
|
||||
If both lists contains constants and they are different then
|
||||
@ -5626,24 +5628,45 @@ void Item_equal::merge(Item_equal *item)
|
||||
The method 'merge' just joins the list of equal items belonging to 'item'
|
||||
to the list of equal items belonging to this object assuming that the lists
|
||||
are disjoint. It would be more correct to call the method 'join'.
|
||||
The method 'merge_with_check' really merges two lists of equal items if they
|
||||
have common members.
|
||||
The method 'merge_into_with_check' really merges two lists of equal items if
|
||||
they have common members.
|
||||
*/
|
||||
|
||||
bool Item_equal::merge_with_check(Item_equal *item)
|
||||
bool Item_equal::merge_with_check(Item_equal *item, bool save_merged)
|
||||
{
|
||||
bool intersected= FALSE;
|
||||
Item_equal_fields_iterator_slow fi(*this);
|
||||
Item_equal_fields_iterator_slow fi(*item);
|
||||
|
||||
while (fi++)
|
||||
{
|
||||
if (item->contains(fi.get_curr_field()))
|
||||
if (contains(fi.get_curr_field()))
|
||||
{
|
||||
fi.remove();
|
||||
intersected= TRUE;
|
||||
if (!save_merged)
|
||||
fi.remove();
|
||||
}
|
||||
}
|
||||
if (intersected)
|
||||
item->merge(this);
|
||||
{
|
||||
if (!save_merged)
|
||||
merge(item);
|
||||
else
|
||||
{
|
||||
Item *c= item->get_const();
|
||||
if (c)
|
||||
add_const(c);
|
||||
if (!cond_false)
|
||||
{
|
||||
Item *item;
|
||||
fi.rewind();
|
||||
while ((item= fi++))
|
||||
{
|
||||
if (!contains(fi.get_curr_field()))
|
||||
add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return intersected;
|
||||
}
|
||||
|
||||
@ -5652,17 +5675,25 @@ bool Item_equal::merge_with_check(Item_equal *item)
|
||||
@brief
|
||||
Merge this object into a list of Item_equal objects
|
||||
|
||||
@param list the list of Item_equal objects to merge into
|
||||
@param list the list of Item_equal objects to merge into
|
||||
@param save_merged keep the list of equalities in 'this' intact
|
||||
(e.g. for other merges)
|
||||
@param only_intersected do not merge if there are no common members
|
||||
in any of Item_equal objects from the list
|
||||
and this Item_equal
|
||||
|
||||
@details
|
||||
If the list of equal items from 'this' object contains common members
|
||||
with the lists of equal items belonging to Item_equal objects from 'list'
|
||||
then all involved Item_equal objects e1,...,ek are merged into one
|
||||
Item equal that replaces e1,...,ek in the 'list'. Otherwise this
|
||||
Item equal that replaces e1,...,ek in the 'list'. Otherwise, in the case
|
||||
when the value of the parameter only_if_intersected is false, this
|
||||
Item_equal is joined to the 'list'.
|
||||
*/
|
||||
|
||||
void Item_equal::merge_into_list(List<Item_equal> *list)
|
||||
void Item_equal::merge_into_list(List<Item_equal> *list,
|
||||
bool save_merged,
|
||||
bool only_intersected)
|
||||
{
|
||||
Item_equal *item;
|
||||
List_iterator<Item_equal> it(*list);
|
||||
@ -5671,16 +5702,16 @@ void Item_equal::merge_into_list(List<Item_equal> *list)
|
||||
{
|
||||
if (!merge_into)
|
||||
{
|
||||
if (merge_with_check(item))
|
||||
if (item->merge_with_check(this, save_merged))
|
||||
merge_into= item;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item->merge_with_check(merge_into))
|
||||
if (merge_into->merge_with_check(item, false))
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
if (!merge_into)
|
||||
if (!only_intersected && !merge_into)
|
||||
list->push_back(this);
|
||||
}
|
||||
|
||||
|
@ -1761,8 +1761,9 @@ public:
|
||||
/** Get number of field items / references to field items in this object */
|
||||
uint n_field_items() { return equal_items.elements-test(with_const); }
|
||||
void merge(Item_equal *item);
|
||||
bool merge_with_check(Item_equal *equal_item);
|
||||
void merge_into_list(List<Item_equal> *list);
|
||||
bool merge_with_check(Item_equal *equal_item, bool save_merged);
|
||||
void merge_into_list(List<Item_equal> *list, bool save_merged,
|
||||
bool only_intersected);
|
||||
void update_const();
|
||||
enum Functype functype() const { return MULT_EQUAL_FUNC; }
|
||||
longlong val_int();
|
||||
|
@ -13133,14 +13133,175 @@ optimize_cond(JOIN *join, COND *conds,
|
||||
|
||||
|
||||
/**
|
||||
Remove const and eq items.
|
||||
@brief
|
||||
Propagate multiple equalities to the sub-expressions of a condition
|
||||
|
||||
@param thd thread handle
|
||||
@param cond the condition where equalities are to be propagated
|
||||
@param *new_equalities the multiple equalities to be propagated
|
||||
@param inherited path to all inherited multiple equality items
|
||||
@param[out] is_simplifiable_cond 'cond' may be simplified after the
|
||||
propagation of the equalities
|
||||
|
||||
@details
|
||||
The function recursively traverses the tree of the condition 'cond' and
|
||||
for each its AND sub-level of any depth the function merges the multiple
|
||||
equalities from the list 'new_equalities' into the multiple equalities
|
||||
attached to the AND item created for this sub-level.
|
||||
The function also [re]sets references to the equalities formed by the
|
||||
merges of multiple equalities in all field items occurred in 'cond'
|
||||
that are encountered in the equalities.
|
||||
If the result of any merge of multiple equalities is an impossible
|
||||
condition the function returns TRUE in the parameter is_simplifiable_cond.
|
||||
*/
|
||||
|
||||
void propagate_new_equalities(THD *thd, Item *cond,
|
||||
List<Item_equal> *new_equalities,
|
||||
COND_EQUAL *inherited,
|
||||
bool *is_simplifiable_cond)
|
||||
{
|
||||
if (cond->type() == Item::COND_ITEM)
|
||||
{
|
||||
bool and_level= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
|
||||
if (and_level)
|
||||
{
|
||||
Item_cond_and *cond_and= (Item_cond_and *) cond;
|
||||
List<Item_equal> *cond_equalities= &cond_and->cond_equal.current_level;
|
||||
inherited= cond_and->cond_equal.upper_levels;
|
||||
if (!cond_equalities->is_empty() && cond_equalities != new_equalities)
|
||||
{
|
||||
Item_equal *equal_item;
|
||||
List_iterator<Item_equal> it(*new_equalities);
|
||||
while ((equal_item= it++))
|
||||
{
|
||||
equal_item->merge_into_list(cond_equalities, true, true);
|
||||
}
|
||||
List_iterator<Item_equal> ei(*cond_equalities);
|
||||
while ((equal_item= ei++))
|
||||
{
|
||||
if (equal_item->const_item() && !equal_item->val_int())
|
||||
{
|
||||
*is_simplifiable_cond= true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item *item;
|
||||
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
|
||||
while ((item= li++))
|
||||
{
|
||||
propagate_new_equalities(thd, item, new_equalities, inherited,
|
||||
is_simplifiable_cond);
|
||||
}
|
||||
}
|
||||
else if (cond->type() == Item::FUNC_ITEM &&
|
||||
((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
|
||||
{
|
||||
Item_equal *equal_item;
|
||||
List_iterator<Item_equal> it(*new_equalities);
|
||||
Item_equal *equality= (Item_equal *) cond;
|
||||
while ((equal_item= it++))
|
||||
{
|
||||
equality->merge_with_check(equal_item, true);
|
||||
}
|
||||
if (equality->const_item() && !equality->val_int())
|
||||
*is_simplifiable_cond= true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uchar* is_subst_valid= (uchar *) Item::ANY_SUBST;
|
||||
cond= cond->compile(&Item::subst_argument_checker,
|
||||
&is_subst_valid,
|
||||
&Item::equal_fields_propagator,
|
||||
(uchar *) inherited);
|
||||
cond->update_used_tables();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Evaluate all constant boolean sub-expressions in a condition
|
||||
|
||||
@param thd thread handle
|
||||
@param cond condition where where to evaluate constant sub-expressions
|
||||
@param[out] cond_value : the returned value of the condition
|
||||
(TRUE/FALSE/UNKNOWN:
|
||||
Item::COND_TRUE/Item::COND_FALSE/Item::COND_OK)
|
||||
@return
|
||||
Return new item, or NULL if no condition @n
|
||||
cond_value is set to according:
|
||||
- COND_OK : query is possible (field = constant)
|
||||
- COND_TRUE : always true ( 1 = 1 )
|
||||
- COND_FALSE : always false ( 1 = 2 )
|
||||
the item that is the result of the substitution of all inexpensive constant
|
||||
boolean sub-expressions into cond, or,
|
||||
NULL if the condition is constant and is evaluated to FALSE.
|
||||
|
||||
@details
|
||||
This function looks for all inexpensive constant boolean sub-expressions in
|
||||
the given condition 'cond' and substitutes them for their values.
|
||||
For example, the condition 2 > (5 + 1) or a < (10 / 2)
|
||||
will be transformed to the condition a < (10 / 2).
|
||||
Note that a constant sub-expression is evaluated only if it is constant and
|
||||
inexpensive. A sub-expression with an uncorrelated subquery may be evaluated
|
||||
only if the subquery is considered as inexpensive.
|
||||
The function does not evaluate a constant sub-expression if it is not on one
|
||||
of AND/OR levels of the condition 'cond'. For example, the subquery in the
|
||||
condition a > (select max(b) from t1 where b > 5) will never be evaluated
|
||||
by this function.
|
||||
If a constant boolean sub-expression is evaluated to TRUE then:
|
||||
- when the sub-expression is a conjunct of an AND formula it is simply
|
||||
removed from this formula
|
||||
- when the sub-expression is a disjunct of an OR formula the whole OR
|
||||
formula is converted to TRUE
|
||||
If a constant boolean sub-expression is evaluated to FALSE then:
|
||||
- when the sub-expression is a disjunct of an OR formula it is simply
|
||||
removed from this formula
|
||||
- when the sub-expression is a conjuct of an AND formula the whole AND
|
||||
formula is converted to FALSE
|
||||
When a disjunct/conjunct is removed from an OR/AND formula it might happen
|
||||
that there is only one conjunct/disjunct remaining. In this case this
|
||||
remaining disjunct/conjunct must be merged into underlying AND/OR formula,
|
||||
because AND/OR levels must alternate in the same way as they alternate
|
||||
after fix_fields() is called for the original condition.
|
||||
The specifics of merging a formula f into an AND formula A appears
|
||||
when A contains multiple equalities and f contains multiple equalities.
|
||||
In this case the multiple equalities from f and A have to be merged.
|
||||
After this the resulting multiple equalities have to be propagated into
|
||||
the all AND/OR levels of the formula A (see propagate_new_equalities()).
|
||||
The propagation of multiple equalities might result in forming multiple
|
||||
equalities that are always FALSE. This, in its turn, might trigger further
|
||||
simplification of the condition.
|
||||
|
||||
@note
|
||||
EXAMPLE 1:
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
First 1 != 1 will be removed from the second conjunct:
|
||||
=> SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5 AND a = 5);
|
||||
Then (b = 5 AND a = 5) will be merged into the top level condition:
|
||||
=> SELECT * FROM t1 WHERE (b = 1 OR a = 1) AND (b = 5) AND (a = 5);
|
||||
Then (b = 5), (a = 5) will be propagated into the disjuncs of
|
||||
(b = 1 OR a = 1):
|
||||
=> SELECT * FROM t1 WHERE ((b = 1) AND (b = 5) AND (a = 5) OR
|
||||
(a = 1) AND (b = 5) AND (a = 5)) AND
|
||||
(b = 5) AND (a = 5)
|
||||
=> SELECT * FROM t1 WHERE ((FALSE AND (a = 5)) OR
|
||||
(FALSE AND (b = 5))) AND
|
||||
(b = 5) AND (a = 5)
|
||||
After this an additional call of remove_eq_conds() converts it
|
||||
to FALSE
|
||||
|
||||
EXAMPLE 2:
|
||||
SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5 OR 1 != 1);
|
||||
=> SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5 AND a = 5);
|
||||
=> SELECT * FROM t1 WHERE (b = 1 OR a = 5) AND (b = 5) AND (a = 5);
|
||||
=> SELECT * FROM t1 WHERE ((b = 1) AND (b = 5) AND (a = 5) OR
|
||||
(a = 5) AND (b = 5) AND (a = 5)) AND
|
||||
(b = 5) AND (a = 5)
|
||||
=> SELECT * FROM t1 WHERE ((FALSE AND (a = 5)) OR
|
||||
((b = 5) AND (a = 5))) AND
|
||||
(b = 5) AND (a = 5)
|
||||
After this an additional call of remove_eq_conds() converts it to
|
||||
=> SELECT * FROM t1 WHERE (b = 5) AND (a = 5)
|
||||
*/
|
||||
|
||||
COND *
|
||||
@ -13148,9 +13309,11 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
{
|
||||
if (cond->type() == Item::COND_ITEM)
|
||||
{
|
||||
List<Item_equal> new_equalities;
|
||||
bool and_level= ((Item_cond*) cond)->functype()
|
||||
== Item_func::COND_AND_FUNC;
|
||||
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
|
||||
List<Item> *cond_arg_list= ((Item_cond*) cond)->argument_list();
|
||||
List_iterator<Item> li(*cond_arg_list);
|
||||
Item::cond_result tmp_cond_value;
|
||||
bool should_fix_fields=0;
|
||||
|
||||
@ -13160,92 +13323,72 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
{
|
||||
Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value);
|
||||
if (!new_item)
|
||||
{
|
||||
/* This can happen only when item is converted to TRUE or FALSE */
|
||||
li.remove();
|
||||
}
|
||||
else if (item != new_item)
|
||||
{
|
||||
if (and_level)
|
||||
{
|
||||
/*
|
||||
Take a special care of multiple equality predicates
|
||||
that may be part of 'cond' and 'new_item'.
|
||||
Those multiple equalities that have common members
|
||||
must be merged.
|
||||
*/
|
||||
Item_cond_and *cond_and= (Item_cond_and *) cond;
|
||||
List<Item_equal> *cond_equal_items=
|
||||
&cond_and->cond_equal.current_level;
|
||||
List<Item> *cond_and_list= cond_and->argument_list();
|
||||
|
||||
if (new_item->type() == Item::COND_ITEM &&
|
||||
((Item_cond*) new_item)->functype() == Item_func::COND_AND_FUNC)
|
||||
{
|
||||
Item_cond_and *new_item_and= (Item_cond_and *) new_item;
|
||||
List<Item_equal> *new_item_equal_items=
|
||||
&new_item_and->cond_equal.current_level;
|
||||
List<Item> *new_item_and_list= new_item_and->argument_list();
|
||||
cond_and_list->disjoin((List<Item>*) cond_equal_items);
|
||||
new_item_and_list->disjoin((List<Item>*) new_item_equal_items);
|
||||
Item_equal *equal_item;
|
||||
List_iterator<Item_equal> it(*new_item_equal_items);
|
||||
while ((equal_item= it++))
|
||||
{
|
||||
equal_item->merge_into_list(cond_equal_items);
|
||||
}
|
||||
if (new_item_and_list->is_empty())
|
||||
li.remove();
|
||||
else
|
||||
{
|
||||
Item *list_item;
|
||||
Item *new_list_item;
|
||||
uint cnt= new_item_and_list->elements;
|
||||
List_iterator<Item> it(*new_item_and_list);
|
||||
while ((list_item= it++))
|
||||
{
|
||||
uchar* is_subst_valid= (uchar *) Item::ANY_SUBST;
|
||||
new_list_item=
|
||||
list_item->compile(&Item::subst_argument_checker,
|
||||
&is_subst_valid,
|
||||
&Item::equal_fields_propagator,
|
||||
(uchar *) &cond_and->cond_equal);
|
||||
if (new_list_item != list_item)
|
||||
it.replace(new_list_item);
|
||||
new_list_item->update_used_tables();
|
||||
}
|
||||
li.replace(*new_item_and_list);
|
||||
for (cnt--; cnt; cnt--)
|
||||
item= li++;
|
||||
}
|
||||
cond_and_list->concat((List<Item>*) cond_equal_items);
|
||||
}
|
||||
else if (new_item->type() == Item::FUNC_ITEM &&
|
||||
((Item_cond*) new_item)->functype() ==
|
||||
Item_func::MULT_EQUAL_FUNC)
|
||||
/*
|
||||
This can happen when:
|
||||
- item was an OR formula converted to one disjunct
|
||||
- item was an AND formula converted to one conjunct
|
||||
In these cases the disjunct/conjunct must be merged into the
|
||||
argument list of cond.
|
||||
*/
|
||||
if (new_item->type() == Item::COND_ITEM)
|
||||
{
|
||||
DBUG_ASSERT(((Item_cond *) cond)->functype() ==
|
||||
((Item_cond *) new_item)->functype());
|
||||
List<Item> *new_item_arg_list=
|
||||
((Item_cond *) new_item)->argument_list();
|
||||
if (and_level)
|
||||
{
|
||||
cond_and_list->disjoin((List<Item>*) cond_equal_items);
|
||||
((Item_equal *) new_item)->merge_into_list(cond_equal_items);
|
||||
li.remove();
|
||||
cond_and_list->concat((List<Item>*) cond_equal_items);
|
||||
/*
|
||||
If new_item is an AND formula then multiple equalities
|
||||
of new_item_arg_list must merged into multiple equalities
|
||||
of cond_arg_list.
|
||||
*/
|
||||
List<Item_equal> *new_item_equalities=
|
||||
&((Item_cond_and *) new_item)->cond_equal.current_level;
|
||||
if (!new_item_equalities->is_empty())
|
||||
{
|
||||
/*
|
||||
Cut the multiple equalities from the new_item_arg_list and
|
||||
append them on the list new_equalities. Later the equalities
|
||||
from this list will be merged into the multiple equalities
|
||||
of cond_arg_list all together.
|
||||
*/
|
||||
new_item_arg_list->disjoin((List<Item> *) new_item_equalities);
|
||||
new_equalities.concat(new_item_equalities);
|
||||
}
|
||||
}
|
||||
else
|
||||
li.replace(new_item);
|
||||
if (new_item_arg_list->is_empty())
|
||||
li.remove();
|
||||
else
|
||||
{
|
||||
uint cnt= new_item_arg_list->elements;
|
||||
li.replace(*new_item_arg_list);
|
||||
/* Make iterator li ignore new items */
|
||||
for (cnt--; cnt; cnt--)
|
||||
li++;
|
||||
should_fix_fields= 1;
|
||||
}
|
||||
}
|
||||
else if (and_level &&
|
||||
new_item->type() == Item::FUNC_ITEM &&
|
||||
((Item_cond*) new_item)->functype() ==
|
||||
Item_func::MULT_EQUAL_FUNC)
|
||||
{
|
||||
li.remove();
|
||||
new_equalities.push_back((Item_equal *) new_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_item->type() == Item::COND_ITEM &&
|
||||
((Item_cond*) new_item)->functype() ==
|
||||
((Item_cond*) cond)->functype())
|
||||
{
|
||||
List<Item> *arg_list= ((Item_cond*) new_item)->argument_list();
|
||||
uint cnt= arg_list->elements;
|
||||
li.replace(*arg_list);
|
||||
for ( cnt--; cnt; cnt--)
|
||||
item= li++;
|
||||
}
|
||||
else
|
||||
li.replace(new_item);
|
||||
{
|
||||
li.replace(new_item);
|
||||
should_fix_fields= 1;
|
||||
}
|
||||
should_fix_fields=1;
|
||||
}
|
||||
}
|
||||
if (*cond_value == Item::COND_UNDEF)
|
||||
*cond_value=tmp_cond_value;
|
||||
switch (tmp_cond_value) {
|
||||
@ -13271,6 +13414,53 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
break; /* purecov: deadcode */
|
||||
}
|
||||
}
|
||||
if (!new_equalities.is_empty())
|
||||
{
|
||||
DBUG_ASSERT(and_level);
|
||||
/*
|
||||
Merge multiple equalities that were cut from the results of
|
||||
simplification of OR formulas converted into AND formulas.
|
||||
These multiple equalities are to be merged into the
|
||||
multiple equalities of cond_arg_list.
|
||||
*/
|
||||
COND_EQUAL *cond_equal= &((Item_cond_and *) cond)->cond_equal;
|
||||
List<Item_equal> *cond_equalities= &cond_equal->current_level;
|
||||
cond_arg_list->disjoin((List<Item> *) cond_equalities);
|
||||
Item_equal *equality;
|
||||
List_iterator_fast<Item_equal> it(new_equalities);
|
||||
while ((equality= it++))
|
||||
{
|
||||
equality->merge_into_list(cond_equalities, false, false);
|
||||
List_iterator_fast<Item_equal> ei(*cond_equalities);
|
||||
while ((equality= ei++))
|
||||
{
|
||||
if (equality->const_item() && !equality->val_int())
|
||||
{
|
||||
*cond_value= Item::COND_FALSE;
|
||||
return (COND*) 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
cond_arg_list->concat((List<Item> *) cond_equalities);
|
||||
/*
|
||||
Propagate the newly formed multiple equalities to
|
||||
the all AND/OR levels of cond
|
||||
*/
|
||||
bool is_simplifiable_cond= true;
|
||||
propagate_new_equalities(thd, cond, cond_equalities,
|
||||
cond_equal->upper_levels,
|
||||
&is_simplifiable_cond);
|
||||
/*
|
||||
If the above propagation of multiple equalities brings us
|
||||
to multiple equalities that are always FALSE then try to
|
||||
simplify the condition with remove_eq_cond() again.
|
||||
*/
|
||||
if (is_simplifiable_cond)
|
||||
{
|
||||
if (!(cond= remove_eq_conds(thd, cond, cond_value)))
|
||||
return cond;
|
||||
}
|
||||
}
|
||||
if (should_fix_fields)
|
||||
cond->update_used_tables();
|
||||
|
||||
@ -13382,6 +13572,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
||||
return cond; // Point at next and level
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check if equality can be used in removing components of GROUP BY/DISTINCT
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user