revision-id: 1d25639bf9a58cbf0a8427e3edd9781536602679 (mariadb-10.2.14-94-g1d25639) parent(s): fb5d5794623af1e6bff2ba7f6c7142770fa5e9d9 author: Igor Babaev committer: Igor Babaev timestamp: 2018-05-17 15:47:17 -0700 message: MDEV-16212 Memory leak with recursive CTE that uses global ORDER BY with recursive subquery There were two problems: 1. The code did not report that usage of global ORDER BY / LIMIT clauses was not supported yet. 2. The code just reset fake_select_lex of the the unit specifying a recursive CTE to NULL and that caused memory leaks in some cases. --- mysql-test/r/cte_recursive.result | 10 ++++++++++ mysql-test/t/cte_recursive.test | 12 ++++++++++++ sql/sql_union.cc | 13 ++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index d6dfdf1..b7516b8 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -3233,3 +3233,13 @@ Parent Child Path 654 987 987, 321 654 987,654, DROP TABLE t1; +# +# MDEV-16212: recursive CTE with global ORDER BY +# +set statement max_recursive_iterations = 2 for +WITH RECURSIVE qn AS ( +SELECT 1 FROM dual UNION ALL +SELECT 1 FROM qn +ORDER BY (SELECT * FROM qn)) +SELECT count(*) FROM qn; +ERROR 42000: This version of MariaDB doesn't yet support 'global ORDER_BY/LIMIT in recursive CTE spec' diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index 3a8795e..b327647 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -2246,3 +2246,15 @@ FROM cte ORDER BY Path; DROP TABLE t1; + +--echo # +--echo # MDEV-16212: recursive CTE with global ORDER BY +--echo # + +--error ER_NOT_SUPPORTED_YET +set statement max_recursive_iterations = 2 for +WITH RECURSIVE qn AS ( +SELECT 1 FROM dual UNION ALL +SELECT 1 FROM qn +ORDER BY (SELECT * FROM qn)) +SELECT count(*) FROM qn; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 3fe8a24..35c31fe 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -521,7 +521,18 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, with_element->rec_result= new (thd_arg->mem_root) select_union_recursive(thd_arg); union_result= with_element->rec_result; - fake_select_lex= NULL; + if (fake_select_lex) + { + if (fake_select_lex->order_list.first || + fake_select_lex->explicit_limit) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), + "global ORDER_BY/LIMIT in recursive CTE spec"); + goto err; + } + fake_select_lex->cleanup(); + fake_select_lex= NULL; + } } if (!(tmp_result= union_result)) goto err; /* purecov: inspected */