summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2022-07-21 15:20:53 -0700
committerIgor Babaev <igor@askmonty.org>2022-07-26 18:03:34 -0700
commitbd935a41060199a17019453d6e187e8edd7929ba (patch)
treedea103f55d67e2649293a6137367b6cb83888dc4
parente8eb6d9c936bab05b6058a329f9770840e6e3cff (diff)
downloadmariadb-git-bd935a41060199a17019453d6e187e8edd7929ba.tar.gz
MDEV-29139 Crash when using ANY predicand with redundant subquery in GROUP BY clause
This bug could cause a crash of the server when executing queries containing ANY/ALL predicands with redundant subqueries in GROUP BY clauses. These subqueries are eliminated by remove_redundant_subquery_clause() together with elimination of GROUP BY list containing these subqueries. However the references to the elements of the GROUP BY remained in the JOIN::all_fields list of the right operand of of the ALL/ANY predicand. Later these references confused make_aggr_tables_info() when forming proper execution structures after ALL/ANY predicands had been replaced with expressions containing MIN/MAX set functions. The patch just removes these references from JOIN::all_fields list used by the subquery of the ALL/ANY predicand when its GROUP BY clause is eliminated. Approved by Oleksandr Byelkin <sanja@mariadb.com>
-rw-r--r--mysql-test/main/subselect4.result57
-rw-r--r--mysql-test/main/subselect4.test39
-rw-r--r--sql/sql_select.cc15
3 files changed, 111 insertions, 0 deletions
diff --git a/mysql-test/main/subselect4.result b/mysql-test/main/subselect4.result
index ba5a6bb1ba8..c374040e9e8 100644
--- a/mysql-test/main/subselect4.result
+++ b/mysql-test/main/subselect4.result
@@ -2981,4 +2981,61 @@ ANALYZE
}
DROP TABLE t1;
# End of 10.2 tests
+#
+# MDEV-29139: Redundannt subquery in GROUP BY clause of ANY/ALL subquery
+#
+create table t1 (a int);
+insert into t1 values (3), (1), (2);
+create table t2 (b int not null);
+insert into t2 values (4), (2);
+create table t3 (c int);
+insert into t3 values (7), (1);
+explain extended select a from t1
+where a >= any (select b from t2 group by (select c from t3 where c = 1));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <nop>(<in_optimizer>(`test`.`t1`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t1`.`a`)))
+select a from t1
+where a >= any (select b from t2 group by (select c from t3 where c = 1));
+a
+3
+2
+prepare stmt from "select a from t1
+where a >= any (select b from t2 group by (select c from t3 where c = 1))";
+execute stmt;
+a
+3
+2
+execute stmt;
+a
+3
+2
+deallocate prepare stmt;
+explain extended select a from t1
+where a <= all (select b from t2 group by (select c from t3 where c = 1));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <not>(<in_optimizer>(`test`.`t1`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) < <cache>(`test`.`t1`.`a`)))
+select a from t1
+where a <= all (select b from t2 group by (select c from t3 where c = 1));
+a
+1
+2
+explain extended select a from t1
+where a >= any (select b from t2 group by 1 + (select c from t3 where c = 1));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where <nop>(<in_optimizer>(`test`.`t1`.`a`,(/* select#2 */ select min(`test`.`t2`.`b`) from `test`.`t2`) <= <cache>(`test`.`t1`.`a`)))
+select a from t1
+where a >= any (select b from t2 group by 1 + (select c from t3 where c = 1));
+a
+3
+2
+drop table t1,t2,t3;
# End of 10.3 tests
diff --git a/mysql-test/main/subselect4.test b/mysql-test/main/subselect4.test
index aeef8849fc5..2faede5c27e 100644
--- a/mysql-test/main/subselect4.test
+++ b/mysql-test/main/subselect4.test
@@ -2438,4 +2438,43 @@ DROP TABLE t1;
--echo # End of 10.2 tests
+
+--echo #
+--echo # MDEV-29139: Redundannt subquery in GROUP BY clause of ANY/ALL subquery
+--echo #
+
+create table t1 (a int);
+insert into t1 values (3), (1), (2);
+create table t2 (b int not null);
+insert into t2 values (4), (2);
+create table t3 (c int);
+insert into t3 values (7), (1);
+
+let $q1=
+select a from t1
+ where a >= any (select b from t2 group by (select c from t3 where c = 1));
+
+eval explain extended $q1;
+eval $q1;
+
+eval prepare stmt from "$q1";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
+let $q2=
+select a from t1
+ where a <= all (select b from t2 group by (select c from t3 where c = 1));
+
+eval explain extended $q2;
+eval $q2;
+
+let $q3=
+select a from t1
+ where a >= any (select b from t2 group by 1 + (select c from t3 where c = 1));
+eval explain extended $q3;
+eval $q3;
+
+drop table t1,t2,t3;
+
--echo # End of 10.3 tests
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0803e785302..33fb19966b2 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -605,7 +605,22 @@ void remove_redundant_subquery_clauses(st_select_lex *subq_select_lex)
Here SUBQ cannot be removed.
*/
if (!ord->in_field_list)
+ {
(*ord->item)->walk(&Item::eliminate_subselect_processor, FALSE, NULL);
+ /*
+ Remove from the JOIN::all_fields list any reference to the elements
+ of the eliminated GROUP BY list unless it is 'in_field_list'.
+ This is needed in order not to confuse JOIN::make_aggr_tables_info()
+ when it constructs different structure for execution phase.
+ */
+ List_iterator<Item> li(subq_select_lex->join->all_fields);
+ Item *item;
+ while ((item= li++))
+ {
+ if (item == *ord->item)
+ li.remove();
+ }
+ }
}
subq_select_lex->join->group_list= NULL;
subq_select_lex->group_list.empty();