create table t1 (a int, b varchar(32)); insert into t1 values (4,'aaaa' ), (7,'bb'), (1,'ccc'), (4,'dd'); insert into t1 values (3,'eee'), (7,'bb'), (1,'fff'), (4,'ggg'); with recursive t as ( select * from t1 where t1.b >= 'c' union select * from r ), r as ( select * from t union select t1.* from t1,r where r.a+1 = t1.a ) select * from r; ERROR HY000: Unacceptable mutual recursion with anchored table 't' with recursive a1(a,b) as (select * from t1 where t1.a>3 union select * from b1 where b1.a >3 union select * from c1 where c1.a>3), b1(a,b) as (select * from a1 where a1.b > 'ccc' union select * from c1 where c1.b > 'ddd'), c1(a,b) as (select * from a1 where a1.a<6 and a1.b< 'zz' union select * from b1 where b1.b > 'auu') select * from c1; ERROR HY000: Unacceptable mutual recursion with anchored table 'a1' drop table t1; # WITH RECURSIVE vs just WITH create table t1 (a int); insert into t1 values (0), (1), (2), (3), (4); create table t2 (a int); insert into t2 values (1), (2), (3), (4), (5); # just WITH : s refers to t defined after s with s(a) as (select t.a + 10 from t), t(a) as (select t1.a from t1) select * from s; ERROR 42S02: Table 'test.t' doesn't exist # WITH RECURSIVE: s refers to t defined after s with recursive s(a) as (select t.a + 10 from t), t(a) as (select t1.a from t1) select * from s; a 10 11 12 13 14 # just WITH : defined t1 is non-recursive and uses base tables t1,t2 with t1 as ( select a from t2 where t2.a=3 union select t2.a from t1,t2 where t1.a+1=t2.a ) select * from t1; a 3 1 2 4 5 explain with t1 as ( select a from t2 where t2.a=3 union 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 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 #WITH RECURSIVE : defined t1 is recursive and uses only base table t2 with recursive t1 as ( select a from t2 where t2.a=3 union select t2.a from t1,t2 where t1.a+1=t2.a ) select * from t1; a 3 4 5 explain with recursive t1 as ( select a from t2 where t2.a=3 union 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 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 # just WITH : types of t1 columns are determined by all parts of union create view v1 as with t1 as ( select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a ) select * from t1; show columns from v1; Field Type Null Key Default Extra a bigint(20) YES NULL # WITH RECURSIVE : types of t1 columns are determined by anchor parts create view v2 as with recursive t1 as ( select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a ) select * from t1; show columns from v2; Field Type Null Key Default Extra a int(11) YES NULL drop view v1,v2; drop table t1,t2; create table folks(id int, name char(32), dob date, father int, mother int); insert into folks values (100, 'Me', '2000-01-01', 20, 30), (20, 'Dad', '1970-02-02', 10, 9), (30, 'Mom', '1975-03-03', 8, 7), (10, 'Grandpa Bill', '1940-04-05', null, null), (9, 'Grandma Ann', '1941-10-15', null, null), (25, 'Uncle Jim', '1968-11-18', 8, 7), (98, 'Sister Amy', '2001-06-20', 20, 30), (7, 'Grandma Sally', '1943-08-23', null, 6), (8, 'Grandpa Ben', '1940-10-21', null, null), (6, 'Grandgrandma Martha', '1923-05-17', null, null), (67, 'Cousin Eddie', '1992-02-28', 25, 27), (27, 'Auntie Melinda', '1971-03-29', null, null); # simple recursion with one anchor and one recursive select # the anchor is the first select in the specification with recursive ancestors as ( select * from folks where name = 'Me' and dob = '2000-01-01' union select p.id, p.name, p.dob, p.father, p.mother from folks as p, ancestors AS a where p.id = a.father or p.id = a.mother ) select * from ancestors; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL # simple recursion with one anchor and one recursive select # the anchor is the last select in the specification with recursive ancestors as ( select p.* from folks as p, ancestors AS a where p.id = a.father or p.id = a.mother union select * from folks where name = 'Me' and dob = '2000-01-01' ) select * from ancestors; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL # simple recursion with one anchor and one recursive select # the anchor is the first select in the specification with recursive ancestors as ( select * from folks where name = 'Cousin Eddie' union select p.* from folks as p, ancestors as a where p.id = a.father or p.id = a.mother ) select * from ancestors; id name dob father mother 67 Cousin Eddie 1992-02-28 25 27 25 Uncle Jim 1968-11-18 8 7 27 Auntie Melinda 1971-03-29 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL # simple recursion with or in anchor and or in recursive part with recursive ancestors as ( select * from folks where name = 'Me' or name='Sister Amy' union select p.* from folks as p, ancestors as a where p.id = a.father or p.id = a.mother ) select * from ancestors; id name dob father mother 100 Me 2000-01-01 20 30 98 Sister Amy 2001-06-20 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL # two recursive definition, one uses another with recursive prev_gen as ( select folks.* from folks, prev_gen where folks.id=prev_gen.father or folks.id=prev_gen.mother union select * from folks where name='Me' ), ancestors as ( select * from folks where name='Me' union select * from ancestors union select * from prev_gen ) select ancestors.name, ancestors.dob from ancestors; name dob Me 2000-01-01 Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandma Sally 1943-08-23 Grandpa Ben 1940-10-21 Grandgrandma Martha 1923-05-17 # recursive definition with two attached non-recursive with recursive ancestors(id,name,dob) as ( with father(child_id,id,name,dob) as ( select folks.id, f.id, f.name, f.dob from folks, folks f where folks.father=f.id ), mother(child_id,id,name,dob) as ( select folks.id, m.id, m.name, m.dob from folks, folks m where folks.mother=m.id ) select folks.id, folks.name, folks.dob from folks where name='Me' union select f.id, f.name, f.dob from ancestors a, father f where f.child_id=a.id union select m.id, m.name, m.dob from ancestors a, mother m where m.child_id=a.id ) select ancestors.name, ancestors.dob from ancestors; name dob Me 2000-01-01 Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandpa Ben 1940-10-21 Grandma Ann 1941-10-15 Grandma Sally 1943-08-23 Grandgrandma Martha 1923-05-17 # simple recursion with one anchor and one recursive select # the anchor is the first select in the specification with recursive descendants as ( select * from folks where name = 'Grandpa Bill' union select folks.* from folks, descendants as d where d.id=folks.father or d.id=folks.mother ) select * from descendants; id name dob father mother 10 Grandpa Bill 1940-04-05 NULL NULL 20 Dad 1970-02-02 10 9 100 Me 2000-01-01 20 30 98 Sister Amy 2001-06-20 20 30 # simple recursion with one anchor and one recursive select # the anchor is the first select in the specification with recursive descendants as ( select * from folks where name = 'Grandma Sally' union select folks.* from folks, descendants as d where d.id=folks.father or d.id=folks.mother ) select * from descendants; id name dob father mother 7 Grandma Sally 1943-08-23 NULL 6 30 Mom 1975-03-03 8 7 25 Uncle Jim 1968-11-18 8 7 100 Me 2000-01-01 20 30 98 Sister Amy 2001-06-20 20 30 67 Cousin Eddie 1992-02-28 25 27 # simple recursive table used three times in the main query with recursive ancestors as ( select * from folks where name = 'Me' and dob = '2000-01-01' union select p.* from folks as p, ancestors AS a where p.id = a.father OR p.id = a.mother ) select * from ancestors t1, ancestors t2 where exists (select * from ancestors a where a.father=t1.id AND a.mother=t2.id); id name dob father mother id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 8 Grandpa Ben 1940-10-21 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 # simple recursive table used three times in the main query with ancestor_couples(husband, h_dob, wife, w_dob) as ( with recursive ancestors as ( select * from folks where name = 'Me' union select p.* from folks as p, ancestors AS a where p.id = a.father OR p.id = a.mother ) select t1.name, t1.dob, t2.name, t2.dob from ancestors t1, ancestors t2 where exists (select * from ancestors a where a.father=t1.id AND a.mother=t2.id) ) select * from ancestor_couples; husband h_dob wife w_dob Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23 # simple recursion with two selects in recursive part with recursive ancestors as ( select * from folks where name = 'Me' union select p.* from folks as p, ancestors as fa where p.id = fa.father union select p.* from folks as p, ancestors as ma where p.id = ma.mother ) select * from ancestors; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 8 Grandpa Ben 1940-10-21 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 6 Grandgrandma Martha 1923-05-17 NULL NULL # mutual recursion with renaming with recursive ancestor_couples(h_id, h_name, h_dob, h_father, h_mother, w_id, w_name, w_dob, w_father, w_mother) as ( select h.*, w.* from folks h, folks w, coupled_ancestors a where a.father = h.id AND a.mother = w.id union select h.*, w.* from folks v, folks h, folks w where v.name = 'Me' and (v.father = h.id AND v.mother= w.id) ), coupled_ancestors (id, name, dob, father, mother) as ( select h_id, h_name, h_dob, h_father, h_mother from ancestor_couples union select w_id, w_name, w_dob, w_father, w_mother from ancestor_couples ) select h_name, h_dob, w_name, w_dob from ancestor_couples; h_name h_dob w_name w_dob Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23 # mutual recursion with union all with recursive ancestor_couples(h_id, h_name, h_dob, h_father, h_mother, w_id, w_name, w_dob, w_father, w_mother) as ( select h.*, w.* from folks h, folks w, coupled_ancestors a where a.father = h.id AND a.mother = w.id union select h.*, w.* from folks v, folks h, folks w where v.name = 'Me' and (v.father = h.id AND v.mother= w.id) ), coupled_ancestors (id, name, dob, father, mother) as ( select h_id, h_name, h_dob, h_father, h_mother from ancestor_couples union all select w_id, w_name, w_dob, w_father, w_mother from ancestor_couples ) select h_name, h_dob, w_name, w_dob from ancestor_couples; h_name h_dob w_name w_dob Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23 # mutual recursion with renaming with recursive ancestor_couples(h_id, h_name, h_dob, h_father, h_mother, w_id, w_name, w_dob, w_father, w_mother) as ( select h.*, w.* from folks h, folks w, coupled_ancestors a where a.father = h.id AND a.mother = w.id union select h.*, w.* from folks v, folks h, folks w where v.name = 'Me' and (v.father = h.id AND v.mother= w.id) ), coupled_ancestors (id, name, dob, father, mother) as ( select h_id, h_name, h_dob, h_father, h_mother from ancestor_couples union select w_id, w_name, w_dob, w_father, w_mother from ancestor_couples ) select h_name, h_dob, w_name, w_dob from ancestor_couples; h_name h_dob w_name w_dob Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23 # mutual recursion with union all with recursive ancestor_couples(h_id, h_name, h_dob, h_father, h_mother, w_id, w_name, w_dob, w_father, w_mother) as ( select h.*, w.* from folks h, folks w, coupled_ancestors a where a.father = h.id AND a.mother = w.id ), coupled_ancestors (id, name, dob, father, mother) as ( select * from folks where name = 'Me' union all select h_id, h_name, h_dob, h_father, h_mother from ancestor_couples union all select w_id, w_name, w_dob, w_father, w_mother from ancestor_couples ) select h_name, h_dob, w_name, w_dob from ancestor_couples; h_name h_dob w_name w_dob Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23 # mutual recursion with one select in the first definition with recursive ancestor_couple_ids(h_id, w_id) as ( select a.father, a.mother from coupled_ancestors a where a.father is not null and a.mother is not null ), coupled_ancestors (id, name, dob, father, mother) as ( select * from folks where name = 'Me' union all select p.* from folks p, ancestor_couple_ids fa where p.id = fa.h_id union all select p.* from folks p, ancestor_couple_ids ma where p.id = ma.w_id ) select * from ancestor_couple_ids; h_id w_id 20 30 10 9 8 7 # join of a mutually recursive table with base tables with recursive ancestor_couple_ids(h_id, w_id) as ( select a.father, a.mother from coupled_ancestors a where a.father is not null and a.mother is not null ), coupled_ancestors (id, name, dob, father, mother) as ( select * from folks where name = 'Me' union all select p.* from folks p, ancestor_couple_ids fa where p.id = fa.h_id union all select p.* from folks p, ancestor_couple_ids ma where p.id = ma.w_id ) select h.name, h.dob, w.name, w.dob from ancestor_couple_ids c, folks h, folks w where c.h_id = h.id and c.w_id= w.id; name dob name dob Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23 # join of two mutually recursive tables with recursive ancestor_couple_ids(h_id, w_id) as ( select a.father, a.mother from coupled_ancestors a where a.father is not null and a.mother is not null ), coupled_ancestors (id, name, dob, father, mother) as ( select * from folks where name = 'Me' union all select p.* from folks p, ancestor_couple_ids fa where p.id = fa.h_id union all select p.* from folks p, ancestor_couple_ids ma where p.id = ma.w_id ) select h.name, h.dob, w.name, w.dob from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w where c.h_id = h.id and c.w_id= w.id; name dob name dob Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23 explain extended with recursive ancestor_couple_ids(h_id, w_id) as ( select a.father, a.mother from coupled_ancestors a where a.father is not null and a.mother is not null ), coupled_ancestors (id, name, dob, father, mother) as ( select * from folks where name = 'Me' union all select p.* from folks p, ancestor_couple_ids fa where p.id = fa.h_id union all select p.* from folks p, ancestor_couple_ids ma where p.id = ma.w_id ) select h.name, h.dob, w.name, w.dob from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w where c.h_id = h.id and c.w_id= w.id; 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 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 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 with recursive ancestor_couple_ids(h_id, w_id) as ( select a.father, a.mother from coupled_ancestors a ), coupled_ancestors (id, name, dob, father, mother) as ( select * from folks where name = 'Me' union all select p.* from folks p, ancestor_couple_ids fa where p.id = fa.h_id union all select p.* from folks p, ancestor_couple_ids ma where p.id = ma.w_id ) select * from ancestor_couple_ids; h_id w_id 20 30 10 9 8 7 NULL NULL NULL NULL NULL NULL NULL 6 NULL NULL # join of two mutually recursive tables with recursive ancestor_couple_ids(h_id, w_id) as ( select a.father, a.mother from coupled_ancestors a ), coupled_ancestors (id, name, dob, father, mother) as ( select * from folks where name = 'Me' union all select p.* from folks p, ancestor_couple_ids fa where p.id = fa.h_id union all select p.* from folks p, ancestor_couple_ids ma where p.id = ma.w_id ) select h.name, h.dob, w.name, w.dob from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w where c.h_id = h.id and c.w_id= w.id; name dob name dob Dad 1970-02-02 Mom 1975-03-03 Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15 Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23 # execution of prepared query using a recursive table prepare stmt1 from " with recursive ancestors as ( select * from folks where name = 'Me' and dob = '2000-01-01' union select p.id, p.name, p.dob, p.father, p.mother from folks as p, ancestors AS a where p.id = a.father or p.id = a.mother ) select * from ancestors; "; execute stmt1; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL execute stmt1; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL deallocate prepare stmt1; # view using a recursive table create view v1 as with recursive ancestors as ( select * from folks where name = 'Me' and dob = '2000-01-01' union select p.id, p.name, p.dob, p.father, p.mother from folks as p, ancestors AS a where p.id = a.father or p.id = a.mother ) select * from ancestors; show create view v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with recursive ancestors as (select `folks`.`id` AS `id`,`folks`.`name` AS `name`,`folks`.`dob` AS `dob`,`folks`.`father` AS `father`,`folks`.`mother` AS `mother` from `folks` where `folks`.`name` = 'Me' and `folks`.`dob` = '2000-01-01' union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `a`) where `p`.`id` = `a`.`father` or `p`.`id` = `a`.`mother`)select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors` latin1 latin1_swedish_ci select * from v1; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL create view v2 as with recursive ancestors as ( select * from folks where name = 'Me' union select p.* from folks as p, ancestors as fa where p.id = fa.father union select p.* from folks as p, ancestors as ma where p.id = ma.mother ) select * from ancestors; show create view v2; View Create View character_set_client collation_connection v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS with recursive ancestors as (select `folks`.`id` AS `id`,`folks`.`name` AS `name`,`folks`.`dob` AS `dob`,`folks`.`father` AS `father`,`folks`.`mother` AS `mother` from `folks` where `folks`.`name` = 'Me' union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `fa`) where `p`.`id` = `fa`.`father` union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `ma`) where `p`.`id` = `ma`.`mother`)select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors` latin1 latin1_swedish_ci select * from v2; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 8 Grandpa Ben 1940-10-21 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 6 Grandgrandma Martha 1923-05-17 NULL NULL drop view v1,v2; explain extended with recursive ancestors as ( select * from folks where name = 'Me' and dob = '2000-01-01' union select p.id, p.name, p.dob, p.father, p.mother from folks as p, ancestors AS a 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 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 Warnings: Note 1003 with recursive 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' and `test`.`folks`.`dob` = DATE'2000-01-01' union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestors` `a` where `a`.`father` = `p`.`id` or `a`.`mother` = `p`.`id`)select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors` # recursive spec with two anchor selects and two recursive ones with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks, ancestor_ids a where folks.id = a.id union select mother from folks, ancestor_ids a where folks.id = a.id ), ancestors as ( select p.* from folks as p, ancestor_ids as a where p.id = a.id ) select * from ancestors; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL # recursive spec using union all with recursive ancestors as ( select * from folks where name = 'Me' union all select p.* from folks as p, ancestors as fa where p.id = fa.father union all select p.* from folks as p, ancestors as ma where p.id = ma.mother ) select * from ancestors; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 8 Grandpa Ben 1940-10-21 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 6 Grandgrandma Martha 1923-05-17 NULL NULL with recursive ancestor_ids (id, generation) as ( select father, 1 from folks where name = 'Me' and father is not null union all select mother, 1 from folks where name = 'Me' and mother is not null union all select father, fa.generation+1 from folks, ancestor_ids fa where folks.id = fa.id and (father not in (select id from ancestor_ids)) union all select mother, ma.generation+1 from folks, ancestor_ids ma where folks.id = ma.id and (mother not in (select id from ancestor_ids)) ) select generation, name from ancestor_ids a, folks where a.id = folks.id; ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids' set standard_compliant_cte=0; with recursive ancestor_ids (id, generation) as ( select father from folks where name = 'Me' and father is not null union all select mother from folks where name = 'Me' and mother is not null union all select father, fa.generation+1 from folks, ancestor_ids fa where folks.id = fa.id and (father not in (select id from ancestor_ids)) union all select mother, ma.generation+1 from folks, ancestor_ids ma where folks.id = ma.id and (mother not in (select id from ancestor_ids)) ) select generation, name from ancestor_ids a, folks where a.id = folks.id; ERROR HY000: WITH column list and SELECT field list have different column counts with recursive ancestor_ids (id, generation) as ( select father, 1 from folks where name = 'Me' and father is not null union all select mother, 1 from folks where name = 'Me' and mother is not null union all select father, fa.generation+1 from folks, ancestor_ids fa where folks.id = fa.id and father is not null and (father not in (select id from ancestor_ids)) union all select mother, ma.generation+1 from folks, ancestor_ids ma where folks.id = ma.id and mother is not null and (mother not in (select id from ancestor_ids)) ) select generation, name from ancestor_ids a, folks where a.id = folks.id; generation name 1 Dad 1 Mom 2 Grandpa Bill 2 Grandma Ann 2 Grandma Sally 2 Grandpa Ben 3 Grandgrandma Martha set standard_compliant_cte=1; with recursive coupled_ancestor_ids (id) as ( select father from folks where name = 'Me' and father is not null union select mother from folks where name = 'Me' and mother is not null union select n.father from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n where folks.father = fa.id and folks.mother = ma.id and (fa.id = n.id or ma.id = n.id) and n.father is not null and n.mother is not null union select n.mother from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n where folks.father = fa.id and folks.mother = ma.id and (fa.id = n.id or ma.id = n.id) and n.father is not null and n.mother is not null ) select p.* from coupled_ancestor_ids a, folks p where a.id = p.id; ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'coupled_ancestor_ids' set statement standard_compliant_cte=0 for with recursive coupled_ancestor_ids (id) as ( select father from folks where name = 'Me' and father is not null union select mother from folks where name = 'Me' and mother is not null union select n.father from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n where folks.father = fa.id and folks.mother = ma.id and (fa.id = n.id or ma.id = n.id) and n.father is not null and n.mother is not null union select n.mother from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n where folks.father = fa.id and folks.mother = ma.id and (fa.id = n.id or ma.id = n.id) and n.father is not null and n.mother is not null ) select p.* from coupled_ancestor_ids a, folks p where a.id = p.id; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks left join ancestor_ids a on folks.id = a.id union select mother from folks left join ancestor_ids a on folks.id = a.id ), ancestors as ( select p.* from folks as p, ancestor_ids as a where p.id = a.id ) select * from ancestors; ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids' set statement standard_compliant_cte=0 for with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks left join ancestor_ids a on folks.id = a.id union select mother from folks left join ancestor_ids a on folks.id = a.id ), ancestors as ( select p.* from folks as p, ancestor_ids as a where p.id = a.id ) select * from ancestors; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 25 Uncle Jim 1968-11-18 8 7 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL 27 Auntie Melinda 1971-03-29 NULL NULL with recursive ancestor_ids (id, generation) as ( select father, 1 from folks where name = 'Me' union select mother, 1 from folks where name = 'Me' union select father, a.generation+1 from folks, ancestor_ids a where folks.id = a.id union select mother, a.generation+1 from folks, ancestor_ids a where folks.id = a.id ), ancestors as ( select generation, name from folks as p, ancestor_ids as a where p.id = a.id ) select * from ancestors; generation name 1 Dad 1 Mom 2 Grandpa Bill 2 Grandma Ann 2 Grandma Sally 2 Grandpa Ben 3 Grandgrandma Martha with recursive ancestor_ids (id, generation) as ( select father, 1 from folks where name = 'Me' union select mother, 1 from folks where name = 'Me' union select max(father), max(a.generation)+1 from folks, ancestor_ids a where folks.id = a.id group by a.generation union select max(mother), max(a.generation)+1 from folks, ancestor_ids a where folks.id = a.id group by a.generation ), ancestors as ( select generation, name from folks as p, ancestor_ids as a where p.id = a.id ) select * from ancestors; ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids' set statement standard_compliant_cte=0 for with recursive ancestor_ids (id, generation) as ( select father, 1 from folks where name = 'Me' union select mother, 1 from folks where name = 'Me' union select max(father), a.generation+1 from folks, ancestor_ids a where folks.id = a.id group by a.generation union select max(mother), a.generation+1 from folks, ancestor_ids a where folks.id = a.id group by a.generation ), ancestors as ( select generation, name from folks as p, ancestor_ids as a where p.id = a.id ) select * from ancestors; generation name 1 Dad 1 Mom 2 Grandpa Bill 2 Grandma Ann set statement max_recursive_iterations=1 for with recursive ancestor_ids (id, generation) as ( select father, 1 from folks where name = 'Me' union select mother, 1 from folks where name = 'Me' union select father, a.generation+1 from folks, ancestor_ids a where folks.id = a.id union select mother, a.generation+1 from folks, ancestor_ids a where folks.id = a.id ), ancestors as ( select generation, name from folks as p, ancestor_ids as a where p.id = a.id ) select * from ancestors; generation name 1 Dad 1 Mom 2 Grandpa Bill 2 Grandma Ann 2 Grandma Sally 2 Grandpa Ben # query with recursive tables using key access alter table folks add primary key (id); explain with recursive ancestors as ( select * from folks where name = 'Me' union select p.* from folks as p, ancestors as fa where p.id = fa.father union select p.* from folks as p, ancestors as ma 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 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 4 RECURSIVE UNION ref key0 key0 5 test.p.id 2 NULL UNION RESULT ALL NULL NULL NULL NULL NULL with recursive ancestors as ( select * from folks where name = 'Me' union select p.* from folks as p, ancestors as fa where p.id = fa.father union select p.* from folks as p, ancestors as ma where p.id = ma.mother ) select * from ancestors; id name dob father mother 100 Me 2000-01-01 20 30 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 8 Grandpa Ben 1940-10-21 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 6 Grandgrandma Martha 1923-05-17 NULL NULL # # EXPLAIN FORMAT=JSON on a query where one recursive CTE uses another: # explain with recursive prev_gen as ( select folks.* from folks, prev_gen where folks.id=prev_gen.father or folks.id=prev_gen.mother union select * from folks where name='Me' ), ancestors as ( select * from folks where name='Me' union select * from ancestors union select * 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 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 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 explain FORMAT=JSON with recursive prev_gen as ( select folks.* from folks, prev_gen where folks.id=prev_gen.father or folks.id=prev_gen.mother union select * from folks where name='Me' ), ancestors as ( select * from folks where name='Me2' union select * from ancestors where id < 234 union select * from prev_gen where id < 345 ) select ancestors.name, ancestors.dob from ancestors; EXPLAIN { "query_block": { "select_id": 1, "table": { "table_name": "", "access_type": "ALL", "rows": 24, "filtered": 100, "materialized": { "query_block": { "recursive_union": { "table_name": "", "access_type": "ALL", "query_specifications": [ { "query_block": { "select_id": 4, "table": { "table_name": "folks", "access_type": "ALL", "rows": 12, "filtered": 100, "attached_condition": "folks.`name` = 'Me2'" } } }, { "query_block": { "select_id": 6, "table": { "table_name": "", "access_type": "ALL", "rows": 12, "filtered": 100, "attached_condition": "prev_gen.`id` < 345", "materialized": { "query_block": { "recursive_union": { "table_name": "", "access_type": "ALL", "query_specifications": [ { "query_block": { "select_id": 3, "table": { "table_name": "folks", "access_type": "ALL", "rows": 12, "filtered": 100, "attached_condition": "folks.`name` = 'Me'" } } }, { "query_block": { "select_id": 2, "table": { "table_name": "folks", "access_type": "ALL", "possible_keys": ["PRIMARY"], "rows": 12, "filtered": 100 }, "block-nl-join": { "table": { "table_name": "", "access_type": "ALL", "rows": 12, "filtered": 100 }, "buffer_type": "flat", "buffer_size": "256Kb", "join_type": "BNL", "attached_condition": "prev_gen.father = folks.`id` or prev_gen.mother = folks.`id`" } } } ] } } } } } }, { "query_block": { "select_id": 5, "table": { "table_name": "", "access_type": "ALL", "rows": 24, "filtered": 100, "attached_condition": "ancestors.`id` < 234" } } } ] } } } } } } # explain format=json with recursive ancestor_couples(h_id, h_name, h_dob, h_father, h_mother, w_id, w_name, w_dob, w_father, w_mother) as ( select h.*, w.* from folks h, folks w, coupled_ancestors a where a.father = h.id AND a.mother = w.id union select h.*, w.* from folks v, folks h, folks w where v.name = 'Me' and (v.father = h.id AND v.mother= w.id) ), coupled_ancestors (id, name, dob, father, mother) as ( select h_id, h_name, h_dob, h_father, h_mother from ancestor_couples union all select w_id, w_name, w_dob, w_father, w_mother from ancestor_couples ) select h_name, h_dob, w_name, w_dob from ancestor_couples; EXPLAIN { "query_block": { "select_id": 1, "table": { "table_name": "", "access_type": "ALL", "rows": 12, "filtered": 100, "materialized": { "query_block": { "recursive_union": { "table_name": "", "access_type": "ALL", "query_specifications": [ { "query_block": { "select_id": 3, "table": { "table_name": "v", "access_type": "ALL", "rows": 12, "filtered": 100, "attached_condition": "v.`name` = 'Me' and v.father is not null and v.mother is not null" }, "table": { "table_name": "h", "access_type": "eq_ref", "possible_keys": ["PRIMARY"], "key": "PRIMARY", "key_length": "4", "used_key_parts": ["id"], "ref": ["test.v.father"], "rows": 1, "filtered": 100 }, "table": { "table_name": "w", "access_type": "eq_ref", "possible_keys": ["PRIMARY"], "key": "PRIMARY", "key_length": "4", "used_key_parts": ["id"], "ref": ["test.v.mother"], "rows": 1, "filtered": 100 } } }, { "query_block": { "select_id": 2, "table": { "table_name": "", "access_type": "ALL", "rows": 2, "filtered": 100, "attached_condition": "a.father is not null and a.mother is not null" }, "table": { "table_name": "h", "access_type": "eq_ref", "possible_keys": ["PRIMARY"], "key": "PRIMARY", "key_length": "4", "used_key_parts": ["id"], "ref": ["a.father"], "rows": 1, "filtered": 100 }, "table": { "table_name": "w", "access_type": "eq_ref", "possible_keys": ["PRIMARY"], "key": "PRIMARY", "key_length": "4", "used_key_parts": ["id"], "ref": ["a.mother"], "rows": 1, "filtered": 100 } } } ] } } } } } } create table my_ancestors with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks, ancestor_ids a where folks.id = a.id union select mother from folks, ancestor_ids a where folks.id = a.id ) select p.* from folks as p, ancestor_ids as a where p.id = a.id; select * from my_ancestors; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL delete from my_ancestors; insert into my_ancestors with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks, ancestor_ids a where folks.id = a.id union select mother from folks, ancestor_ids a where folks.id = a.id ) select p.* from folks as p, ancestor_ids as a where p.id = a.id; select * from my_ancestors; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL drop table my_ancestors; # # MDEV-10883: execution of prepared statement from SELECT # with recursive CTE that renames columns # prepare stmt from" with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks, ancestor_ids a where folks.id = a.id union select mother from folks, ancestor_ids a where folks.id = a.id ) select p.* from folks as p, ancestor_ids as a where p.id = a.id; "; execute stmt; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL deallocate prepare stmt; # # MDEV-10881: execution of prepared statement from # CREATE ... SELECT, INSERT ... SELECT # prepare stmt from" create table my_ancestors with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks, ancestor_ids a where folks.id = a.id union select mother from folks, ancestor_ids a where folks.id = a.id ) select p.* from folks as p, ancestor_ids as a where p.id = a.id; "; execute stmt; deallocate prepare stmt; select * from my_ancestors; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL delete from my_ancestors; prepare stmt from" insert into my_ancestors with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks, ancestor_ids a where folks.id = a.id union select mother from folks, ancestor_ids a where folks.id = a.id ) select p.* from folks as p, ancestor_ids as a where p.id = a.id; "; execute stmt; deallocate prepare stmt; select * from my_ancestors; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL drop table my_ancestors; # # MDEV-10933: WITH clause together with SELECT in parenthesis # CREATE SELECT # create table my_ancestors ( with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from folks, ancestor_ids a where folks.id = a.id union select mother from folks, ancestor_ids a where folks.id = a.id ) select p.* from folks as p, ancestor_ids as a where p.id = a.id ); select * from my_ancestors; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL drop table my_ancestors; drop table folks; # # MDEV-10372: [bb-10.2-mdev9864 tree] EXPLAIN with recursive CTE enters endless recursion # create table t1(a int); insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); explain format=json with recursive t as (select a from t1 union select a+10 from t where a < 1000) select * from t; EXPLAIN { "query_block": { "select_id": 1, "table": { "table_name": "", "access_type": "ALL", "rows": 10, "filtered": 100, "materialized": { "query_block": { "recursive_union": { "table_name": "", "access_type": "ALL", "query_specifications": [ { "query_block": { "select_id": 2, "table": { "table_name": "t1", "access_type": "ALL", "rows": 10, "filtered": 100 } } }, { "query_block": { "select_id": 3, "table": { "table_name": "", "access_type": "ALL", "rows": 10, "filtered": 100, "attached_condition": "t.a < 1000" } } } ] } } } } } } drop table t1; # # MDEV-10737: recursive union with several anchors at the end # WITH RECURSIVE cte(n) AS ( SELECT n+1 FROM cte WHERE n < 5 UNION SELECT 1 UNION SELECT 1 ) SELECT * FROM cte; n 1 2 3 4 5 # # MDEV-10736: recursive definition with anchor over a table with blob # CREATE TABLE t1 (f VARCHAR(1024)); WITH RECURSIVE cte(f) AS (SELECT t1.f FROM t1 UNION ALL SELECT cte.f FROM cte) SELECT * FROM cte as t; f DROP TABLE t1; # # MDEV-10899: mergeable derived in the spec of recursive CTE # create table t1 (a int); insert into t1 values (0), (1), (2), (3), (4); create table t2 (a int); insert into t2 values (1), (2), (3), (4), (5); with recursive t1 as ( select x.a from (select a from t2 where t2.a=3) x union select t2.a from t1,t2 where t1.a+1=t2.a ) select * from t1; a 3 4 5 explain with recursive t1 as ( select x.a from (select a from t2 where t2.a=3) x union 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 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 drop table t1,t2; # # MDEV-11278: non-mergeable view in the spec of recursive CTE # create table t1 (a int); insert into t1 values (0), (1), (2), (3), (4); create table t2 (a int); insert into t2 values (1), (2), (3), (4), (5); create view v1 as select a from t2 where a < 3 union select a from t2 where a > 4; with recursive t1 as ( select a from v1 where a=1 union select v1.a from t1,v1 where t1.a+1=v1.a ) select * from t1; a 1 2 drop view v1; drop table t1,t2; # # MDEV-11259: recursive CTE with concatenation operation # DROP TABLE IF EXISTS edges; Warnings: Note 1051 Unknown table 'test.edges' CREATE TABLE edges( a int(10) unsigned NOT NULL, b int(10) unsigned NOT NULL, PRIMARY KEY (a,b), KEY b(b) ); INSERT INTO edges VALUES (1,3),(2,1),(2,4),(3,4),(3,5),(3,6),(4,7),(5,1),(5,6),(6,1); DROP TABLE IF EXISTS edges2; Warnings: Note 1051 Unknown table 'test.edges2' CREATE VIEW edges2 (a, b) AS SELECT a, b FROM edges UNION ALL SELECT b, a FROM edges; WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS ( SELECT a, b, 1 AS distance, concat(a, '.', b, '.') AS path_string FROM edges UNION ALL SELECT tc.a, e.b, tc.distance + 1, concat(tc.path_string, e.b, '.') AS path_string FROM edges AS e JOIN transitive_closure AS tc ON e.a = tc.b WHERE tc.path_string NOT LIKE concat('%', e.b, '.%') ) SELECT * FROM transitive_closure ORDER BY a, b, distance; a b distance path_string 1 3 1 1.3. 1 4 2 1.3.4. 1 5 2 1.3.5. 1 6 2 1.3.6. 1 6 3 1.3.5.6. 1 7 3 1.3.4.7. 2 1 1 2.1. 2 3 2 2.1.3. 2 4 1 2.4. 2 4 3 2.1.3.4. 2 5 3 2.1.3.5. 2 6 3 2.1.3.6. 2 6 4 2.1.3.5.6. 2 7 2 2.4.7. 2 7 4 2.1.3.4.7. 3 1 2 3.5.1. 3 1 2 3.6.1. 3 1 3 3.5.6.1. 3 4 1 3.4. 3 5 1 3.5. 3 6 1 3.6. 3 6 2 3.5.6. 3 7 2 3.4.7. 4 7 1 4.7. 5 1 1 5.1. 5 1 2 5.6.1. 5 3 2 5.1.3. 5 3 3 5.6.1.3. 5 4 3 5.1.3.4. 5 4 4 5.6.1.3.4. 5 6 1 5.6. 5 6 3 5.1.3.6. 5 7 4 5.1.3.4.7. 5 7 5 5.6.1.3.4.7. 6 1 1 6.1. 6 3 2 6.1.3. 6 4 3 6.1.3.4. 6 5 3 6.1.3.5. 6 7 4 6.1.3.4.7. WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS ( SELECT a, b, 1 AS distance, concat(a, '.', b, '.') AS path_string FROM edges WHERE a = 1 -- source UNION ALL SELECT tc.a, e.b, tc.distance + 1, concat(tc.path_string, e.b, '.') AS path_string FROM edges AS e JOIN transitive_closure AS tc ON e.a = tc.b WHERE tc.path_string NOT LIKE concat('%', e.b, '.%') ) SELECT * FROM transitive_closure WHERE b = 6 -- destination ORDER BY a, b, distance; a b distance path_string 1 6 2 1.3.6. 1 6 3 1.3.5.6. WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS ( SELECT a, b, 1 AS distance, concat(a, '.', b, '.') AS path_string FROM edges2 UNION ALL SELECT tc.a, e.b, tc.distance + 1, concat(tc.path_string, e.b, '.') AS path_string FROM edges2 AS e JOIN transitive_closure AS tc ON e.a = tc.b WHERE tc.path_string NOT LIKE concat('%', e.b, '.%') ) SELECT * FROM transitive_closure ORDER BY a, b, distance; a b distance path_string 1 2 1 1.2. 1 2 3 1.3.4.2. 1 2 4 1.5.3.4.2. 1 2 4 1.6.3.4.2. 1 2 5 1.5.6.3.4.2. 1 2 5 1.6.5.3.4.2. 1 3 1 1.3. 1 3 2 1.5.3. 1 3 2 1.6.3. 1 3 3 1.2.4.3. 1 3 3 1.5.6.3. 1 3 3 1.6.5.3. 1 4 2 1.2.4. 1 4 2 1.3.4. 1 4 3 1.5.3.4. 1 4 3 1.6.3.4. 1 4 4 1.5.6.3.4. 1 4 4 1.6.5.3.4. 1 5 1 1.5. 1 5 2 1.3.5. 1 5 2 1.6.5. 1 5 3 1.3.6.5. 1 5 3 1.6.3.5. 1 5 4 1.2.4.3.5. 1 5 5 1.2.4.3.6.5. 1 6 1 1.6. 1 6 2 1.3.6. 1 6 2 1.5.6. 1 6 3 1.3.5.6. 1 6 3 1.5.3.6. 1 6 4 1.2.4.3.6. 1 6 5 1.2.4.3.5.6. 1 7 3 1.2.4.7. 1 7 3 1.3.4.7. 1 7 4 1.5.3.4.7. 1 7 4 1.6.3.4.7. 1 7 5 1.5.6.3.4.7. 1 7 5 1.6.5.3.4.7. 2 1 1 2.1. 2 1 3 2.4.3.1. 2 1 4 2.4.3.5.1. 2 1 4 2.4.3.6.1. 2 1 5 2.4.3.5.6.1. 2 1 5 2.4.3.6.5.1. 2 3 2 2.1.3. 2 3 2 2.4.3. 2 3 3 2.1.5.3. 2 3 3 2.1.6.3. 2 3 4 2.1.5.6.3. 2 3 4 2.1.6.5.3. 2 4 1 2.4. 2 4 3 2.1.3.4. 2 4 4 2.1.5.3.4. 2 4 4 2.1.6.3.4. 2 4 5 2.1.5.6.3.4. 2 4 5 2.1.6.5.3.4. 2 5 2 2.1.5. 2 5 3 2.1.3.5. 2 5 3 2.1.6.5. 2 5 3 2.4.3.5. 2 5 4 2.1.3.6.5. 2 5 4 2.1.6.3.5. 2 5 4 2.4.3.1.5. 2 5 4 2.4.3.6.5. 2 5 5 2.4.3.1.6.5. 2 5 5 2.4.3.6.1.5. 2 6 2 2.1.6. 2 6 3 2.1.3.6. 2 6 3 2.1.5.6. 2 6 3 2.4.3.6. 2 6 4 2.1.3.5.6. 2 6 4 2.1.5.3.6. 2 6 4 2.4.3.1.6. 2 6 4 2.4.3.5.6. 2 6 5 2.4.3.1.5.6. 2 6 5 2.4.3.5.1.6. 2 7 2 2.4.7. 2 7 4 2.1.3.4.7. 2 7 5 2.1.5.3.4.7. 2 7 5 2.1.6.3.4.7. 2 7 6 2.1.5.6.3.4.7. 2 7 6 2.1.6.5.3.4.7. 3 1 1 3.1. 3 1 2 3.5.1. 3 1 2 3.6.1. 3 1 3 3.4.2.1. 3 1 3 3.5.6.1. 3 1 3 3.6.5.1. 3 2 2 3.1.2. 3 2 2 3.4.2. 3 2 3 3.5.1.2. 3 2 3 3.6.1.2. 3 2 4 3.5.6.1.2. 3 2 4 3.6.5.1.2. 3 4 1 3.4. 3 4 3 3.1.2.4. 3 4 4 3.5.1.2.4. 3 4 4 3.6.1.2.4. 3 4 5 3.5.6.1.2.4. 3 4 5 3.6.5.1.2.4. 3 5 1 3.5. 3 5 2 3.1.5. 3 5 2 3.6.5. 3 5 3 3.1.6.5. 3 5 3 3.6.1.5. 3 5 4 3.4.2.1.5. 3 5 5 3.4.2.1.6.5. 3 6 1 3.6. 3 6 2 3.1.6. 3 6 2 3.5.6. 3 6 3 3.1.5.6. 3 6 3 3.5.1.6. 3 6 4 3.4.2.1.6. 3 6 5 3.4.2.1.5.6. 3 7 2 3.4.7. 3 7 4 3.1.2.4.7. 3 7 5 3.5.1.2.4.7. 3 7 5 3.6.1.2.4.7. 3 7 6 3.5.6.1.2.4.7. 3 7 6 3.6.5.1.2.4.7. 4 1 2 4.2.1. 4 1 2 4.3.1. 4 1 3 4.3.5.1. 4 1 3 4.3.6.1. 4 1 4 4.3.5.6.1. 4 1 4 4.3.6.5.1. 4 2 1 4.2. 4 2 3 4.3.1.2. 4 2 4 4.3.5.1.2. 4 2 4 4.3.6.1.2. 4 2 5 4.3.5.6.1.2. 4 2 5 4.3.6.5.1.2. 4 3 1 4.3. 4 3 3 4.2.1.3. 4 3 4 4.2.1.5.3. 4 3 4 4.2.1.6.3. 4 3 5 4.2.1.5.6.3. 4 3 5 4.2.1.6.5.3. 4 5 2 4.3.5. 4 5 3 4.2.1.5. 4 5 3 4.3.1.5. 4 5 3 4.3.6.5. 4 5 4 4.2.1.3.5. 4 5 4 4.2.1.6.5. 4 5 4 4.3.1.6.5. 4 5 4 4.3.6.1.5. 4 5 5 4.2.1.3.6.5. 4 5 5 4.2.1.6.3.5. 4 6 2 4.3.6. 4 6 3 4.2.1.6. 4 6 3 4.3.1.6. 4 6 3 4.3.5.6. 4 6 4 4.2.1.3.6. 4 6 4 4.2.1.5.6. 4 6 4 4.3.1.5.6. 4 6 4 4.3.5.1.6. 4 6 5 4.2.1.3.5.6. 4 6 5 4.2.1.5.3.6. 4 7 1 4.7. 5 1 1 5.1. 5 1 2 5.3.1. 5 1 2 5.6.1. 5 1 3 5.3.6.1. 5 1 3 5.6.3.1. 5 1 4 5.3.4.2.1. 5 1 5 5.6.3.4.2.1. 5 2 2 5.1.2. 5 2 3 5.3.1.2. 5 2 3 5.3.4.2. 5 2 3 5.6.1.2. 5 2 4 5.1.3.4.2. 5 2 4 5.3.6.1.2. 5 2 4 5.6.3.1.2. 5 2 4 5.6.3.4.2. 5 2 5 5.1.6.3.4.2. 5 2 5 5.6.1.3.4.2. 5 3 1 5.3. 5 3 2 5.1.3. 5 3 2 5.6.3. 5 3 3 5.1.6.3. 5 3 3 5.6.1.3. 5 3 4 5.1.2.4.3. 5 3 5 5.6.1.2.4.3. 5 4 2 5.3.4. 5 4 3 5.1.2.4. 5 4 3 5.1.3.4. 5 4 3 5.6.3.4. 5 4 4 5.1.6.3.4. 5 4 4 5.3.1.2.4. 5 4 4 5.6.1.2.4. 5 4 4 5.6.1.3.4. 5 4 5 5.3.6.1.2.4. 5 4 5 5.6.3.1.2.4. 5 6 1 5.6. 5 6 2 5.1.6. 5 6 2 5.3.6. 5 6 3 5.1.3.6. 5 6 3 5.3.1.6. 5 6 5 5.1.2.4.3.6. 5 6 5 5.3.4.2.1.6. 5 7 3 5.3.4.7. 5 7 4 5.1.2.4.7. 5 7 4 5.1.3.4.7. 5 7 4 5.6.3.4.7. 5 7 5 5.1.6.3.4.7. 5 7 5 5.3.1.2.4.7. 5 7 5 5.6.1.2.4.7. 5 7 5 5.6.1.3.4.7. 5 7 6 5.3.6.1.2.4.7. 5 7 6 5.6.3.1.2.4.7. 6 1 1 6.1. 6 1 2 6.3.1. 6 1 2 6.5.1. 6 1 3 6.3.5.1. 6 1 3 6.5.3.1. 6 1 4 6.3.4.2.1. 6 1 5 6.5.3.4.2.1. 6 2 2 6.1.2. 6 2 3 6.3.1.2. 6 2 3 6.3.4.2. 6 2 3 6.5.1.2. 6 2 4 6.1.3.4.2. 6 2 4 6.3.5.1.2. 6 2 4 6.5.3.1.2. 6 2 4 6.5.3.4.2. 6 2 5 6.1.5.3.4.2. 6 2 5 6.5.1.3.4.2. 6 3 1 6.3. 6 3 2 6.1.3. 6 3 2 6.5.3. 6 3 3 6.1.5.3. 6 3 3 6.5.1.3. 6 3 4 6.1.2.4.3. 6 3 5 6.5.1.2.4.3. 6 4 2 6.3.4. 6 4 3 6.1.2.4. 6 4 3 6.1.3.4. 6 4 3 6.5.3.4. 6 4 4 6.1.5.3.4. 6 4 4 6.3.1.2.4. 6 4 4 6.5.1.2.4. 6 4 4 6.5.1.3.4. 6 4 5 6.3.5.1.2.4. 6 4 5 6.5.3.1.2.4. 6 5 1 6.5. 6 5 2 6.1.5. 6 5 2 6.3.5. 6 5 3 6.1.3.5. 6 5 3 6.3.1.5. 6 5 5 6.1.2.4.3.5. 6 5 5 6.3.4.2.1.5. 6 7 3 6.3.4.7. 6 7 4 6.1.2.4.7. 6 7 4 6.1.3.4.7. 6 7 4 6.5.3.4.7. 6 7 5 6.1.5.3.4.7. 6 7 5 6.3.1.2.4.7. 6 7 5 6.5.1.2.4.7. 6 7 5 6.5.1.3.4.7. 6 7 6 6.3.5.1.2.4.7. 6 7 6 6.5.3.1.2.4.7. 7 1 3 7.4.2.1. 7 1 3 7.4.3.1. 7 1 4 7.4.3.5.1. 7 1 4 7.4.3.6.1. 7 1 5 7.4.3.5.6.1. 7 1 5 7.4.3.6.5.1. 7 2 2 7.4.2. 7 2 4 7.4.3.1.2. 7 2 5 7.4.3.5.1.2. 7 2 5 7.4.3.6.1.2. 7 2 6 7.4.3.5.6.1.2. 7 2 6 7.4.3.6.5.1.2. 7 3 2 7.4.3. 7 3 4 7.4.2.1.3. 7 3 5 7.4.2.1.5.3. 7 3 5 7.4.2.1.6.3. 7 3 6 7.4.2.1.5.6.3. 7 3 6 7.4.2.1.6.5.3. 7 4 1 7.4. 7 5 3 7.4.3.5. 7 5 4 7.4.2.1.5. 7 5 4 7.4.3.1.5. 7 5 4 7.4.3.6.5. 7 5 5 7.4.2.1.3.5. 7 5 5 7.4.2.1.6.5. 7 5 5 7.4.3.1.6.5. 7 5 5 7.4.3.6.1.5. 7 5 6 7.4.2.1.3.6.5. 7 5 6 7.4.2.1.6.3.5. 7 6 3 7.4.3.6. 7 6 4 7.4.2.1.6. 7 6 4 7.4.3.1.6. 7 6 4 7.4.3.5.6. 7 6 5 7.4.2.1.3.6. 7 6 5 7.4.2.1.5.6. 7 6 5 7.4.3.1.5.6. 7 6 5 7.4.3.5.1.6. 7 6 6 7.4.2.1.3.5.6. 7 6 6 7.4.2.1.5.3.6. WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS ( SELECT a, b, 1 AS distance, concat(a, '.', b, '.') AS path_string FROM edges2 UNION ALL SELECT tc.a, e.b, tc.distance + 1, concat(tc.path_string, e.b, '.') AS path_string FROM edges2 AS e JOIN transitive_closure AS tc ON e.a = tc.b WHERE tc.path_string NOT LIKE concat('%', e.b, '.%') ) SELECT a, b, min(distance) AS dist FROM transitive_closure GROUP BY a, b ORDER BY a, dist, b; a b dist 1 2 1 1 3 1 1 4 2 1 5 1 1 6 1 1 7 3 2 1 1 2 3 2 2 4 1 2 5 2 2 6 2 2 7 2 3 1 1 3 2 2 3 4 1 3 5 1 3 6 1 3 7 2 4 1 2 4 2 1 4 3 1 4 5 2 4 6 2 4 7 1 5 1 1 5 2 2 5 3 1 5 4 2 5 6 1 5 7 3 6 1 1 6 2 2 6 3 1 6 4 2 6 5 1 6 7 3 7 1 3 7 2 2 7 3 2 7 4 1 7 5 3 7 6 3 DROP VIEW edges2; DROP TABLE edges; # # MDEV-11674: recursive CTE table that cannot be stored # in a heap table # create table t1 (id int, test_data varchar(36)); insert into t1(id, test_data) select id, test_data from ( with recursive data_generator(id, test_data) as ( select 1 as id, uuid() as test_data union all select id + 1, uuid() from data_generator where id < 150000 ) select * from data_generator ) as a; drop table t1; # # MDEV-10773: ANALYZE for query with recursive CTE # analyze format=json with recursive src(counter) as (select 1 union select counter+1 from src where counter<10 ) select * from src; ANALYZE { "query_block": { "select_id": 1, "r_loops": 1, "r_total_time_ms": "REPLACED", "table": { "table_name": "", "access_type": "ALL", "r_loops": 1, "rows": 2, "r_rows": 10, "r_total_time_ms": "REPLACED", "filtered": 100, "r_filtered": 100, "materialized": { "query_block": { "recursive_union": { "table_name": "", "access_type": "ALL", "r_loops": 0, "r_rows": null, "query_specifications": [ { "query_block": { "select_id": 2, "table": { "message": "No tables used" } } }, { "query_block": { "select_id": 3, "r_loops": 10, "r_total_time_ms": "REPLACED", "table": { "table_name": "", "access_type": "ALL", "r_loops": 10, "rows": 2, "r_rows": 1, "r_total_time_ms": "REPLACED", "filtered": 100, "r_filtered": 90, "attached_condition": "src.counter < 10" } } } ] } } } } } } # # mdev-12360: recursive reference in left operand of LEFT JOIN # create table folks(id int, name char(32), dob date, father int, mother int); insert into folks values (100, 'Me', '2000-01-01', 20, 30), (20, 'Dad', '1970-02-02', 10, 9), (30, 'Mom', '1975-03-03', 8, 7), (10, 'Grandpa Bill', '1940-04-05', null, null), (9, 'Grandma Ann', '1941-10-15', null, null), (25, 'Uncle Jim', '1968-11-18', 8, 7), (98, 'Sister Amy', '2001-06-20', 20, 30), (7, 'Grandma Sally', '1943-08-23', null, 6), (8, 'Grandpa Ben', '1940-10-21', null, null), (6, 'Grandgrandma Martha', '1923-05-17', null, null), (67, 'Cousin Eddie', '1992-02-28', 25, 27), (27, 'Auntie Melinda', '1971-03-29', null, null); with recursive ancestor_ids (id) as ( select father from folks where name = 'Me' union select mother from folks where name = 'Me' union select father from ancestor_ids as a left join folks on folks.id = a.id union select mother from ancestor_ids as a left join folks on folks.id = a.id ), ancestors as ( select p.* from folks as p, ancestor_ids as a where p.id = a.id ) select * from ancestors; id name dob father mother 20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7 10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6 8 Grandpa Ben 1940-10-21 NULL NULL 6 Grandgrandma Martha 1923-05-17 NULL NULL drop table folks; # # mdev-12368: crash with mutually recursive CTE # that arenot Standard compliant # create table value_nodes (v char(4)); create table module_nodes(m char(4)); create table module_arguments(m char(4), v char(4)); create table module_results(m char(4), v char(4)); with recursive reached_values as ( select v from value_nodes where v in ('v3','v7','v9') union select module_results.v from module_results, applied_modules where module_results.m = applied_modules.m ), applied_modules as ( select module_nodes.m from module_nodes left join ( module_arguments left join reached_values on module_arguments.v = reached_values.v ) on reached_values.v is null and module_nodes.m = module_arguments.m where module_arguments.m is null ) select * from reached_values; ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'applied_modules' drop table value_nodes, module_nodes, module_arguments, module_results; # # mdev-12375: query using one of two mutually recursive CTEs # whose non-recursive part returns an empty set # create table value_nodes (v char(4)); insert into value_nodes values ('v1'), ('v2'), ('v3'), ('v4'), ('v5'), ('v6'), ('v7'), ('v8'), ('v9'), ('v10'), ('v11'), ('v12'), ('v13'), ('v14'), ('v15'), ('v16'); create table module_nodes(m char(4)); insert into module_nodes values ('m1'), ('m2'), ('m3'), ('m4'), ('m5'), ('m6'), ('m7'); create table module_arguments(m char(4), v char(4)); insert into module_arguments values ('m1','v3'), ('m1','v9'), ('m2','v4'), ('m2','v3'), ('m2','v7'), ('m3','v6'), ('m4','v4'), ('m4','v1'), ('m5','v10'), ('m5','v8'), ('m5','v3'), ('m6','v8'), ('m6','v1'), ('m7','v11'), ('m7','v12'); create table module_results(m char(4), v char(4)); insert into module_results values ('m1','v4'), ('m2','v1'), ('m2','v6'), ('m3','v10'), ('m4','v8'), ('m5','v11'), ('m5','v9'), ('m6','v12'), ('m6','v4'), ('m7','v2'); set statement max_recursive_iterations=2, standard_compliant_cte=0 for with recursive reached_values as ( select v from value_nodes where v in ('v3','v7','v9') union select module_results.v from module_results, applied_modules where module_results.m = applied_modules.m ), applied_modules as ( select * from module_nodes where 1=0 union select module_nodes.m from module_nodes left join ( module_arguments left join reached_values on module_arguments.v = reached_values.v ) on reached_values.v is null and module_nodes.m = module_arguments.m where module_arguments.m is null ) select * from applied_modules; m m1 m2 drop table value_nodes, module_nodes, module_arguments, module_results; # # mdev-12519: recursive references in subqueries # create table t1 (lp char(4) not null, rp char(4) not null); insert into t1 values ('p1','p2'), ('p2','p3'), ('p3','p4'), ('p4','p5'), ('p2','p7'), ('p7','p8'), ('p8','p3'), ('p8','p4'); set standard_compliant_cte=0; with recursive reachables(p) as ( select lp from t1 where lp = 'p1' union select t1.rp from reachables, t1 where t1.lp = reachables.p ) select * from reachables; p p1 p2 p3 p7 p4 p8 p5 with recursive reachables(p) as ( select lp from t1 where lp = 'p1' union select t1.rp from reachables, t1 where 'p3' not in (select * from reachables) and t1.lp = reachables.p ) select * from reachables; p p1 p2 p3 p7 with recursive reachables(p) as ( select lp from t1 where lp = 'p1' union select t1.rp from reachables, t1 where 'p3' not in (select p from reachables where p <= 'p5' union select p from reachables where p > 'p5') and t1.lp = reachables.p ) select * from reachables; p p1 p2 p3 p7 prepare stmt from " with recursive reachables(p) as ( select lp from t1 where lp = 'p1' union select t1.rp from reachables, t1 where 'p3' not in (select p from reachables where p <= 'p5' union select p from reachables where p > 'p5') and t1.lp = reachables.p ) select * from reachables; "; execute stmt; p p1 p2 p3 p7 execute stmt; p p1 p2 p3 p7 deallocate prepare stmt; drop table t1; create table objects(v char(4) not null); insert into objects values ('v1'), ('v2'), ('v3'), ('v4'), ('v5'), ('v6'), ('v7'), ('v8'), ('v9'), ('v10'); create table modules(m char(4) not null); insert into modules values ('m1'), ('m2'), ('m3'), ('m4'); create table module_arguments(m char(4) not null, v char(4) not null); insert into module_arguments values ('m1','v3'), ('m1','v9'), ('m2','v4'), ('m2','v7'), ('m3','v6'), ('m4','v2'); create table module_results(m char(4) not null, v char(4) not null); insert into module_results values ('m1','v4'), ('m2','v1'), ('m2','v6'), ('m3','v10'), ('m4','v7'); set standard_compliant_cte=0; with recursive reached_objects as ( select v, 'init' as m from objects where v in ('v3','v7','v9') union select module_results.v, module_results.m from module_results, applied_modules where module_results.m = applied_modules.m ), applied_modules as ( select * from modules where 1=0 union select modules.m from modules where not exists (select * from module_arguments where module_arguments.m = modules.m and module_arguments.v not in (select v from reached_objects)) ) select * from reached_objects; v m v3 init v7 init v9 init v4 m1 v1 m2 v6 m2 v10 m3 with recursive reached_objects as ( select v, 'init' as m from objects where v in ('v3','v7','v9') union select module_results.v, module_results.m from module_results, applied_modules where module_results.m = applied_modules.m ), applied_modules as ( select * from modules where 1=0 union select modules.m from modules where 'v6' not in (select v from reached_objects) and not exists (select * from module_arguments where module_arguments.m = modules.m and module_arguments.v not in (select v from reached_objects)) ) select * from reached_objects; v m v3 init v7 init v9 init v4 m1 v1 m2 v6 m2 prepare stmt from " with recursive reached_objects as ( select v, 'init' as m from objects where v in ('v3','v7','v9') union select module_results.v, module_results.m from module_results, applied_modules where module_results.m = applied_modules.m ), applied_modules as ( select * from modules where 1=0 union select modules.m from modules where 'v6' not in (select v from reached_objects) and not exists (select * from module_arguments where module_arguments.m = modules.m and module_arguments.v not in (select v from reached_objects)) ) select * from reached_objects; "; execute stmt; v m v3 init v7 init v9 init v4 m1 v1 m2 v6 m2 execute stmt; v m v3 init v7 init v9 init v4 m1 v1 m2 v6 m2 deallocate prepare stmt; drop table objects, modules, module_arguments, module_results; set standard_compliant_cte=default; select @@standard_compliant_cte; @@standard_compliant_cte 1 # # mdev-12554: impossible where in recursive select # CREATE TABLE t1 (i int); INSERT INTO t1 VALUES (1),(2); WITH RECURSIVE cte(f) AS ( SELECT i FROM t1 UNION SELECT f FROM t1, cte WHERE 1=0 ) SELECT * FROM cte; f 1 2 DROP TABLE t1; # # mdev-12556: recursive execution uses Aria temporary tables # CREATE TABLE t (c1 varchar(255), c2 tinytext); INSERT INTO t VALUES ('a','a'),('b','b'),('c','c'),('d','d'); ANALYZE WITH RECURSIVE cte(f) AS ( SELECT c1 FROM t UNION 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 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 WITH RECURSIVE cte(f) AS ( SELECT c1 FROM t UNION SELECT c1 FROM t, cte ) SELECT COUNT(*) FROM cte; COUNT(*) 4 ANALYZE WITH RECURSIVE cte(f) AS ( SELECT c2 FROM t UNION 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 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 WITH RECURSIVE cte(f) AS ( SELECT c2 FROM t UNION SELECT c2 FROM t, cte ) SELECT COUNT(*) FROM cte; COUNT(*) 4 DROP TABLE t; # # mdev-12563: no recursive references on the top level of the CTE spec # CREATE TABLE t (i int); INSERT INTO t VALUES (3), (1),(2); SET standard_compliant_cte=0; WITH RECURSIVE cte(f) AS ( SELECT i FROM t UNION SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte ) ) SELECT * FROM cte; f 3 1 2 WITH RECURSIVE cte(f) AS ( SELECT i FROM t UNION SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte WHERE i < 2 ) UNION SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte WHERE i > 2 ) ) SELECT * FROM cte; f 3 1 2 WITH RECURSIVE cte(f) AS ( SELECT i FROM t UNION SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte WHERE i < 2 UNION SELECT * FROM cte WHERE i > 2) ) SELECT * FROM cte; f 3 1 2 WITH RECURSIVE cte(f) AS ( SELECT i FROM t UNION SELECT i FROM t WHERE i NOT IN ( SELECT * FROM t WHERE i IN ( SELECT * FROM cte ) GROUP BY i ) ) SELECT * FROM cte; f 3 1 2 WITH RECURSIVE cte(f) AS ( SELECT i FROM t UNION SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte ) UNION SELECT * FROM cte WHERE f > 2 ) SELECT * FROM cte; f 3 1 2 set standard_compliant_cte=default; DROP TABLE t;