diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result index 79d380a04db..453f1319ccb 100644 --- a/mysql-test/r/cte_nonrecursive.result +++ b/mysql-test/r/cte_nonrecursive.result @@ -86,7 +86,7 @@ select * from t2,t where t2.c=t.a; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where 1 PRIMARY ref key0 key0 5 test.t2.c 2 -2 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort explain select * from t2, (select a, count(*) from t1 where b >= 'c' group by a) as t where t2.c=t.a; @@ -176,7 +176,7 @@ select * from t2 where c in (select c from t); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where 1 PRIMARY ref key0 key0 8 test.t2.c 2 Using where; FirstMatch(t2) -2 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort explain select * from t2 where c in (select c from (select count(*) as c from t1 @@ -245,8 +245,8 @@ select * from t as r1, t as r2 where r1.a=r2.a; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 8 Using where 1 PRIMARY ref key0 key0 5 r1.a 2 -3 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary -2 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary +3 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary explain select * from (select distinct a from t1 where b >= 'c') as r1, (select distinct a from t1 where b >= 'c') as r2 @@ -370,7 +370,7 @@ select * from t2,t where t2.c=t.a; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where 1 PRIMARY ref key0 key0 5 test.t2.c 2 -2 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where +2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where 3 UNION t2 ALL NULL NULL NULL NULL 4 Using where NULL UNION RESULT ALL NULL NULL NULL NULL NULL explain @@ -598,7 +598,7 @@ select * from v2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where 1 PRIMARY ref key0 key0 5 test.t2.c 2 -3 SUBQUERY t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort +3 DERIVED t1 ALL NULL NULL NULL NULL 8 Using where; Using temporary; Using filesort # with clause in the specification of a view that whose definition # table alias for a with table create view v3 as @@ -1055,3 +1055,27 @@ deallocate prepare stmt1; deallocate prepare stmt2; drop view v1,v2; drop table t1,t2; +# +# MDEV-13796: UNION of two materialized CTEs +# +CREATE TABLE t1 (id int, k int); +CREATE TABLE t2 (id int); +INSERT INTO t1 VALUES (3,5), (1,7), (4,3); +INSERT INTO t2 VALUES (4), (3), (2); +WITH d1 AS (SELECT SUM(k) FROM t1, t2 as t2 WHERE t1.id = t2.id), +d2 AS (SELECT SUM(k) FROM t1, t2 as t2 WHERE t1.id = t2.id) +SELECT * FROM d1 UNION SELECT * FROM d2; +SUM(k) +8 +explain WITH d1 AS (SELECT SUM(k) FROM t1, t2 as t2 WHERE t1.id = t2.id), +d2 AS (SELECT SUM(k) FROM t1, t2 as t2 WHERE t1.id = t2.id) +SELECT * FROM d1 UNION SELECT * FROM d2; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 9 +2 DERIVED t1 ALL NULL NULL NULL NULL 3 +2 DERIVED t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +4 UNION ALL NULL NULL NULL NULL 9 +3 DERIVED t1 ALL NULL NULL NULL NULL 3 +3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +DROP TABLE t1,t2; diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index 42ba01e42de..057e3fe034c 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -86,7 +86,7 @@ select t2.a from t1,t2 where t1.a+1=t2.a select * from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 30 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where +2 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where 3 UNION t1 ALL NULL NULL NULL NULL 5 3 UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL @@ -114,7 +114,7 @@ select t2.a from t1,t2 where t1.a+1=t2.a select * from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 5 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where +2 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where 3 RECURSIVE UNION ALL NULL NULL NULL NULL 5 3 RECURSIVE UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL @@ -691,13 +691,13 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 2 100.00 Using where 1 PRIMARY ref key0 key0 5 c.h_id 2 100.00 1 PRIMARY ref key0 key0 5 c.w_id 2 100.00 -3 SUBQUERY folks ALL NULL NULL NULL NULL 12 100.00 Using where +3 DERIVED folks ALL NULL NULL NULL NULL 12 100.00 Using where 4 RECURSIVE UNION ALL NULL NULL NULL NULL 2 100.00 4 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join) 5 RECURSIVE UNION ALL NULL NULL NULL NULL 2 100.00 5 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL -2 UNCACHEABLE SUBQUERY ALL NULL NULL NULL NULL 12 100.00 Using where +2 DERIVED ALL NULL NULL NULL NULL 12 100.00 Using where Warnings: Note 1003 with recursive ancestor_couple_ids as (select `a`.`father` AS `h_id`,`a`.`mother` AS `w_id` from `coupled_ancestors` `a` where `a`.`father` is not null and `a`.`mother` is not null), coupled_ancestors as (select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' union all select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `fa` where `test`.`p`.`id` = `fa`.`h_id` union all select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `ma` where `test`.`p`.`id` = `ma`.`w_id`)select `h`.`name` AS `name`,`h`.`dob` AS `dob`,`w`.`name` AS `name`,`w`.`dob` AS `dob` from `ancestor_couple_ids` `c` join `coupled_ancestors` `h` join `coupled_ancestors` `w` where `h`.`id` = `c`.`h_id` and `w`.`id` = `c`.`w_id` # simple mutual recursion @@ -877,7 +877,7 @@ where p.id = a.father or p.id = a.mother select * from ancestors; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 12 100.00 -2 SUBQUERY folks ALL NULL NULL NULL NULL 12 100.00 Using where +2 DERIVED folks ALL NULL NULL NULL NULL 12 100.00 Using where 3 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 3 RECURSIVE UNION ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL @@ -1236,7 +1236,7 @@ where p.id = ma.mother select * from ancestors; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 12 -2 SUBQUERY folks ALL NULL NULL NULL NULL 12 Using where +2 DERIVED folks ALL NULL NULL NULL NULL 12 Using where 3 RECURSIVE UNION p ALL PRIMARY NULL NULL NULL 12 3 RECURSIVE UNION ref key0 key0 5 test.p.id 2 4 RECURSIVE UNION p ALL PRIMARY NULL NULL NULL 12 @@ -1300,14 +1300,14 @@ from prev_gen select ancestors.name, ancestors.dob from ancestors; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 24 -4 SUBQUERY folks ALL NULL NULL NULL NULL 12 Using where +4 DERIVED folks ALL NULL NULL NULL NULL 12 Using where 6 RECURSIVE UNION ALL NULL NULL NULL NULL 12 -5 RECURSIVE UNION ALL NULL NULL NULL NULL 24 -NULL UNION RESULT ALL NULL NULL NULL NULL NULL -3 SUBQUERY folks ALL NULL NULL NULL NULL 12 Using where +3 DERIVED folks ALL NULL NULL NULL NULL 12 Using where 2 RECURSIVE UNION folks ALL PRIMARY NULL NULL NULL 12 2 RECURSIVE UNION ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL +5 RECURSIVE UNION ALL NULL NULL NULL NULL 24 +NULL UNION RESULT ALL NULL NULL NULL NULL NULL explain FORMAT=JSON with recursive prev_gen @@ -1831,7 +1831,7 @@ select t2.a from t1,t2 where t1.a+1=t2.a select * from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 5 -2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where +2 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where 4 RECURSIVE UNION ALL NULL NULL NULL NULL 5 4 RECURSIVE UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL @@ -2783,7 +2783,7 @@ SELECT c1 FROM t, cte ) SELECT COUNT(*) FROM cte; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 -2 SUBQUERY t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 +2 DERIVED t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 3 RECURSIVE UNION t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 3 RECURSIVE UNION ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL 0.00 NULL NULL @@ -2801,7 +2801,7 @@ SELECT c2 FROM t, cte ) SELECT COUNT(*) FROM cte; id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 -2 SUBQUERY t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 +2 DERIVED t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 3 RECURSIVE UNION t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 3 RECURSIVE UNION ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 Using join buffer (flat, BNL join) NULL UNION RESULT ALL NULL NULL NULL NULL NULL 0.00 NULL NULL diff --git a/mysql-test/t/cte_nonrecursive.test b/mysql-test/t/cte_nonrecursive.test index 980bff01694..57b7ae1658f 100644 --- a/mysql-test/t/cte_nonrecursive.test +++ b/mysql-test/t/cte_nonrecursive.test @@ -724,3 +724,22 @@ deallocate prepare stmt2; drop view v1,v2; drop table t1,t2; + +--echo # +--echo # MDEV-13796: UNION of two materialized CTEs +--echo # + +CREATE TABLE t1 (id int, k int); +CREATE TABLE t2 (id int); +INSERT INTO t1 VALUES (3,5), (1,7), (4,3); +INSERT INTO t2 VALUES (4), (3), (2); + +let $q= +WITH d1 AS (SELECT SUM(k) FROM t1, t2 as t2 WHERE t1.id = t2.id), + d2 AS (SELECT SUM(k) FROM t1, t2 as t2 WHERE t1.id = t2.id) +SELECT * FROM d1 UNION SELECT * FROM d2; + +eval $q; +eval explain $q; + +DROP TABLE t1,t2; diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 1b14c5b68b7..e1af30123f6 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -991,7 +991,7 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) been done yet. */ if (with_elem && sl->master_unit() == with_elem->spec) - break; + break; With_clause *with_clause=sl->get_with_clause(); if (with_clause) { @@ -1039,13 +1039,21 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem) } with= with_elem; if (!with_elem->is_referenced() || with_elem->is_recursive) + { derived= with_elem->spec; + if (derived->get_master() != select_lex && + !is_with_table_recursive_reference()) + { + derived->move_as_slave(select_lex); + } + } else { if(!(derived= with_elem->clone_parsed_spec(thd, this))) return true; derived->with_element= with_elem; } + derived->first_select()->linkage= DERIVED_TABLE_TYPE; with_elem->inc_references(); return false; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 7879edc3f67..c8474c66ca1 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2304,6 +2304,30 @@ st_select_lex_node *st_select_lex_node:: insert_chain_before( return this; } + +/* + Detach the node from its master and attach it to a new master +*/ + +void st_select_lex_node::move_as_slave(st_select_lex_node *new_master) +{ + exclude_from_tree(); + if (new_master->slave) + { + st_select_lex_node *curr= new_master->slave; + for ( ; curr->next ; curr= curr->next) ; + prev= &curr->next; + } + else + { + prev= &new_master->slave; + new_master->slave= this; + } + next= 0; + master= new_master; +} + + /* Exclude a node from the tree lex structure, but leave it in the global list of nodes. @@ -4404,7 +4428,8 @@ void st_select_lex::set_explain_type(bool on_the_fly) pos_in_table_list=NULL for e.g. post-join aggregation JOIN_TABs. */ if (tab->table && tab->table->pos_in_table_list && - tab->table->pos_in_table_list->with) + tab->table->pos_in_table_list->with && + tab->table->pos_in_table_list->with->is_recursive) { uses_cte= true; break; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a1ef42861b4..9ab09c9fe7e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -561,6 +561,7 @@ public: } st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert, st_select_lex_node *end_chain_node); + void move_as_slave(st_select_lex_node *new_master); friend class st_select_lex_unit; friend bool mysql_new_select(LEX *lex, bool move_down); friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,