403Webshell
Server IP : 88.99.149.37  /  Your IP : 216.73.216.141
Web Server : nginx/1.31.2
System : Linux server-88-99-149-37 6.12.0-124.56.5.el10_1.x86_64 #1 SMP PREEMPT_DYNAMIC Fri May 15 06:12:08 EDT 2026 x86_64
User : muralimurth ( 1015)
PHP Version : 8.4.23
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /usr/local/mysql/mysql-test/main/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/local/mysql/mysql-test/main/cte_recursive.test
--source include/default_optimizer_switch.inc
# This is too slow on MSAN
--source include/no_msan_without_big.inc
--source include/not_valgrind.inc
--source include/have_innodb.inc
# --view-protocol fails due to MDEV-37119 for MDEV-32299
--source include/no_view_protocol.inc

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');

--ERROR ER_UNACCEPTABLE_MUTUAL_RECURSION
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 ER_UNACCEPTABLE_MUTUAL_RECURSION
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; 

drop table t1;


--echo # 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);


--echo # just WITH : s refers to t defined after s
--ERROR ER_NO_SUCH_TABLE
with 
 s(a) as (select t.a + 10 from t),
 t(a) as (select t1.a from t1)
select * from s;

--echo # 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;

--echo # 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;

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;


--echo #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;

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;
    
--echo # 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;


--echo # 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;

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); 

--echo # simple recursion with one anchor and one recursive select
--echo # 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;

--echo # simple recursion with one anchor and one recursive select
--echo # 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;

--echo # simple recursion with one anchor and one recursive select
--echo # 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;

--echo # 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;

--echo # 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;

--echo # 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;

--echo # simple recursion with one anchor and one recursive select
--echo # 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;

--echo # simple recursion with one anchor and one recursive select
--echo # 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;


--echo # 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);


--echo # 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;


--echo # 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;


--echo # 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;


--echo # 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;


--echo # 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;


--echo # 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;

--echo # 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;


--echo # 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;


--echo # 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;

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;


--echo # 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;


--echo # 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;


--echo # 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;
execute stmt1;

deallocate prepare stmt1;


--echo # 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;

select * from v1;

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;

select * from v2;

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;


--echo # 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;


--echo # 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;


--ERROR ER_NOT_STANDARD_COMPLIANT_RECURSIVE
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;

set standard_compliant_cte=0;

--ERROR ER_WITH_COL_WRONG_LIST
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;

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;

set standard_compliant_cte=1;

--ERROR ER_NOT_STANDARD_COMPLIANT_RECURSIVE
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;

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;

--ERROR ER_NOT_STANDARD_COMPLIANT_RECURSIVE
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;

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;

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;

--ERROR ER_NOT_STANDARD_COMPLIANT_RECURSIVE
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;

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;

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;

--echo # 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;


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;


--echo #
--echo # EXPLAIN FORMAT=JSON on a query where one recursive CTE uses another:
--echo #
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;

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;

--echo #
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;


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;

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;

drop table my_ancestors;

#
# MDEV-17967 Add a solution of the 8 queens problem to the regression test for CTE
#
# adapted to MariaDB from https://rosettacode.org/wiki/N-queens_problem#SQL
#
let $N=4; # 8 takes too long for a test
eval WITH RECURSIVE
  positions(i) AS (
    VALUES(0)
    UNION SELECT ALL
    i+1 FROM positions WHERE i < $N*$N-1
    ),
  solutions(board, n_queens) AS (
    SELECT REPEAT('-', $N*$N), 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 < $N
      AND substr(board,1,i) != '*'
      AND NOT EXISTS (
        SELECT 1 FROM positions WHERE
          substr(board,i+1,1) = '*' AND
            (
                i % $N = ps.i % $N OR
                i div $N = ps.i div $N OR
                i div $N + (i % $N) = ps.i div $N + (ps.i % $N) OR
                i div $N - (i % $N) = ps.i div $N - (ps.i % $N)
            )
        )
  )
SELECT regexp_replace(board,concat('(',REPEAT('.', $N),')'),'\\\\1\\n') n_queens FROM solutions WHERE n_queens = $N;

--echo #
--echo # MDEV-10883: execution of prepared statement from SELECT
--echo #             with recursive CTE that renames columns
--echo #

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;
deallocate prepare stmt;

--echo #
--echo # MDEV-10881: execution of prepared statement from
--echo #             CREATE ... SELECT, INSERT ... SELECT       
--echo #

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;

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;

drop table my_ancestors;

--echo #
--echo # MDEV-10933: WITH clause together with SELECT in parenthesis
--echo #             CREATE SELECT      
--echo #

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;
drop table my_ancestors;

drop table folks;

--echo #
--echo # MDEV-10372: [bb-10.2-mdev9864 tree] EXPLAIN with recursive CTE enters endless recursion
--echo #
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;

drop table t1;


--echo #
--echo # MDEV-10737: recursive union with several anchors at the end
--echo #

WITH RECURSIVE cte(n) AS
  ( SELECT n+1 FROM cte WHERE n < 5 UNION SELECT 1 UNION SELECT 1 )
SELECT * FROM cte;

--echo #
--echo # MDEV-10736: recursive definition with anchor over a table with blob
--echo #

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;
DROP TABLE t1;

--echo #
--echo # MDEV-10899: mergeable derived in the spec of recursive CTE
--echo #

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;

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;

drop table t1,t2;

--echo #
--echo # MDEV-11278: non-mergeable view in the spec of recursive CTE
--echo #

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;

drop view v1;
drop table t1,t2;


--echo #
--echo # MDEV-11259: recursive CTE with concatenation operation
--echo #

DROP TABLE IF EXISTS 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;
CREATE VIEW edges2 (a, b) AS 
 SELECT a, b FROM edges   UNION ALL   SELECT b, a FROM edges;

--sorted_result
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;

--sorted_result
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;

--sorted_result
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;

--sorted_result
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;

DROP VIEW edges2;
DROP TABLE edges;


--echo #
--echo # MDEV-11674: recursive CTE table that cannot be stored
--echo #             in a heap table
--echo #

create table t1 (id int, test_data varchar(36));

set @save_max_recursive_iterations= @@max_recursive_iterations;
set max_recursive_iterations= 200000;

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;

set max_recursive_iterations= @save_max_recursive_iterations;

--echo #
--echo # MDEV-10773: ANALYZE for query with recursive CTE
--echo #

--source include/analyze-format.inc
analyze format=json 
with recursive src(counter) as 
(select 1 
 union 
 select counter+1 from src where counter<10
) select * from src;

--echo #
--echo # mdev-12360: recursive reference in left operand of LEFT JOIN
--echo #

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;

drop table folks;

--echo #
--echo # mdev-12368: crash with mutually recursive CTE
--echo #             that arenot Standard compliant 
--echo #

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));

--ERROR ER_NOT_STANDARD_COMPLIANT_RECURSIVE
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;

drop table value_nodes, module_nodes, module_arguments, module_results;

--echo #
--echo # mdev-12375: query using one of two mutually recursive CTEs
--echo #             whose non-recursive part returns an empty set
--echo #

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;

drop table value_nodes, module_nodes, module_arguments, module_results;

--echo #
--echo # mdev-12519: recursive references in subqueries 
--echo #             

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;

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;

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;

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;
execute stmt;

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;

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;

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;
execute stmt;

deallocate prepare stmt;

drop table objects, modules, module_arguments, module_results;

set standard_compliant_cte=default;
select @@standard_compliant_cte;

--echo #
--echo # mdev-12554: impossible where in recursive select 
--echo #             

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;

DROP TABLE t1;

--echo #
--echo # mdev-12556: recursive execution uses Aria temporary tables 
--echo #             

CREATE TABLE t (c1 varchar(255), c2 tinytext);
INSERT INTO t VALUES ('a','a'),('b','b'),('c','c'),('d','d');

let $q1=
WITH RECURSIVE cte(f) AS (
  SELECT c1 FROM t
  UNION
  SELECT c1 FROM t, cte
) SELECT COUNT(*) FROM cte;

let $q2=
WITH RECURSIVE cte(f) AS (
  SELECT c2 FROM t
  UNION
  SELECT c2 FROM t, cte
) SELECT COUNT(*) FROM cte;

eval ANALYZE $q1;
eval $q1;

eval ANALYZE $q2;
eval $q2;

DROP TABLE t;

--echo #
--echo # mdev-12563: no recursive references on the top level of the CTE spec 
--echo #  

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;           

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;
           
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;           

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;           

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;           

set standard_compliant_cte=default;

DROP TABLE t;

--echo #
--echo # mdev-14184: recursive CTE embedded into CTE with multiple references 
--echo #

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;

--echo #
--echo # mdev-14629: a user-defined variable is defined by the recursive CTE
--echo #

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;

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;

--ERROR ER_UNACCEPTABLE_MUTUAL_RECURSION
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
);

drop table t1;

--echo #
--echo # mdev-14777: crash caused by the same as in mdev-14755
--echo #

--source include/have_sequence.inc

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;

drop table t1,t2,t3;

--echo #
--echo # mdev-14879: subquery with recursive reference in WHERE of CTE
--echo #

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;

set standard_compliant_cte=0;

let $q=
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;

eval $q;
eval explain extended $q;

set standard_compliant_cte=default;

drop table flights;

--echo #
--echo # MDEV-15162: Setting user variable in recursive CTE
--echo #

SET @c=1;

WITH RECURSIVE cte AS
	(SELECT 5
	UNION
	SELECT @c:=@c+1 FROM cte WHERE @c<3)
SELECT * FROM cte;

--echo #
--echo # MDEV-15575: using recursive cte with big_tables enabled
--echo #

set tmp_memory_table_size=0; # force on-disk tmp table

with recursive qn as
(select 123 as a union all select 1+a from qn where a<130)
select * from qn;

set tmp_memory_table_size=default;

--echo #
--echo # MDEV-15571: using recursive cte with big_tables enabled
--echo #

create table t1 (a bigint);
insert into t1 values(1);

set tmp_memory_table_size=0; # force on-disk tmp table

--error ER_DATA_OUT_OF_RANGE
with recursive qn as
(
  select  a from t1
  union all
  select a*2000 from qn where a<10000000000000000000
)
select * from qn;

set tmp_memory_table_size=default;

drop table t1;

--echo #
--echo # MDEV-15556: using recursive cte with big_tables enabled
--echo #             when recursive tables are accessed by key
--echo #

set tmp_memory_table_size=0; # force on-disk tmp table

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();

let $q=
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;

eval $q;
eval EXPLAIN $q;

DROP TABLE t1,t2;

set tmp_memory_table_size=default;

--echo #
--echo # MDEV-15840: recursive tables are accessed by key
--echo #             (the same problem as for MDEV-15556)
--echo #

--source include/have_sequence.inc

CREATE TABLE t1 (p1 text,k2 int, p2 text, k1 int);
INSERT INTO t1 select seq, seq, seq, seq from seq_1_to_1000;

DELIMITER |;
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 |

DELIMITER ;|
call getNums();

DROP PROCEDURE getNums;
DROP TABLE t1;

--echo #
--echo # MDEV-15894: aggregate/winfow functions in non-recorsive part
--echo #

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;

with recursive qn as
  (select rank() over (order by b) as a from t1 union
   select a from qn)
select * from qn;

drop table t1;

--echo #
--echo # MDEV-16086: tmp table for CTE is created as ARIA tables
--echo #

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;

DROP TABLE t1;

--echo #
--echo # MDEV-16212: recursive CTE with global ORDER BY
--echo #

--error ER_NOT_SUPPORTED_YET
set statement max_recursive_iterations = 2 for
WITH RECURSIVE qn AS (
SELECT 1 FROM dual UNION ALL
SELECT 1 FROM qn
ORDER BY (SELECT * FROM qn))
SELECT count(*) FROM qn;

--echo #
--echo # MDEV-15581: mix of ALL and DISTINCT UNION in recursive CTE
--echo #

create table t1(a int);
insert into t1 values(1),(2);
insert into t1 values(1),(2);

set @c=0, @d=0;
--error ER_NOT_SUPPORTED_YET
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;

drop table t1;

--echo #
--echo # MDEV-16629: function with recursive CTE using a base table
--echo #

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;

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();

DROP FUNCTION func;
DROP TABLE t1;

--echo #
--echo # MDEV-16661: function with recursive CTE using no base tables
--echo #             (fixed by the patch for MDEV-16629)
--echo #

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();

DROP FUNCTION func;

--echo #
--echo # MDEV-17024: two materialized CTEs using the same recursive CTE
--echo #

create table t1 (id int);
insert into t1 values (1), (2), (3);

let $q=
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;

eval $q;
eval explain extended $q;
eval prepare stmt from "$q";
execute stmt;
execute stmt;

create table t2 (c1 int, c2 int);
eval create procedure p() insert into t2 $q;
call p();
select * from t2;

let $q1=
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;

eval $q1;

let $q2=
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;

eval $q2;

let $q3=
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;

eval $q3;

let $q4=
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 cte2, cte1;

eval $q4;
eval explain extended $q4;
eval prepare stmt from "$q4";
execute stmt;
execute stmt;

drop procedure p;
drop table t2;

create table t2 (c1 int, c2 int);
eval create procedure p() insert into t2 $q4;
call p();
select * from t2;

drop procedure p;
drop table t1,t2;

--echo #
--echo # MDEV-17201: recursive part with LIMIT
--echo #

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;

DROP TABLE purchases, expired;

--echo #
--echo # MDEV-17635: Two recursive CTEs, the second using the first
--echo #

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;

--echo # 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;

--echo #
--echo # MDEV-17871: EXPLAIN for query with not used recursive cte
--echo #

create table t1 (a int);
insert into t1 values (2), (1), (4), (3);

let $rec_cte =
with recursive cte as
  (select * from t1 where a=1 union select a+1 from cte where a<3);

eval
explain extended
$rec_cte
select * from cte as t;

eval
$rec_cte
select * from cte as t;

eval
explain extended
$rec_cte
select * from t1 as t;

eval
$rec_cte
select * from t1 as t;

create table t2 ( i1 int, i2 int);
insert into t2 values (1,1),(2,2);

explain
with recursive cte as
 ( select * from t2 union select s1.* from t2 as s1, cte where s1.i1 = cte.i2 )
select * from t2 as t;

drop table t1,t2;


--echo #
--echo # MDEV-22042: ANALYZE of query using stored function and recursive CTE
--echo #

create table t1 (a1 varchar(20),a2 varchar(20)) engine=myisam;
insert into t1 values (1,1),(2,2),(3,3);

create table t2 (
a2 varchar(20) primary key, b1 varchar(20), key (b1)
) engine=myisam;
insert into t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7);
insert into t2 values (11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17);

delimiter $$;
create  function f1(id varchar(20)) returns varchar(50)
begin
  declare res  varchar (50);
  select a2 into res from t2 where a2=id and b1=1 limit 1;
  return res;
end$$
delimiter ;$$

let q=
select fv
from (select t1.a1, f1(t1.a2) fv from t1) dt
where (dt.a1) in (with recursive cte as (select a2 from t2 where a2='2'
   union select tt2.a2 from t2 tt2 join cte on tt2.b1=cte.a2)
select a2 from cte);

eval $q;
eval explain $q;
--source include/analyze-format.inc
eval analyze format=json $q;

drop function f1;
drop table t1,t2;

--echo #
--echo # MDEV-22748: two materialized CTEs using the same recursive CTE
--echo # (see also test case for MDEV-17024)
--echo #

CREATE TABLE t1 (YEAR int(4), d1 date , d2 date) ;
INSERT INTO t1 VALUES (2018,'2018-01-01','2018-09-20');
CREATE TABLE t2 (id int, tm date);
INSERT INTO t2 VALUES (1,'2018-08-30'),(2,'2018-08-30'),(3,'2018-08-30');
CREATE TABLE t3 (id int, tm date);
INSERT INTO t3 VALUES (1,'2018-08-30'),(2,'2018-08-30');

let $q=
WITH RECURSIVE
cte AS
  (SELECT  YEAR(t1.d1) AS YEAR, t1.d1 AS st, t1.d1 + INTERVAL 1 MONTH AS fn
     FROM t1
   UNION ALL
   SELECT YEAR(cte.st + INTERVAL 1 MONTH),
          cte.st + INTERVAL 1 MONTH,  t1.d2 + INTERVAL 1 DAY
     FROM cte JOIN t1
   WHERE cte.st + INTERVAL 1 MONTH < t1.d2 ),
cte2 AS (SELECT YEAR, COUNT(*)
        FROM cte JOIN t2 ON t2.tm BETWEEN cte.st AND cte.fn),
cte3 AS (SELECT YEAR, COUNT(*)
        FROM cte JOIN t3 ON t3.tm BETWEEN cte.st AND cte.fn)
SELECT t1.* FROM t1 JOIN cte2 USING (YEAR) JOIN cte3 USING (YEAR);

eval $q;
eval EXPLAIN EXTENDED $q;
eval PREPARE stmt FROM "$q";
EXECUTE stmt;
EXECUTE stmt;

CREATE TABLE t4 (YEAR int(4), d1 date , d2 date);
eval CREATE PROCEDURE p() INSERT INTO t4 $q;
CALL p();
SELECT * FROM t4;

DROP PROCEDURE p;
DROP TABLE t1,t2,t3,t4;

--echo #
--echo # MDEV-23619: recursive CTE used only in the second operand of UNION
--echo #

create table t1 (
  a bigint(10) not null auto_increment,
  b int(5) not null,
  c bigint(10) default null,
  primary key (a)
) engine myisam;
insert into t1 values
  (1,3,12), (2,7,15), (3,1,3), (4,3,1);

let $q=
with recursive r_cte as
( select * from t1 as s
  union
  select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t;

eval explain $q;
eval $q;
--source include/analyze-format.inc
eval analyze format=json $q;
eval prepare stmt from "$q";
execute stmt;
execute stmt;
deallocate prepare stmt;

--echo #checking hanging cte that uses a recursive cte
let $q1=
with h_cte as
( with recursive r_cte as
  ( select * from t1 as s
    union
    select t1.* from t1, r_cte as r where t1.c = r.a )
  select 0 as b FROM dual union all select b FROM r_cte as t)
select * from t1 as tt;

eval explain $q1;
eval $q1;
--source include/analyze-format.inc
eval analyze format=json $q1;
eval prepare stmt from "$q1";
execute stmt;
execute stmt;
deallocate prepare stmt;

drop table t1;

--echo #
--echo # MDEV-24019: query with recursive CTE when no default database is set
--echo #

create database dummy;
use dummy;
drop database dummy;

let $q=
with recursive a as
   (select 1 from dual union select * from a as r)
select * from a;

eval $q;

create database db1;
create table db1.t1 (a int);
insert into db1.t1 values (3), (7), (1);

let $q=
with recursive cte as
  (select * from db1.t1 union select * from (select * from cte) as t)
select * from cte;

eval $q;
eval explain $q;

eval prepare stmt from "$q";
execute stmt;
execute stmt;
deallocate prepare stmt;

drop database db1;

use test;

--echo #
--echo # MDEV-23406: query with mutually recursive CTEs when big_tables=1
--echo #

set @save_big_tables=@@big_tables;
set big_tables=1;

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);

let q=
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;

eval $q;
eval explain $q;
eval prepare stmt from "$q";
execute stmt;
execute stmt;
deallocate prepare stmt;

let $q=
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;

eval $q;
eval explain $q;
eval prepare stmt from "$q";
execute stmt;
execute stmt;
deallocate prepare stmt;

drop table folks;

set big_tables=@save_big_tables;

--echo #
--echo # MDEV-26135: execution of PS for query with hanging recursive CTE
--echo #

create table t1 (a int);
insert into t1 values (5), (7);
create table t2 (b int);
insert into t2 values (3), (7), (1);

let $q=
with recursive r as (select a from t1 union select a+1 from r where a < 10)
select * from t2;

eval $q;
eval prepare stmt from "$q";
execute stmt;
execute stmt;
deallocate prepare stmt;

drop table t1,t2;

--echo #
--echo # MDEV-26189: Unknown column reference within hanging recursive CTE
--echo #

create table t1 (a int);
insert into t1 values (3), (7), (1);

let $q1=
with recursive
  r as (select * from t1 union select s1.* from t1 as s1, r where s1.a = r.b)
select * from t1 as t;

--ERROR ER_BAD_FIELD_ERROR
eval $q1;
--ERROR ER_BAD_FIELD_ERROR
eval explain $q1;

eval create procedure sp1() $q1;
--ERROR ER_BAD_FIELD_ERROR
call sp1();
--ERROR ER_BAD_FIELD_ERROR
call sp1();

let $q2=
with recursive
  r as (select * from t1 union select s1.* from t1 as s1, r where s1.b = r.a)
select * from t1 as t;

--ERROR ER_BAD_FIELD_ERROR
eval $q2;
--ERROR ER_BAD_FIELD_ERROR
eval explain $q2;

eval create procedure sp2() $q2;
--ERROR ER_BAD_FIELD_ERROR
call sp2();
--ERROR ER_BAD_FIELD_ERROR
call sp2();

drop procedure sp1;
drop procedure sp2;

drop table t1;

--echo #
--echo # MDEV-26202: Recursive CTE used indirectly twice
--echo # (fixed by the patch forMDEV-26025)
--echo #

with recursive
  rcte as ( SELECT 1 AS a
            UNION ALL
            SELECT cast(a + 1 as unsigned int) FROM rcte WHERE a < 3),
  cte1 AS (SELECT a FROM rcte),
  cte2 AS (SELECT a FROM cte1),
  cte3 AS ( SELECT a FROM  cte2)
SELECT * FROM cte2, cte3;

--echo #
--echo # End of 10.2 tests
--echo #

--echo #
--echo # MDEV-14217 [db crash] Recursive CTE when SELECT includes new field
--echo #

CREATE TEMPORARY TABLE a_tbl (
  a VARCHAR(33) PRIMARY KEY,
  b VARCHAR(33)
);

INSERT INTO a_tbl VALUES ('block0', 'block0'), ('block1', NULL);

--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
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;
DROP TABLE a_tbl;

--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
WITH RECURSIVE x AS (SELECT 1,2 UNION ALL SELECT 1 FROM x) SELECT * FROM x;

--echo #
--echo # MDEV-15162: Setting user variable in recursive CTE
--echo #

SET @c=1;

WITH RECURSIVE cte AS
	(SELECT 5
	UNION
	SELECT @c:=@c+1 FROM cte WHERE @c<3)
SELECT * FROM cte;

--echo #
--echo # MDEV-14883: recursive references in operands of INTERSECT / EXCEPT
--echo #

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;

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;

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;

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;

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;

drop table flights, distances;

--echo #
--echo # MDEV-15159: Forced nullability of columns in recursive CTE
--echo #

WITH RECURSIVE cte AS (
	SELECT 1 AS a UNION ALL
	SELECT NULL FROM cte WHERE a IS NOT NULL)
SELECT * FROM cte;

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;

DROP TABLE t1;

--echo #
--echo # MDEV-12325 Unexpected data type and truncation when using CTE
--echo #

CREATE TABLE t1
(
  id INT, mid INT, name TEXT
);
INSERT INTO t1 VALUES (0,NULL,'Name'),(1,0,'Name1'),(2,0,'Name2'),(11,1,'Name11'),(12,1,'Name12');

let $query=
WITH RECURSIVE
cteReports (level, id, mid, name) AS
(
  SELECT 1, id, mid, name FROM t1 WHERE mid IS NULL
  UNION ALL
  SELECT r.level + 1, e.id, e.mid + 1000000000000, e.name FROM t1 e
  INNER JOIN cteReports r ON e.mid = r.id
)
SELECT
  level, id, mid, name,
  (SELECT name FROM t1 WHERE id= cteReports.mid) AS mname
FROM cteReports ORDER BY level, mid;

--error ER_WARN_DATA_OUT_OF_RANGE
--eval $query
--error ER_WARN_DATA_OUT_OF_RANGE
--eval create table t2 as $query;
--eval create table t2 ignore as $query;
show create table t2;
--error ER_WARN_DATA_OUT_OF_RANGE
--eval insert into t2 $query;
--eval insert ignore into t2 $query;
drop table t2;
set @@sql_mode="";
--eval $query
--eval create table t2 as $query;
show create table t2;
set @@sql_mode=default;
drop table t1,t2;

--echo #
--echo # MDEV-29361: Embedded recursive / non-recursive CTE within
--echo #             the scope of another embedded CTE with the same name
--echo #

create table t1 (a int);
insert into t1 values (4), (5);
create table t2 (a int);
insert into t2 values (6), (8);
create table t3 (a int);
insert into t3 values (1), (9);


with recursive
x as
(
  select a from t1 union select a+1 from x as r1 where a < 7
)
select * from x as s1;

with recursive
x as
(
  select a from t2
  union
  select a+2 from x as r2 where a < 10
)
select a from x as s2;

# All recursive CTEs with name x are embedded in in the definition of 'cte',
# without this embedding CTE the bug could not be reproduced

# two recursive CTEs with name x, the second CTE is in the scope
# of the first one, but does not use it
# before fix of this bug: wrong result set

with
cte as
(
  with recursive
  x as
  (
    select a from t1 union select a+1 from x as r1 where a < 7
  )
  select * from x as s1
  where s1.a in (
                 with recursive
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# two recursive CTEs with name x, the second CTE is in the scope of the first
# one, but does not use it; there are two non-recursive references to the latter
# before fix of this bug: wrong result set

with
cte as
(
  with recursive
  x(a) as
  (
    select a from t1 union select a+1 from x as r1 where a < 7
  )
  select s1.a from x as s1, x
  where s1.a = x.a and
        x.a in (
                 with recursive
                 x(a) as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r1 belongs to the definition of CTE x from non-RECURSIVE with clause
# before fix of this bug: infinite sequence of recursive calls

--error ER_NO_SUCH_TABLE
with
cte as
(
  with
  x as
  (
    select a from t1 union select a+1 from x as r1 where a < 7
  )
  select * from x as s1
  where s1.a in (
                 with recursive
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r2 belongs to the definition of CTE x from non-RECURSIVE with clause
# yet it is in the scope of another CTE with the same name
# before fix of this bug: crash in With_element::get_name()

with
cte as
(
  with recursive
  x as
  (
    select a from t1 union select a+1 from x as r1 where a < 7
  )
  select * from x as s1
  where s1.a in (
                 with
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r1 is in the definition of CTE x from non-RECURSIVE with clause, thus
# although x as r2 is in the scope of the first CTE x an error is expected
# before fix of this bug: crash in With_element::get_name()

--error ER_NO_SUCH_TABLE
with
cte as
(
  with
  x as
  (
    select a from t1 union select a+1 from x as r1 where a < 7
  )
  select * from x as s1
  where s1.a in (
                 with
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r2 belongs to the definition of CTE x from non-RECURSIVE with clause
# and in the scope of recursive CTE y, but does not use the latter
# before fix of this bug: crash in With_element::get_name()

--error ER_NO_SUCH_TABLE
with
cte as
(
  with recursive
  y as
  (
    select a from t1 union select a+1 from y as r1 where a < 7
  )
  select * from y as s1
  where s1.a in (
                 with
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r2 belongs to the definition of CTE x from non-RECURSIVE with clause
# and in the scope of non-recursive CTE y, but does not use the latter
# before fix of this bug: crash in With_element::get_name()

--error ER_NO_SUCH_TABLE
with
cte as
(
  with
  y(a) as
  (
    select a+5 from t1
  )
  select * from y as s1
  where s1.a in (
                 with
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# in the subquery of the embedding CTE cte:
# x as r1 is in the definition of CTE x from non-RECURSIVE with clause;
# x as t2 is in the definition of CTE x from RECURSIVE with clause;
# an error is expected to be reported for x as r1
# before fix of this bug: infinite sequence of recursive calls

--error ER_NO_SUCH_TABLE
with
cte as
(
  select (
           with
           x as
           (
             select a from x as r1
           )
           select * from x as s1
           where s1.a in (
                          with recursive
                          x as
                          (
                            select a from t2
                            union
                            select a+2 from x as r2 where a < 10
                          )
                          select a from x as s2
                        )
         ) as r
  from t3
)
select * from cte;


# in the subquery of the embedding CTE cte:
# x as r1 is in the definition of CTE x from non-RECURSIVE with clause, thus
# although x as r2 is in the scope of the first CTE x an error is expected
# before fix of this bug: crash in With_element::get_name()

--error ER_NO_SUCH_TABLE
with
cte as
(
  select (
           with
           x as
           (
             select a from x as r1
           )
           select * from x as s1
           where s1.a < 5 and
                 s1.a in (
                          with
                          x as
                          (
                            select a from t2
                            union
                            select a+2 from x as r2 where a < 10
                          )
                          select a from x as s2
                        )
         ) as r
  from t3
)
select * from cte;


# in the subquery of the embedding CTE cte:
# two recursive CTEs with name x, the second CTE is in the scope
# of the first one, but does not use it
# before fix of this bug: wrong result set

with
cte as
(
  select (
           with recursive
           x(a) as
           (
             select a+3 from t1 union select a+1 from x as r1 where a < 7
           )
           select * from x as s1
           where s1.a < 8 and
                 s1.a in (
                           with recursive
                           x(a) as
                           (
                             select a-2 from t2
                             union
                             select a+1 from x as r2 where a < 10
                           )
                           select a from x as s2
                         )
         ) as r
  from t3
)
select * from cte;


# in the subquery of the embedding CTE cte:
# two recursive CTEs with name x, the second CTE is in the scope
# of the first one, but does not use it
# before fix of this bug: Subquery returns more than 1 row

with
cte as
(
  select (
           with recursive
           x as
           (
             select a from t1 union select a+1 from x as r1 where a < 7
           )
           select * from x as s1
           where s1.a in (
                           with recursive
                           x as
                           (
                             select a from t2
                             union
                             select a+2 from x as r2 where a < 10
                           )
                           select a from x as s2
                         )
         ) as r
  from t3
)
select * from cte;


create table x (a int);
insert into x values (3), (7), (1), (5), (6);


# in the subquery of the embedding CTE cte:
# one non-recursive CTEs with name x using table t in a subquery, the second
# CTE x is recursive and is in the scope of the first one, but does not use it;
# the query uses both CTE with name x.
# before fix of this bug: infinite sequence of recursive calls

--error ER_SUBQUERY_NO_1_ROW
with
cte as
(
  select (
           with
           x as
           (
             select ( select a from x as r1 ) as a from t1
           )
           select * from x as s1
           where s1.a in (
                           with recursive
                           x as
                           (
                             select a from t2
                             union
                             select a+2 from x as r2 where a < 10
                           )
                           select a from x s2
                         )
         ) as r
  from t3
)
select * from cte;


# in the subquery of the embedding CTE cte:
# one non-recursive CTEs with name x using table t, the second CTE x is
# recursive and is in the scope of the first one, but does not use it;
# the query uses only the second CTE with name x.
# before fix of this bug: Subquery returns more than 1 row

with
cte as
(
  select (
           with
           x as
           (
             select ( select a from x ) as a from t1
           )
           select exists (
                           with recursive
                           x as
                           (
                             select a from t2
                             union
                             select a+2 from x as r2 where a < 10
                           )
                           select a from x
                         )
         ) as r
  from t3
)
select * from cte;


# in the subquery of the embedding CTE cte embedded in the CTE cte_e
# one non-recursive CTEs with name x uses table t1, the second CTE x is
# recursive and is in the scope of the first one, but does not use it;
# CTE cte uses only the second CTE with name x;
# the query has two refeences to cte_e
# before fix of this bug: infinite sequence of recursive calls

with
cte_e as
(
  with
  cte as
  (
    select (
             with
             x as
             (
               select ( select a from x ) from t1
             )
             select exists (
                             with recursive
                             x as
                             (
                               select a from t2
                               union
                               select a+2 from x as r2 where a < 10
                             )
                             select a from x
                           )
           ) as r
    from t3
  )
  select * from cte
)
select s1.*, s2.*  from cte_e as s1, cte_e as s2;


# check : with base table x all queries abobe that returned error
# message ER_NO_SUCH_TABLE now return proper result sets

with
x as
(
  select a from t1 union select a+1 from x as r1 where a < 7
)
select * from x as s1;

with
x as
(
  select a from t2
  union
  select a+2 from x as r2 where a < 10
)
select a from x as s2;

with recursive
x as
(
  select a from t1 union select a+1 from x as r1 where a < 7
)
select * from x as s1;

with recursive
x as
(
  select a from t2
  union
  select a+2 from x as r2 where a < 10
)
select a from x as s2;


# x as r1 is bound to table x, x as s1 is bound to the first CTE x
# x as r2 and x as s2 are bound to the second CTE x
# before fix of this bug: infinite sequence of recursive calls

with
cte as
(
  with
  x as
  (
    select a from t1 union select a+1 from x as r1 where a < 7
  )
  select * from x as s1
  where s1.a in (
                 with recursive
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r1 is bound to table x, x as s1 is bound to the first CTE x
# x as r1 is bound to the first CTE x, x as s2 is bound to the second CTE x
# before fix of this bug: crash in With_element::get_name()

with
cte as
(
  with
  x as
  (
    select a from t1 union select a+1 from x as r1 where a < 7
  )
  select * from x as s1
  where s1.a in (
                 with
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r2 is bound to table x, x as s2 is bound to CTE x
# before fix of this bug: crash in With_element::get_name()

with
cte as
(
  with recursive
  y as
  (
    select a from t1 union select a+1 from y as r1 where a < 7
  )
  select * from y as s1
  where s1.a in (
                 with
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r2 is bound to table x, x as s2 is bound to CTE x
# before fix of this bug: crash in With_element::get_name()

with
cte as
(
  with
  y(a) as
  (
    select a+5 from t1
  )
  select * from y as s1
  where s1.a in (
                 with
                 x as
                 (
                   select a from t2
                   union
                   select a+2 from x as r2 where a < 10
                 )
                 select a from x as s2
               )
)
select * from cte;


# x as r1 is bound to table x, x as s1 is bound to the first CTE x
# x as r2 and x as s2 are bound to the second CTE x
# before fix of this bug: infinite sequence of recursive calls

with
cte as
(
  select (
           with
           x as
           (
             select a from x as r1
           )
           select * from x as s1
           where s1.a in (
                          with
                          recursive x as
                          (
                            select a from t2
                            union
                            select a+2 from x as r2 where a < 10
                          )
                          select a from x as s2
                        )
         ) as r
  from t3
)
select * from cte;


# x as r1 is bound to table x, x as s1 is bound to the first CTE x
# x as r2 is bound to the first CTE x, x as s2 is bound to the second CTE x
# before fix of this bug: crash in With_element::get_name()

with
cte as
(
  select (
           with
           x as
           (
             select a from x as r1
           )
           select * from x as s1
           where s1.a < 5 and
                 s1.a in (
                          with
                          x as
                          (
                            select a from t2
                            union
                            select a+2 from x as r2 where a < 10
                          )
                          select a from x as s2
                        )
         ) as r
  from t3
)
select * from cte;


drop table t1,t2,t3,x;

--echo #
--echo # MDEV-30248: Embedded non-recursive CTE referring to base table 'x'
--echo #             within a CTE with name 'x' used in a subquery from
--echo #             select list of another CTE
--echo #

CREATE TABLE x (a int) ENGINE=MyISAM;
INSERT INTO x VALUES (3),(7),(1);
CREATE TABLE t1 (b int) ENGINE=MYISAM;
INSERT INTO t1 VALUES (1);

let $q1=
WITH cte AS
(
  SELECT
    (
      WITH x AS
      (WITH x AS (SELECT a FROM x AS t) SELECT 1 AS b)
      SELECT b FROM x AS r
    ) AS c
)
SELECT cte.c FROM cte;
eval $q1;

let $q2=
WITH cte AS
(
  SELECT
    (
      WITH x AS
      (WITH x AS (SELECT a FROM x AS t) SELECT b FROM t1)
      SELECT b FROM x AS r
    ) AS c
)
SELECT cte.c FROM cte;
eval $q2;

let $q3=
WITH cte AS
(
  SELECT
    (
      WITH x AS
      (WITH y AS (SELECT a FROM x AS t) SELECT b FROM t1)
      SELECT b FROM x AS r
    ) AS c
)
SELECT cte.c FROM cte;
eval $q3;


let $q4=
WITH cte AS
(
  SELECT
    (
      WITH x AS
      (WITH y(b) AS (SELECT a FROM x AS t LIMIT 1) SELECT b FROM y)
      SELECT b FROM x AS r
    ) AS c
)
SELECT cte.c FROM cte;
eval $q4;

let $q5=
WITH cte AS
(
  SELECT
    (
      WITH x AS
      (WITH x(b) AS (SELECT a FROM x AS t LIMIT 1) SELECT b FROM x)
      SELECT b FROM x AS r
    ) AS c
)
SELECT cte.c FROM cte;
eval $q5;

let $q6=
WITH x AS
(
  SELECT
    (
      WITH x AS
      (WITH x AS (SELECT a FROM x AS t) SELECT 1 AS b)
      SELECT b FROM x AS r
    ) AS c
)
SELECT x.c from x;
eval $q6;

let $q7=
WITH cte AS
(
  SELECT
    (
      WITH x AS
      (WITH x AS (SELECT a FROM x AS t) SELECT 2 AS b)
      SELECT r1.b FROM x AS r1, x AS r2 WHERE r1.b=r2.b
    ) AS c
)
SELECT cte.c from cte;
eval $q7;


DROP TABLE x;

--ERROR ER_NO_SUCH_TABLE
eval $q1;
--ERROR ER_NO_SUCH_TABLE
eval $q2;
--ERROR ER_NO_SUCH_TABLE
eval $q3;
--ERROR ER_NO_SUCH_TABLE
eval $q4;
--ERROR ER_NO_SUCH_TABLE
eval $q5;
--ERROR ER_NO_SUCH_TABLE
eval $q6;
--ERROR ER_NO_SUCH_TABLE
eval $q7;

DROP TABLE t1;

--echo #
--echo # End of 10.3 tests
--echo #

--echo #
--echo # MDEV-26108: Recursive CTE embedded into another CTE which is used twice
--echo #

create table t1 (a int);
insert into t1 values (5), (7);

with cte_e as (
  with recursive cte_r as (
    select a from t1 union select a+1 as a from cte_r r where a < 10
  ) select * from cte_r
) select * from cte_e s1, cte_e s2 where s1.a=s2.a;

drop table t1;

--echo #
--echo # MDEV-20010 Equal on two RANK window functions create wrong result
--echo #

create table t1 (a int, b int) engine= innodb;
insert into t1 values (4, -2), (3, -1);

SELECT RANK() OVER (ORDER BY D.C) = RANK() OVER (ORDER BY B.a) FROM
(SELECT 5 AS C FROM t1) as D, (SELECT t1.b AS A FROM t1) AS B;

select b, rank() over (order by c) , rank() over (order by dt1.b)
from
(select 5 as c from t1) as dt,
(select b from t1) as dt1;

select b, rank() over (order by c) , rank() over (order by dt1.b),
rank() over (order by c) = rank() over (order by dt1.b)
from
(select 5 as c from t1) as dt,
(select b from t1) as dt1;

alter table t1 engine=myisam;
select b, rank() over (order by c) , rank() over (order by dt1.b)
from
(select 5 as c from t1) as dt,
(select b from t1) as dt1;

create view v1 as select b,5 as c from t1;
select b, rank() over (order by c) from v1 order by b;

drop view v1;
drop table t1;

--echo # End of 10.4 tests

--echo #
--echo # MDEV-32308: Server crash on cleanup of
--echo # non-fully-constructed-due-to-an-error CTE
--echo #
--error ER_BAD_FIELD_ERROR
SELECT ( WITH RECURSIVE x AS ( WITH x AS ( SELECT 1 FROM t14 ) SELECT x ) , t14 AS ( SELECT 1 UNION SELECT 'x' FROM x ) SELECT x FROM x WHERE ( SELECT x FROM x ) ) ;

--echo #
--echo # MDEV-32299 Segfault when preparing unreferenced select in recursive CTE
--echo #

# As in bug report
--error ER_BAD_FIELD_ERROR
SELECT ( WITH RECURSIVE x AS ( SELECT * FROM ( SELECT UTC_TIMESTAMP FROM ( SELECT ( WITH x AS ( WITH x AS ( SELECT * FROM x ) SELECT 1 ) SELECT 1 ) ) x ) x UNION SELECT NULL ) ( SELECT x FROM x ) ) ;

#0  0x00005555569dff7b in TABLE_LIST::reset_const_table (this=0x7fffe0019938) at ../src/sql/table.cc:9615
#1  0x00005555569dffd4 in TABLE_LIST::reset_const_table (this=0x7fffe001a8c0) at ../src/sql/table.cc:9622
--error ER_BAD_FIELD_ERROR
select (
  with recursive x as (
    select * from (
      select utc_timestamp
      from (
        select (
          with x as (
            with x as (
              select * from x
            )
            select 1
          )
          select 1
        ) s
      ) y
    ) z

    union

    select null
  )
  (select x from x)
);

#6  0x00007ffff7639206 in __assert_fail (assertion=0x555555e121b6 "table_ref->table || table_ref->view", file=0x555555cdf138 "../src/sql/table.cc", line=7305, function=0x555555e30e24 "void Field_iterator_table_ref::set_field_iterator()") at ./assert/assert.c:101
#7  0x00005555569da013 in Field_iterator_table_ref::set_field_iterator (this=0x7ffff0a9afc0) at ../src/sql/table.cc:7305
select (
  with recursive r as (
    select * from (
      with a as (
          select * from r
      )
      select 1
    ) y

    union

    select 1
  )
  (select * from r)
);

# Field resolution in unreferenced:
create table t1 (x int);

with recursive r as (
  select f1 from (
    with a as (
        select x from t1
    )
    select 1 as f1
  ) y

  union

  select null
)
(select * from r);

--error ER_BAD_FIELD_ERROR
with recursive r as (
  select f1 from (
    with a as (
        select f2 from t1
    )
    select 1 as f1
  ) y

  union

  select null
)
(select * from r);

drop table t1;

with recursive r as (
  select 1 as f1

  union

  select f1 from (
    with a as (
        select f1 from r
    )
    select 1 as f1
  ) y
)
(select f1 from r);

--error ER_BAD_FIELD_ERROR
with recursive r as (
  select 1 as f1

  union

  select f1 from (
    with a as (
        select f2 from r
    )
    select 1 as f1
  ) y
)
(select f1 from r);


--echo # End of 10.6 tests

--echo #
--echo # MDEV-32724 Segmentation fault due to Deep Recursion in table.cc and sql_lex.cc
--echo #
--error ER_RECURSIVE_WITHOUT_ANCHORS
with recursive r (y) as (
  with r (z) as (select 1 from r) select 1 from r
  union all
  select y from r)
select y from r;

--echo # r2 CTE is the anchor for r (original behavior):
with recursive r (y) as (
  with recursive r2 (z) as (
    select z + 1 from r2 where z < 2
    union all
    select 1)
  select z from r2
  union all
  select y * 2 from r where y < 10)
select y from r;

--echo # It is different with the name clash,
--echo # select y * 2 from r is attached to inner r:
--error ER_BAD_FIELD_ERROR
with recursive r (y) as (
  with recursive r (z) as (
    select z + 1 from r where z < 2
    union all
    select 1)
  select z from r
  union all
  select y * 2 from r where y < 10)
select y from r;

--echo # The whole set of SELECTs is attached to CTE:
with recursive r (z) as (
  select z + 1 from r where z < 2
  union all
  select 1)
select z from r
union all
select z * 2 from r where z < 10;

--echo # In this case no outer recursion can occur as every r
--echo # is taken by the inner recursive CTE:
with recursive r (y) as (
  with recursive r (z) as (
    select z + 1 from r where z < 2
    union all
    select 1)
  select z from r
  union all
  select z * 2 from r where z < 10)
select y from r;

--echo # End of 10.11 tests

Youez - 2016 - github.com/yon3zu
LinuXploit