summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2013-05-03 22:46:45 -0700
committerIgor Babaev <igor@askmonty.org>2013-05-03 22:46:45 -0700
commit920c479c6ebd2236dbe5510e5ed8b748bf0ee158 (patch)
treeb5895605eba5f91e3cf0cce0b870076e6571f98c
parentb249680fd11f5c9102f7a22cf638f3872d5c2e61 (diff)
downloadmariadb-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.result14
-rw-r--r--mysql-test/r/join_outer_jcl6.result14
-rw-r--r--mysql-test/t/join_outer.test17
-rw-r--r--sql/sql_select.cc15
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);
}