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 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 #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 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 # 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 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 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 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 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 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 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 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 DERIVED folks ALL NULL NULL NULL NULL 12 Using where 6 RECURSIVE UNION ALL NULL NULL NULL NULL 12 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 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 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 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 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 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 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 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; # # mdev-14184: recursive CTE embedded into CTE with multiple references # WITH cte1 AS ( SELECT n FROM ( WITH RECURSIVE rec_cte(n) AS ( SELECT 1 as n1 UNION ALL SELECT n+1 as n2 FROM rec_cte WHERE n < 3 ) SELECT n FROM rec_cte ) AS X ), cte2 as ( SELECT 2 FROM cte1 ) SELECT * FROM cte1; n 1 2 3 # # mdev-14629: a user-defined variable is defined by the recursive CTE # set @var= ( with recursive cte_tab(a) as ( select 1 union select a+1 from cte_tab where a<3) select count(*) from cte_tab ); select @var; @var 3 create table t1(a int, b int); insert into t1 values (3,8),(1,5),(5,7),(7,4),(4,3); set @var= ( with recursive summ(a,s) as ( select 1, 0 union select t1.b, t1.b+summ.s from summ, t1 where summ.a=t1.a) select s from summ order by a desc limit 1 ); select @var; @var 27 set @var= ( with recursive cte_1 as ( select 1 union select * from cte_2), cte_2 as ( select * from cte_1 union select a from t1, cte_2 where t1.a=cte_2.a) select * from cte_2 limit 1 ); ERROR HY000: Unacceptable mutual recursion with anchored table 'cte_1' drop table t1; # # mdev-14777: crash caused by the same as in mdev-14755 # CREATE TABLE t1 (i1 int NOT NULL, i2 int); CREATE TABLE t2 (d1 int NOT NULL PRIMARY KEY); CREATE TABLE t3 (i int ); insert into t1 select seq,seq from seq_1_to_100000; insert into t2 select seq from seq_1000_to_100000; insert into t3 select seq from seq_1_to_1000; SELECT * FROM ( SELECT * FROM ( WITH RECURSIVE rt AS ( SELECT i2 P, i1 C FROM t1 WHERE i1 IN (SELECT d1 FROM t2) UNION SELECT t1.i2 P, rt.C C FROM t1, rt ) SELECT C,P FROM ( SELECT P,C FROM rt WHERE NOT EXISTS (SELECT 1 FROM t1) ) Y ) X WHERE 1 = 1 ) K, t3; C P i drop table t1,t2,t3; # # mdev-14879: subquery with recursive reference in WHERE of CTE # create table flights (departure varchar(32), arrival varchar(32), carrier varchar(20), flight_number char(7)); insert into flights values ('Seattle', 'Frankfurt', 'Lufthansa', 'LH 491'), ('Seattle', 'Chicago', 'American', 'AA 2573'), ('Seattle', 'Los Angeles', 'Alaska Air', 'AS 410'), ('Chicago', 'New York', 'American', 'AA 375'), ('Chicago', 'Montreal', 'Air Canada', 'AC 3053'), ('Los Angeles', 'New York', 'Delta', 'DL 1197'), ('Moscow', 'Tokyo', 'Aeroflot', 'SU 264'), ('New York', 'Paris', 'Air France', 'AF 23'), ('Frankfurt', 'Moscow', 'Lufthansa', 'LH 1444'), ('Tokyo', 'Seattle', 'ANA', 'NH 178'), ('Los Angeles', 'Tokyo', 'ANA', 'NH 175'), ('Moscow', 'Los Angeles', 'Aeroflot', 'SU 106'), ('Montreal', 'Paris', 'Air Canada', 'AC 870'), ('Cairo', 'Paris', 'Air France', 'AF 503'), ('New York', 'Seattle', 'American', 'AA 45'), ('Paris', 'Chicago', 'Air France', 'AF 6734'); with recursive destinations (city) as ( select a.arrival from flights a where a.departure='Cairo' union select b.arrival from destinations r, flights b where r.city=b.departure) select * from destinations; city Paris Chicago New York Montreal Seattle Frankfurt Los Angeles Moscow Tokyo set standard_compliant_cte=0; with recursive destinations (city, legs) as ( select a.arrival, 1 from flights a where a.departure='Cairo' union select b.arrival, r.legs + 1 from destinations r, flights b where r.city=b.departure and b.arrival not in (select city from destinations) ) select * from destinations; city legs Paris 1 Chicago 2 New York 3 Montreal 3 Seattle 4 Frankfurt 5 Los Angeles 5 Moscow 6 Tokyo 6 explain extended with recursive destinations (city, legs) as ( select a.arrival, 1 from flights a where a.departure='Cairo' union select b.arrival, r.legs + 1 from destinations r, flights b where r.city=b.departure and b.arrival not in (select city from destinations) ) select * from destinations; id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 16 100.00 2 DERIVED a ALL NULL NULL NULL NULL 16 100.00 Using where 3 RECURSIVE UNION b ALL NULL NULL NULL NULL 16 100.00 Using where 3 RECURSIVE UNION ref key0 key0 35 test.b.departure 2 100.00 4 DEPENDENT SUBQUERY ALL NULL NULL NULL NULL 16 100.00 Using where NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL Warnings: Note 1003 with recursive destinations as (select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union select `test`.`b`.`arrival` AS `arrival`,`r`.`legs` + 1 AS `r.legs + 1` from `destinations` `r` join `test`.`flights` `b` where `r`.`city` = `test`.`b`.`departure` and !(`test`.`b`.`arrival`,(select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null))))select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations` set standard_compliant_cte=default; drop table flights;