diff options
author | Igor Babaev <igor@askmonty.org> | 2013-05-03 22:46:45 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2013-05-03 22:46:45 -0700 |
commit | 920c479c6ebd2236dbe5510e5ed8b748bf0ee158 (patch) | |
tree | b5895605eba5f91e3cf0cce0b870076e6571f98c | |
parent | b249680fd11f5c9102f7a22cf638f3872d5c2e61 (diff) | |
download | mariadb-git-920c479c6ebd2236dbe5510e5ed8b748bf0ee158.tar.gz |
Fixed bug mdev-4336.
When iterating over a list of conditions using List_iterator
the function remove_eq_conds should skip all predicates that
replace a condition from the list. Otherwise it can come to
an infinite recursion.
-rw-r--r-- | mysql-test/r/join_outer.result | 14 | ||||
-rw-r--r-- | mysql-test/r/join_outer_jcl6.result | 14 | ||||
-rw-r--r-- | mysql-test/t/join_outer.test | 17 | ||||
-rw-r--r-- | sql/sql_select.cc | 15 |
4 files changed, 57 insertions, 3 deletions
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 7bc95e78041..723b2a88382 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1822,4 +1822,18 @@ b c d 5 8 88 5 8 81 DROP TABLE t1,t2; +# +# Bug mdev-4336: LEFT JOIN with disjunctive +# <non-nullable datetime field> IS NULL in WHERE +# causes a hang and eventual crash +# +CREATE TABLE t1 ( +id int(11) NOT NULL, +modified datetime NOT NULL, +PRIMARY KEY (id) +); +SELECT a.* FROM t1 a LEFT JOIN t1 b ON a.id = b.id +WHERE a.modified > b.modified or b.modified IS NULL; +id modified +DROP TABLE t1; SET optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/r/join_outer_jcl6.result b/mysql-test/r/join_outer_jcl6.result index 554e0027a9e..d063720836d 100644 --- a/mysql-test/r/join_outer_jcl6.result +++ b/mysql-test/r/join_outer_jcl6.result @@ -1833,6 +1833,20 @@ b c d 5 8 88 5 8 81 DROP TABLE t1,t2; +# +# Bug mdev-4336: LEFT JOIN with disjunctive +# <non-nullable datetime field> IS NULL in WHERE +# causes a hang and eventual crash +# +CREATE TABLE t1 ( +id int(11) NOT NULL, +modified datetime NOT NULL, +PRIMARY KEY (id) +); +SELECT a.* FROM t1 a LEFT JOIN t1 b ON a.id = b.id +WHERE a.modified > b.modified or b.modified IS NULL; +id modified +DROP TABLE t1; SET optimizer_switch=@save_optimizer_switch; set join_cache_level=default; show variables like 'join_cache_level'; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 69c08cd54bd..8c0ee82e1fa 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -1359,4 +1359,21 @@ ORDER BY t1.b; DROP TABLE t1,t2; +--echo # +--echo # Bug mdev-4336: LEFT JOIN with disjunctive +--echo # <non-nullable datetime field> IS NULL in WHERE +--echo # causes a hang and eventual crash +--echo # + +CREATE TABLE t1 ( + id int(11) NOT NULL, + modified datetime NOT NULL, + PRIMARY KEY (id) +); + +SELECT a.* FROM t1 a LEFT JOIN t1 b ON a.id = b.id + WHERE a.modified > b.modified or b.modified IS NULL; + +DROP TABLE t1; + SET optimizer_switch=@save_optimizer_switch; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b5f76608672..3ccebf688e2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13197,7 +13197,8 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) else { Item *list_item; - Item *new_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++)) { @@ -13211,7 +13212,9 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) it.replace(new_list_item); new_list_item->update_used_tables(); } - li.replace(*new_item_and_list); + li.replace(*new_item_and_list); + for (cnt--; cnt; cnt--) + item= li++; } cond_and_list->concat((List<Item>*) cond_equal_items); } @@ -13232,7 +13235,13 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) if (new_item->type() == Item::COND_ITEM && ((Item_cond*) new_item)->functype() == ((Item_cond*) cond)->functype()) - li.replace(*((Item_cond*) new_item)->argument_list()); + { + 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); } |