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	<derived2>	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	<union2,3>	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	<derived2>	ALL	NULL	NULL	NULL	NULL	5	
2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	5	Using where
3	RECURSIVE UNION	<derived2>	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	<union2,3>	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(12)	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	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
1	PRIMARY	<derived3>	ref	key0	key0	5	c.h_id	2	100.00	
1	PRIMARY	<derived3>	ref	key0	key0	5	c.w_id	2	100.00	
2	DERIVED	<derived3>	ALL	NULL	NULL	NULL	NULL	12	100.00	Using where
3	DERIVED	folks	ALL	NULL	NULL	NULL	NULL	12	100.00	Using where
4	RECURSIVE UNION	<derived2>	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	<derived2>	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	<union3,4,5>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
Warnings:
Note	1003	with recursive ancestor_couple_ids(h_id,w_id) as (/* select#2 */ 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(id,name,dob,father,mother) as (/* select#3 */ 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#4 */ 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#5 */ 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#1 */ 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	<derived2>	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	<derived2>	ALL	NULL	NULL	NULL	NULL	12	100.00	Using where; Using join buffer (flat, BNL join)
NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
Warnings:
Note	1003	with recursive ancestors as (/* select#2 */ 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#3 */ 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#1 */ 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	<derived2>	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	<derived2>	ref	key0	key0	5	test.p.id	2	
4	RECURSIVE UNION	p	ALL	PRIMARY	NULL	NULL	NULL	12	
4	RECURSIVE UNION	<derived2>	ref	key0	key0	5	test.p.id	2	
NULL	UNION RESULT	<union2,3,4>	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	<derived4>	ALL	NULL	NULL	NULL	NULL	24	
4	DERIVED	folks	ALL	NULL	NULL	NULL	NULL	12	Using where
6	RECURSIVE UNION	<derived3>	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	<derived3>	ALL	NULL	NULL	NULL	NULL	12	Using where; Using join buffer (flat, BNL join)
NULL	UNION RESULT	<union3,2>	ALL	NULL	NULL	NULL	NULL	NULL	
5	RECURSIVE UNION	<derived4>	ALL	NULL	NULL	NULL	NULL	24	
NULL	UNION RESULT	<union4,6,5>	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": "<derived4>",
      "access_type": "ALL",
      "rows": 24,
      "filtered": 100,
      "materialized": {
        "query_block": {
          "recursive_union": {
            "table_name": "<union4,6,5>",
            "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,
                  "operation": "UNION",
                  "table": {
                    "table_name": "<derived3>",
                    "access_type": "ALL",
                    "rows": 12,
                    "filtered": 100,
                    "attached_condition": "prev_gen.`id` < 345",
                    "materialized": {
                      "query_block": {
                        "recursive_union": {
                          "table_name": "<union3,2>",
                          "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,
                                "operation": "UNION",
                                "table": {
                                  "table_name": "folks",
                                  "access_type": "ALL",
                                  "possible_keys": ["PRIMARY"],
                                  "rows": 12,
                                  "filtered": 100
                                },
                                "block-nl-join": {
                                  "table": {
                                    "table_name": "<derived3>",
                                    "access_type": "ALL",
                                    "rows": 12,
                                    "filtered": 100
                                  },
                                  "buffer_type": "flat",
                                  "buffer_size": "686",
                                  "join_type": "BNL",
                                  "attached_condition": "prev_gen.father = folks.`id` or prev_gen.mother = folks.`id`"
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  }
                }
              },
              {
                "query_block": {
                  "select_id": 5,
                  "operation": "UNION",
                  "table": {
                    "table_name": "<derived4>",
                    "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": "<derived3>",
      "access_type": "ALL",
      "rows": 12,
      "filtered": 100,
      "materialized": {
        "query_block": {
          "recursive_union": {
            "table_name": "<union3,2>",
            "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,
                  "operation": "UNION",
                  "table": {
                    "table_name": "<derived4>",
                    "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;
WITH RECURSIVE
positions(i) AS (
VALUES(0)
UNION SELECT ALL
i+1 FROM positions WHERE i < 4*4-1
),
solutions(board, n_queens) AS (
SELECT REPEAT('-', 4*4), 0
FROM positions
UNION
SELECT
concat(substr(board, 1, i),'*',substr(board, i+2)),n_queens + 1 AS n_queens
FROM positions AS ps, solutions
WHERE n_queens < 4
AND substr(board,1,i) != '*'
      AND NOT EXISTS (
SELECT 1 FROM positions WHERE
substr(board,i+1,1) = '*' AND
(
i % 4 = ps.i % 4 OR
i div 4 = ps.i div 4 OR
i div 4 + (i % 4) = ps.i div 4 + (ps.i % 4) OR
i div 4 - (i % 4) = ps.i div 4 - (ps.i % 4)
)
)
)
SELECT regexp_replace(board,concat('(',REPEAT('.', 4),')'),'\\1\n') n_queens FROM solutions WHERE n_queens = 4;
n_queens
--*-
*---
---*
-*--

-*--
---*
*---
--*-

#
# 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": "<derived2>",
      "access_type": "ALL",
      "rows": 10,
      "filtered": 100,
      "materialized": {
        "query_block": {
          "recursive_union": {
            "table_name": "<union2,3>",
            "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,
                  "operation": "UNION",
                  "table": {
                    "table_name": "<derived2>",
                    "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	<derived2>	ALL	NULL	NULL	NULL	NULL	5	
2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	5	Using where
4	RECURSIVE UNION	<derived2>	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	<union2,4>	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": "<derived2>",
      "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": "<union2,3>",
            "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,
                  "operation": "UNION",
                  "r_loops": 10,
                  "r_total_time_ms": "REPLACED",
                  "table": {
                    "table_name": "<derived2>",
                    "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	<derived2>	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	<derived2>	ALL	NULL	NULL	NULL	NULL	4	4.00	100.00	100.00	Using join buffer (flat, BNL join)
NULL	UNION RESULT	<union2,3>	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	<derived2>	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	<derived2>	ALL	NULL	NULL	NULL	NULL	4	4.00	100.00	100.00	Using join buffer (flat, BNL join)
NULL	UNION RESULT	<union2,3>	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	<derived2>	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	<derived2>	ref	key0	key0	35	test.b.departure	2	100.00	
4	DEPENDENT SUBQUERY	<derived2>	ALL	NULL	NULL	NULL	NULL	16	100.00	Using where
NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
Warnings:
Note	1003	with recursive destinations(city,legs) as (/* select#2 */ select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union /* select#3 */ 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 !<in_optimizer>(`test`.`b`.`arrival`,<exists>(/* select#4 */ select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null))))/* select#1 */ select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations`
set standard_compliant_cte=default;
drop table flights;
#
# MDEV-15162: Setting user variable in recursive CTE
#
SET @c=1;
WITH RECURSIVE cte AS
(SELECT 5
UNION
SELECT @c:=@c+1 FROM cte WHERE @c<3)
SELECT * FROM cte;
5
5
2
3
#
# MDEV-15575: using recursive cte with big_tables enabled
#
set tmp_memory_table_size=0;
with recursive qn as
(select 123 as a union all select 1+a from qn where a<130)
select * from qn;
a
123
124
125
126
127
128
129
130
set tmp_memory_table_size=default;
#
# MDEV-15571: using recursive cte with big_tables enabled
#
create table t1 (a bigint);
insert into t1 values(1);
set tmp_memory_table_size=0;
with recursive qn as
(
select  a from t1
union all
select a*2000 from qn where a<10000000000000000000
)
select * from qn;
ERROR 22003: BIGINT value is out of range in '`qn`.`a` * 2000'
set tmp_memory_table_size=default;
drop table t1;
#
# MDEV-15556: using recursive cte with big_tables enabled
#             when recursive tables are accessed by key
#
set tmp_memory_table_size=0;
CREATE TABLE t1 (id int, name char(10), leftpar int, rightpar int);
INSERT INTO t1 VALUES
(1, "A", 2, 3), (2, "LA", 4, 5), (4, "LLA", 6, 7),
(6, "LLLA", NULL, NULL), (7, "RLLA", NULL, NULL), (5, "RLA", 8, 9),
(8, "LRLA", NULL, NULL), (9, "RRLA", NULL, NULL), (3, "RA", 10, 11),
(10, "LRA", 12, 13), (11, "RRA", 14, 15), (15, "RRRA", NULL, NULL),
(16, "B", 17, 18), (17, "LB", NULL, NULL), (18, "RB", NULL, NULL);
CREATE TABLE t2 SELECT * FROM t1 ORDER BY rand();
WITH RECURSIVE tree_of_a AS
(SELECT *, cast(id AS char(200)) AS path FROM t2 WHERE name="A"
    UNION ALL
SELECT t2.*, concat(tree_of_a.path,",",t2.id)
FROM t2 JOIN tree_of_a ON t2.id=tree_of_a.leftpar
UNION ALL
SELECT t2.*, concat(tree_of_a.path,",",t2.id)
FROM t2 JOIN tree_of_a ON t2.id=tree_of_a.rightpar)
SELECT * FROM tree_of_a
ORDER BY path;
id	name	leftpar	rightpar	path
1	A	2	3	1
2	LA	4	5	1,2
4	LLA	6	7	1,2,4
6	LLLA	NULL	NULL	1,2,4,6
7	RLLA	NULL	NULL	1,2,4,7
5	RLA	8	9	1,2,5
8	LRLA	NULL	NULL	1,2,5,8
9	RRLA	NULL	NULL	1,2,5,9
3	RA	10	11	1,3
10	LRA	12	13	1,3,10
11	RRA	14	15	1,3,11
15	RRRA	NULL	NULL	1,3,11,15
EXPLAIN WITH RECURSIVE tree_of_a AS
(SELECT *, cast(id AS char(200)) AS path FROM t2 WHERE name="A"
    UNION ALL
SELECT t2.*, concat(tree_of_a.path,",",t2.id)
FROM t2 JOIN tree_of_a ON t2.id=tree_of_a.leftpar
UNION ALL
SELECT t2.*, concat(tree_of_a.path,",",t2.id)
FROM t2 JOIN tree_of_a ON t2.id=tree_of_a.rightpar)
SELECT * FROM tree_of_a
ORDER BY path;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	15	Using filesort
2	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	15	Using where
3	RECURSIVE UNION	t2	ALL	NULL	NULL	NULL	NULL	15	Using where
3	RECURSIVE UNION	<derived2>	ref	key0	key0	5	test.t2.id	2	
4	RECURSIVE UNION	t2	ALL	NULL	NULL	NULL	NULL	15	Using where
4	RECURSIVE UNION	<derived2>	ref	key0	key0	5	test.t2.id	2	
NULL	UNION RESULT	<union2,3,4>	ALL	NULL	NULL	NULL	NULL	NULL	
DROP TABLE t1,t2;
set tmp_memory_table_size=default;
#
# MDEV-15840: recursive tables are accessed by key
#             (the same problem as for MDEV-15556)
#
CREATE TABLE t1 (p1 text,k2 int, p2 text, k1 int);
INSERT INTO t1 select seq, seq, seq, seq from seq_1_to_1000;
CREATE PROCEDURE getNums()
BEGIN
WITH RECURSIVE cte as
(
SELECT * FROM t1
UNION
SELECT c.* FROM t1 c JOIN cte p ON c.p1 = p.p2 AND c.k2 = p.k1
)
SELECT * FROM cte LIMIT 10;
END |
call getNums();
p1	k2	p2	k1
1	1	1	1
2	2	2	2
3	3	3	3
4	4	4	4
5	5	5	5
6	6	6	6
7	7	7	7
8	8	8	8
9	9	9	9
10	10	10	10
DROP PROCEDURE getNums;
DROP TABLE t1;
#
# MDEV-15894: aggregate/winfow functions in non-recorsive part
#
create table t1(b int);
insert into t1 values(10),(20),(10);
with recursive qn as
(select max(b) as a from t1 union
select a from qn)
select * from qn;
a
20
with recursive qn as
(select rank() over (order by b) as a from t1 union
select a from qn)
select * from qn;
a
1
3
drop table t1;
#
# MDEV-16086: tmp table for CTE is created as ARIA tables
#
CREATE TABLE t1 (
Id int(11) not null AUTO_INCREMENT,
Parent varchar(15) not null,
Child varchar(15) not null,
PRIMARY KEY (Id)
) ENGINE = MyISAM;
INSERT INTO t1 (Parent, Child) VALUES
('123', '456'),('456', '789'),('321', '654'),('654', '987');
WITH RECURSIVE cte AS
( SELECT b.Parent,
b.Child,
CAST(CONCAT(b.Child,',') AS CHAR(513)) Path
FROM t1 b
LEFT OUTER JOIN t1 bc ON b.Child = bc.Parent
WHERE bc.Id IS NULL
UNION ALL SELECT c.Parent,
c.Child,
CONCAT(p.Path,c.Child,',') Path
FROM t1 c
INNER JOIN cte p ON c.Child = p.Parent)
SELECT *
FROM cte
ORDER BY Path;
Parent	Child	Path
456	789	789,
123	456	789,456,
654	987	987,
321	654	987,654,
DROP TABLE t1;
#
# MDEV-16212: recursive CTE with global ORDER BY
#
set statement max_recursive_iterations = 2 for
WITH RECURSIVE qn AS (
SELECT 1 FROM dual UNION ALL
SELECT 1 FROM qn
ORDER BY (SELECT * FROM qn))
SELECT count(*) FROM qn;
ERROR 42000: This version of MariaDB doesn't yet support 'global ORDER_BY/LIMIT in recursive CTE spec'
#
# MDEV-15581: mix of ALL and DISTINCT UNION in recursive CTE
#
create table t1(a int);
insert into t1 values(1),(2);
insert into t1 values(1),(2);
set @c=0, @d=0;
WITH RECURSIVE qn AS
(
select 1,0 as col from t1
union distinct
select 1,0 from t1
union all
select 3, 0*(@c:=@c+1) from qn where @c<1
union all
select 3, 0*(@d:=@d+1) from qn where @d<1
)
select * from qn;
ERROR 42000: This version of MariaDB doesn't yet support 'mix of ALL and DISTINCT UNION operations in recursive CTE spec'
drop table t1;
#
# MDEV-16629: function with recursive CTE using a base table
#
CREATE TABLE t1 (id int);
INSERT INTO t1 VALUES (0), (1),(2);
WITH recursive cte AS
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
SELECT count(id) FROM cte;
count(id)
4
CREATE OR REPLACE FUNCTION func() RETURNS int
RETURN
(
WITH recursive cte AS
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
SELECT count(id) FROM cte
);
SELECT func();
func()
4
DROP FUNCTION func;
DROP TABLE t1;
#
# MDEV-16661: function with recursive CTE using no base tables
#             (fixed by the patch for MDEV-16629)
#
CREATE OR REPLACE FUNCTION func() RETURNS int
RETURN
(
WITH RECURSIVE cte AS
(SELECT 1 as id UNION SELECT * FROM cte)
SELECT count(id) FROM cte
);
SELECT func();
func()
1
DROP FUNCTION func;
#
# MDEV-17024: two materialized CTEs using the same recursive CTE
#
create table t1 (id int);
insert into t1 values (1), (2), (3);
with recursive
rcte(a) as
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
cte1 as
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
cte2 as
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
select * from cte1, cte2;
c1	c2
2	1
explain extended with recursive
rcte(a) as
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
cte1 as
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
cte2 as
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
select * from cte1, cte2;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
1	PRIMARY	<derived4>	ALL	NULL	NULL	NULL	NULL	6	100.00	
1	PRIMARY	<derived5>	ALL	NULL	NULL	NULL	NULL	6	100.00	Using join buffer (flat, BNL join)
4	DERIVED	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
4	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where; Using join buffer (flat, BNL join)
5	DERIVED	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
5	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where; Using join buffer (flat, BNL join)
2	DERIVED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
3	RECURSIVE UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	2	100.00	Using where
NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
Warnings:
Note	1003	with recursive rcte(a) as (/* select#2 */ select 1 AS `a` union /* select#3 */ select cast(`rcte`.`a` + 1 as unsigned) AS `cast(a+1 as unsigned)` from `rcte` where `rcte`.`a` < 10), cte1 as (/* select#4 */ select count(0) AS `c1` from `rcte` join `test`.`t1` where `rcte`.`a` between 3 and 5 and `test`.`t1`.`id` = `rcte`.`a` - 3), cte2 as (/* select#5 */ select count(0) AS `c2` from `rcte` join `test`.`t1` where `rcte`.`a` between 7 and 8 and `test`.`t1`.`id` = `rcte`.`a` - 7)/* select#1 */ select `cte1`.`c1` AS `c1`,`cte2`.`c2` AS `c2` from `cte1` join `cte2`
prepare stmt from "with recursive
rcte(a) as
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
cte1 as
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
cte2 as
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
select * from cte1, cte2";
execute stmt;
c1	c2
2	1
execute stmt;
c1	c2
2	1
create table t2 (c1 int, c2 int);
create procedure p() insert into t2 with recursive
rcte(a) as
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
cte1 as
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
cte2 as
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
select * from cte1, cte2;
call p();
select * from t2;
c1	c2
2	1
with recursive
rcte(a) as
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
cte1 as
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
cte2 as
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
select * from cte1;
c1
2
with recursive
rcte(a) as
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
cte1 as
(select count(*) as c1 from t1),
cte2 as
(select count(*) as c2 from t2)
select * from cte1,cte2;
c1	c2
3	1
with recursive
rcte(a) as
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
cte1 as
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
cte2 as
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
select * from cte1, cte2 where cte1.c1 = 3;
c1	c2
drop procedure p;
drop table t1,t2;
#
# MDEV-17201: recursive part with LIMIT
#
CREATE TABLE purchases (
id int unsigned NOT NULL AUTO_INCREMENT,
pdate date NOT NULL,
quantity int unsigned NOT NULL,
p_id int unsigned NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO purchases(pdate, quantity, p_id) VALUES
('2014-11-01',5 ,1),('2014-11-03', 3 ,1),
('2014-11-01',2 ,2),('2014-11-03', 4 ,2);
CREATE TABLE expired (
edate date NOT NULL,
quantity int unsigned NOT NULL,
p_id int unsigned NOT NULL,
PRIMARY KEY (edate,p_id)
);
INSERT INTO expired VALUES ('2014-11-12', 5 ,1),('2014-11-08', 1 ,2);
WITH RECURSIVE expired_map AS (
SELECT edate AS expired_date,
CAST(NULL AS date) AS purchase_date,
0 AS quantity,
e.p_id,
(SELECT MAX(id)+1 FROM purchases p
WHERE pdate <= edate AND p.p_id =p_id) AS purchase_processed,
quantity AS unresolved
FROM expired e
UNION
( SELECT expired_date,
pdate,
IF(p.quantity < m.unresolved, p.quantity, m.unresolved),
p.p_id,
p.id,
IF(p.quantity < m.unresolved, m.unresolved - p.quantity, 0)
FROM purchases p JOIN expired_map m ON p.p_id = m.p_id
WHERE p.id < m.purchase_processed AND m.unresolved > 0
ORDER BY p.id DESC
LIMIT 1
)
)
SELECT  * FROM expired_map;
expired_date	purchase_date	quantity	p_id	purchase_processed	unresolved
2014-11-12	NULL	0	1	5	5
2014-11-08	NULL	0	2	5	1
2014-11-08	2014-11-03	1	2	4	0
DROP TABLE purchases, expired;
#
# MDEV-17635: Two recursive CTEs, the second using the first
#
WITH RECURSIVE
x AS (SELECT 0 as k UNION ALL SELECT k + 1 FROM x WHERE k < 1),
z AS
( SELECT  k1 AS cx, k2 AS cy, k1, k2
FROM (SELECT k  AS k1 FROM x) x1 JOIN (SELECT k  AS k2 FROM x) y1
UNION
SELECT 1,1,1,1 FROM z)
SELECT * FROM z;
cx	cy	k1	k2
0	0	0	0
1	0	1	0
0	1	0	1
1	1	1	1
# https://wiki.postgresql.org/wiki/Mandelbrot_set:
WITH RECURSIVE x(i) AS (
SELECT CAST(0 AS DECIMAL(13, 10))
UNION ALL
SELECT i + 1
FROM x
WHERE i < 101
),
Z(Ix, Iy, Cx, Cy, X, Y, I) AS (
SELECT Ix, Iy, X, Y, X, Y, 0
FROM (SELECT CAST(-2.2 + 0.031 * i AS DECIMAL(13, 10)) AS X,
i AS Ix FROM x) AS xgen
CROSS JOIN (
SELECT CAST(-1.5 + 0.031 * i AS DECIMAL(13, 10)) AS Y,
i AS iY FROM x
) AS ygen
UNION ALL
SELECT Ix, Iy, Cx, Cy,
CAST(X * X - Y * Y + Cx AS DECIMAL(13, 10)) AS X,
CAST(Y * X * 2 + Cy AS DECIMAL(13, 10)), I + 1
FROM Z
WHERE X * X + Y * Y < 16.0
AND I < 27
),
Zt (Ix, Iy, I) AS (
SELECT Ix, Iy, MAX(I) AS I
FROM Z
GROUP BY Iy, Ix
ORDER BY Iy, Ix
)
SELECT GROUP_CONCAT(
SUBSTRING(
' .,,,-----++++%%%%@@@@#### ',
GREATEST(I, 1),
1
) ORDER BY Ix SEPARATOR ''
       ) AS 'Mandelbrot Set'
  FROM Zt
GROUP BY Iy
ORDER BY Iy;
Mandelbrot Set
             ....................................................................................     
            .......................................................................................   
           .........................................................................................  
          ........................................................................................... 
        ....................................................,,,,,,,,,.................................
       ................................................,,,,,,,,,,,,,,,,,,.............................
      ..............................................,,,,,,,,,,,,,,,,,,,,,,,,..........................
     ............................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,........................
     ..........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,......................
    .........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,....................
   ........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...................
  .......................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.................
 .......................................,,,,,,,,,,,,,,,,,,,,,,,,--,,,,,,,,,,,,,,,,,,,,................
......................................,,,,,,,,,,,,,,,,,,,,,,,,,,-+--,,,,,,,,,,,,,,,,,,,...............
....................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----,,,,,,,,,,,,,,,,,,,..............
...................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,--- -----,,,,,,,,,,,,,,,,,.............
.................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---++--++,,,,,,,,,,,,,,,,,,............
................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----%++---,,,,,,,,,,,,,,,,,............
..............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+%----,,,,,,,,,,,,,,,,,,...........
.............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----- %%+----,,,,,,,,,,,,,,,,,,..........
...........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---%-+%   ----,,,,,,,,,,,,,,,,,,,.........
..........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---+ +##  %+%---,,,,,,,,,,,,,,,,,,.........
........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----#      # +---,,,,,,,,,,,,,,,,,,........
.......................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------%       %-----,,,,,,,,,,,,,,,,,........
.....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---------+         ------,,,,,,,,,,,,,,,,,.......
....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----------+@       +-----------,,,,,,,,,,,,.......
..................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----@-------++       ++-----------,,,,,,,,,,,,......
.................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--+@% ---+ +@%%@     %%+@+@%------+-,,,,,,,,,,,......
................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----  # ++%               % @-----++--,,,,,,,,,,,.....
..............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----+    %                  %%++ %+%@-,,,,,,,,,,,.....
.............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+#                       #%    ++-,,,,,,,,,,,,....
............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------+                             @---,,,,,,,,,,,,....
..........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------++%                             ---,,,,,,,,,,,,....
.........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--------+ +                             %+---,,,,,,,,,,,,,...
........,,,,,,,,,,,,,,,,,,,,,--------------------@                                +----,,,,,,,,,,,,...
.......,,,,,,,,,,,,,,,,,,,,,,- +-----------------+                                 ----,,,,,,,,,,,,...
.......,,,,,,,,,,,,,,,,,,,,,--++------+---------+%                                 +++--,,,,,,,,,,,,..
......,,,,,,,,,,,,,,,,,,,,,,--%+-----++---------                                     #+-,,,,,,,,,,,,..
.....,,,,,,,,,,,,,,,,,,,,,,----#%++--+@ -+-----+%                                     --,,,,,,,,,,,,..
.....,,,,,,,,,,,,,,,,,,,,,,-----+## ++@ + +----%                                    +--,,,,,,,,,,,,,..
....,,,,,,,,,,,,,,,,,,,,,,------+@  @     @@++++#                                   +--,,,,,,,,,,,,,..
....,,,,,,,,,,,,,,,,,,,,,-------%           #++%                                      -,,,,,,,,,,,,,..
...,,,,,,,,,,,,,,,,,,,,,------++%#           %%@                                     %-,,,,,,,,,,,,,,.
...,,,,,,,,,,,,,,,,,,,--------+               %                                     +--,,,,,,,,,,,,,,.
...,,,,,,,,,,,,,,,,,,-----+--++@              #                                      --,,,,,,,,,,,,,,.
..,,,,,,,,,,,,,,,,,-------%+++%                                                    @--,,,,,,,,,,,,,,,.
..,,,,,,,,,,,-------------+ @#@                                                    ---,,,,,,,,,,,,,,,.
..,,,,,,,,,---@--------@-+%                                                       +---,,,,,,,,,,,,,,,.
..,,,,,------- +-++++-+%%%                                                       +----,,,,,,,,,,,,,,,.
..,,,,,,------%--------++%                                                       +----,,,,,,,,,,,,,,,.
..,,,,,,,,,,--+----------++#                                                       ---,,,,,,,,,,,,,,,.
..,,,,,,,,,,,,------------+@@@%                                                    +--,,,,,,,,,,,,,,,.
..,,,,,,,,,,,,,,,,,------- +++%                                                    %--,,,,,,,,,,,,,,,.
...,,,,,,,,,,,,,,,,,,---------+@              @                                      --,,,,,,,,,,,,,,.
...,,,,,,,,,,,,,,,,,,,,------- #              %@                                    +--,,,,,,,,,,,,,,.
...,,,,,,,,,,,,,,,,,,,,,-------++@           %+                                      %-,,,,,,,,,,,,,,.
....,,,,,,,,,,,,,,,,,,,,,-------            %++%                                     %-,,,,,,,,,,,,,..
....,,,,,,,,,,,,,,,,,,,,,,------+#  %#   #@ ++++                                    +--,,,,,,,,,,,,,..
.....,,,,,,,,,,,,,,,,,,,,,,-----+ %%++% +@+----+                                    +--,,,,,,,,,,,,,..
.....,,,,,,,,,,,,,,,,,,,,,,,---%+++--+#+--------%                                    #--,,,,,,,,,,,,..
......,,,,,,,,,,,,,,,,,,,,,,--++-----%%---------                                    @#--,,,,,,,,,,,,..
.......,,,,,,,,,,,,,,,,,,,,,---------------------+@                                +-++,,,,,,,,,,,,...
........,,,,,,,,,,,,,,,,,,,,,--------------------+                                 ----,,,,,,,,,,,,...
.........,,,,,,,,,,,,,,,,,,,,----,,,-------------                                #+----,,,,,,,,,,,,...
..........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------+ +                              +---,,,,,,,,,,,,,...
...........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--------+%#                           #---,,,,,,,,,,,,....
............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------+#                        @   @---,,,,,,,,,,,,....
.............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+#                        +    @--,,,,,,,,,,,,....
..............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---+%   %+@                 %+-+ +++%-,,,,,,,,,,,.....
................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----% %@++              # %  -----++-,,,,,,,,,,,,.....
.................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-- ++ ---+ + +%@     %++++++------%-,,,,,,,,,,,......
...................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---- -------++       +------------,,,,,,,,,,,,......
....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----------+%       +--------,,,,,,,,,,,,,,,.......
......................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--------+#        -----,,,,,,,,,,,,,,,,,,.......
.......................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------+       #----,,,,,,,,,,,,,,,,,,........
.........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----+%      %#---,,,,,,,,,,,,,,,,,,,........
..........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---+%+%@  %+%%--,,,,,,,,,,,,,,,,,,.........
............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---+-+%  %----,,,,,,,,,,,,,,,,,,..........
.............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+%@+---,,,,,,,,,,,,,,,,,,,..........
...............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+%----,,,,,,,,,,,,,,,,,,...........
................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----%+ +--,,,,,,,,,,,,,,,,,............
..................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---++----,,,,,,,,,,,,,,,,,.............
...................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,---@-----,,,,,,,,,,,,,,,,,.............
.....................................,,,,,,,,,,,,,,,,,,,,,,,,,,,-----,,,,,,,,,,,,,,,,,,,..............
 .....................................,,,,,,,,,,,,,,,,,,,,,,,,,,--%,,,,,,,,,,,,,,,,,,,,...............
 .......................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.................
  ........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..................
   ........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...................
    .........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,....................
     ..........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,......................
      ............................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,........................
       .............................................,,,,,,,,,,,,,,,,,,,,,,,,..........................
        ................................................,,,,,,,,,,,,,,,,,.............................
         .....................................................,,,,....................................
          ........................................................................................... 
           .........................................................................................  
            ......................................................................................    
             ....................................................................................     
               .................................................................................      
                ..............................................................................        
                  ...........................................................................         
                   ........................................................................           
#
# MDEV-17871: EXPLAIN for query with not used recursive cte
#
create table t1 (a int);
insert into t1 values (2), (1), (4), (3);
explain extended
with recursive cte as
(select * from t1 where a=1 union select a+1 from cte where a<3)
select * from cte as t;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
1	PRIMARY	<derived2>	ALL	NULL	NULL	NULL	NULL	4	100.00	
2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	4	100.00	Using where
3	RECURSIVE UNION	<derived2>	ALL	NULL	NULL	NULL	NULL	4	100.00	Using where
NULL	UNION RESULT	<union2,3>	ALL	NULL	NULL	NULL	NULL	NULL	NULL	
Warnings:
Note	1003	with recursive cte as (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 union /* select#3 */ select `cte`.`a` + 1 AS `a+1` from `cte` where `cte`.`a` < 3)/* select#1 */ select `t`.`a` AS `a` from `cte` `t`
with recursive cte as
(select * from t1 where a=1 union select a+1 from cte where a<3)
select * from cte as t;
a
1
2
3
explain extended
with recursive cte as
(select * from t1 where a=1 union select a+1 from cte where a<3)
select * from t1 as t;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
1	PRIMARY	t	ALL	NULL	NULL	NULL	NULL	4	100.00	
Warnings:
Note	1003	with recursive cte as (/* select#2 */ select `*` AS `*` from `test`.`t1` where `a` = 1 union /* select#3 */ select `a` + 1 AS `a+1` from `cte` where `a` < 3)/* select#1 */ select `test`.`t`.`a` AS `a` from `test`.`t1` `t`
with recursive cte as
(select * from t1 where a=1 union select a+1 from cte where a<3)
select * from t1 as t;
a
2
1
4
3
create table t2 ( i1 int, i2 int);
insert into t2 values (1,1),(2,2);
explain
with recursive cte as
( select * from t1 union select s1.* from t1 as s1, cte where s1.i1 = cte.i2 )
select * from t1 as t;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	PRIMARY	t	ALL	NULL	NULL	NULL	NULL	4	
drop table t1,t2;
# End of 10.2 tests
#
# MDEV-14217 [db crash] Recursive CTE when SELECT includes new field
#
CREATE TEMPORARY TABLE a_tbl (
a VARCHAR(33) PRIMARY KEY,
b VARCHAR(33)
);
INSERT INTO a_tbl VALUES ('block0', 'block0'), ('block1', NULL);
WITH RECURSIVE Q0 AS (
SELECT T0.a, T0.b, 5
FROM a_tbl T0
WHERE b IS NULL
UNION ALL
SELECT T1.a, T1.b
FROM Q0
JOIN a_tbl T1
ON T1.a=Q0.a
) SELECT distinct(Q0.a), Q0.b
FROM Q0;
ERROR 21000: The used SELECT statements have a different number of columns
DROP TABLE a_tbl;
WITH RECURSIVE x AS (SELECT 1,2 UNION ALL SELECT 1 FROM x) SELECT * FROM x;
ERROR 21000: The used SELECT statements have a different number of columns
#
# MDEV-15162: Setting user variable in recursive CTE
#
SET @c=1;
WITH RECURSIVE cte AS
(SELECT 5
UNION
SELECT @c:=@c+1 FROM cte WHERE @c<3)
SELECT * FROM cte;
5
5
2
3
#
# MDEV-14883: recursive references in operands of INTERSECT / EXCEPT
#
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', 'Amsterdam', 'KLM', 'KL 6032'),
('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'),
('New York', 'London', 'British Airways', 'BA 1511'),
('London', 'Moscow', 'British Airways', 'BA 233'),
('Moscow', 'Tokyo', 'Aeroflot', 'SU 264'),
('Moscow', 'Dubai', 'Emirates', 'EK 2421'),
('Dubai', 'Tokyo', 'Emirates', 'EK 318'),
('Dubai', 'Bangkok', 'Emirates', 'EK 2142'),
('Beijing', 'Bangkok', 'Air China', 'CA 757'),
('Beijing', 'Tokyo', 'Air China', 'CA 6653'),
('Moscow', 'Bangkok', 'Aeroflot', 'SU 270'),
('New York', 'Reykjavik', 'Icelandair', 'FL 416'),
('New York', 'Paris', 'Air France', 'AF 23'),
('Amsterdam', 'Moscow', 'KLM', 'KL 903'),
('Frankfurt', 'Dubai', 'Lufthansa', 'LH 630'),
('Frankfurt', 'Moscow', 'Lufthansa', 'LH 1444'),
('Reykjavik', 'London', 'British Airways', 'BA 2229'),
('Frankfurt', 'Beijing', 'Air China', 'CA 966'),
('Tokyo', 'Seattle', 'ANA', 'NH 178'),
('Los Angeles', 'Tokyo', 'ANA', 'NH 175'),
('Moscow', 'Los Angeles', 'Aeroflot', 'SU 106'),
('Montreal', 'Paris', 'Air Canada', 'AC 870'),
('London', 'Delhi', 'British Airways', 'BA 143'),
('Delhi', 'Bangkok', 'Air India', 'AI 306'),
('Delhi', 'Dubai', 'Air India', 'AI 995'),
('Dubai', 'Cairo', 'Emirates', 'EK 927'),
('Cairo', 'Paris', 'Air France', 'AF 503'),
('Amsterdam', 'New York', 'Delta', 'DL 47'),
('New York', 'Seattle', 'American', 'AA 45'),
('Paris', 'Chicago', 'Air France', 'AF 6734');
create table distances
(city1 varchar(32),
city2 varchar(32),
dist int);
insert into distances values
('Seattle', 'Frankfurt', 5080),
('Seattle', 'Amsterdam', 4859),
('Seattle', 'Chicago', 1733),
('Seattle', 'Los Angeles', 960),
('Chicago', 'New York', 712),
('Chicago', 'Montreal', 746),
('Los Angeles', 'New York', 2446),
('New York', 'London', 3459),
('London', 'Moscow', 1554),
('Moscow', 'Tokyo', 4647),
('Moscow', 'Dubai', 2298),
('Dubai', 'Tokyo', 4929),
('Dubai', 'Bangkok', 3050),
('Beijing', 'Bangkok', 2046),
('Beijing', 'Tokyo', 1301),
('Moscow', 'Bangkok', 4390),
('New York', 'Reykjavik', 2613),
('New York', 'Paris', 3625),
('Amsterdam', 'Moscow', 1334),
('Frankfurt', 'Dubai', 3003),
('Frankfurt', 'Moscow', 1256),
('Reykjavik', 'London', 1173),
('Frankfurt', 'Beijing', 4836),
('Tokyo', 'Seattle', 4783),
('Los Angeles', 'Tokyo', 5479),
('Moscow', 'Los Angeles', 6071),
('Moscow', 'Reykjavik', 2052),
('Montreal', 'Paris', 3425),
('London', 'Delhi', 4159),
('London', 'Paris', 214),
('Delhi', 'Bangkok', 1810),
('Delhi', 'Dubai', 1369),
('Delhi', 'Beijing', 2350),
('Dubai', 'Cairo', 1501),
('Cairo', 'Paris', 1992),
('Amsterdam', 'New York', 3643),
('New York', 'Seattle', 2402),
('Paris', 'Chicago', 4136),
('Paris', 'Los Angeles', 5647);
with recursive destinations (city) as
(
select a.arrival from flights a where a.departure = 'Seattle'
  union
select b.arrival from destinations r, flights b where r.city = b.departure
)
select * from destinations;
city
Frankfurt
Amsterdam
Chicago
Los Angeles
New York
Montreal
Moscow
Dubai
Beijing
Tokyo
London
Bangkok
Reykjavik
Paris
Seattle
Cairo
Delhi
with recursive destinations (city) as
(
select a.arrival from flights a, distances d
where a.departure = 'Seattle' and
a.departure = d.city1 and a.arrival = d.city2 and
d.dist < 4000
union
select b.arrival from destinations r, flights b, distances d
where r.city = b.departure and
b.departure = d.city1 and b.arrival = d.city2 and
d.dist < 4000
)
select * from destinations;
city
Chicago
Los Angeles
New York
Montreal
London
Reykjavik
Paris
Seattle
Moscow
Dubai
Bangkok
Cairo
set standard_compliant_cte=0;
with recursive legs_to_destinations
(departure, arrival, dist, leg_no, acc_mileage) as
(
select a.departure, a.arrival, d.dist, 1, d.dist
from flights a, distances d
where a.departure = 'Seattle' and
a.departure = d.city1 and a.arrival = d.city2 and
d.dist < 4000
union all
select b.departure, b.arrival, d.dist, r.leg_no + 1, r.acc_mileage + d.dist
from legs_to_destinations r, flights b, distances d
where r.arrival = b.departure and
b.departure = d.city1 and b.arrival = d.city2 and
d.dist < 4000 and
b.arrival not in (select arrival from legs_to_destinations)
)
select * from legs_to_destinations;
departure	arrival	dist	leg_no	acc_mileage
Seattle	Chicago	1733	1	1733
Seattle	Los Angeles	960	1	960
Chicago	New York	712	2	2445
Chicago	Montreal	746	2	2479
Los Angeles	New York	2446	2	3406
New York	London	3459	3	6865
New York	London	3459	3	5904
New York	Reykjavik	2613	3	6019
New York	Reykjavik	2613	3	5058
New York	Paris	3625	3	7031
New York	Paris	3625	3	6070
Montreal	Paris	3425	3	5904
New York	Seattle	2402	3	5808
New York	Seattle	2402	3	4847
London	Moscow	1554	4	7458
London	Moscow	1554	4	8419
Moscow	Dubai	2298	5	10717
Moscow	Dubai	2298	5	9756
Dubai	Bangkok	3050	6	12806
Dubai	Bangkok	3050	6	13767
Dubai	Cairo	1501	6	11257
Dubai	Cairo	1501	6	12218
set standard_compliant_cte=default;
with recursive destinations (city) as
(
select a.arrival from flights a, distances d
where a.departure = 'Seattle' and
a.departure = d.city1 and a.arrival = d.city2 and
d.dist < 4000
union
select b.arrival from destinations r, flights b
where r.city = b.departure
intersect
select city2 from destinations s, distances d
where s.city = d.city1 and d.dist < 4000
)
select * from destinations;
city
Chicago
Los Angeles
New York
Montreal
London
Reykjavik
Paris
Seattle
Moscow
Dubai
Bangkok
Cairo
with recursive destinations (city) as
(
select a.arrival from flights a where a.departure = 'Seattle'
  union
select * from
(
select b.arrival from destinations r, flights b
where r.city = b.departure
except
select arrival from flights
where arrival in
('New York', 'London', 'Moscow', 'Dubai', 'Cairo', 'Tokyo')
) t
)
select * from destinations;
city
Frankfurt
Amsterdam
Chicago
Los Angeles
Montreal
Beijing
Bangkok
Paris
drop table flights, distances;
#
# MDEV-15159: Forced nullability of columns in recursive CTE
#
WITH RECURSIVE cte AS (
SELECT 1 AS a UNION ALL
SELECT NULL FROM cte WHERE a IS NOT NULL)
SELECT * FROM cte;
a
1
NULL
CREATE TABLE t1 (a int NOT NULL);
INSERT INTO t1 VALUES (0);
WITH RECURSIVE cte AS
(SELECT a FROM t1 where a=0 UNION SELECT NULL FROM cte)
SELECT * FROM cte;
a
0
NULL
DROP TABLE t1;
# End of 10.3 tests
