1969 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1969 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 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
 | |
| #MXS qc_sqlite
 | |
| #MXS qc_get_function_info     : ERR: =(folks.name, folks.father, folks.id, folks.mother, mother.child_id, ancestors.id, father.child_id) != =(mother.child_id, ancestors.id, folks.father, folks.id, folks.mother, mother.id, father.child_id, name)
 | |
| #MXS The reported function arguments to '=' are disjoint. The relevant are there though (folks.*).
 | |
| #MXS with recursive 
 | |
| #MXS ancestors(id,name,dob)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   with 
 | |
| #MXS   father(child_id,id,name,dob)
 | |
| #MXS   as
 | |
| #MXS   (
 | |
| #MXS     select folks.id, f.id, f.name, f.dob
 | |
| #MXS       from folks, folks f
 | |
| #MXS         where folks.father=f.id 
 | |
| #MXS         
 | |
| #MXS   ),
 | |
| #MXS   mother(child_id,id,name,dob)
 | |
| #MXS   as
 | |
| #MXS   (
 | |
| #MXS     select folks.id, m.id, m.name, m.dob
 | |
| #MXS       from folks, folks m
 | |
| #MXS         where folks.mother=m.id 
 | |
| #MXS         
 | |
| #MXS   )  
 | |
| #MXS   select folks.id, folks.name, folks.dob
 | |
| #MXS     from folks
 | |
| #MXS       where name='Me'
 | |
| #MXS   union 
 | |
| #MXS   select f.id, f.name, f.dob
 | |
| #MXS     from ancestors a, father f
 | |
| #MXS       where f.child_id=a.id
 | |
| #MXS   union 
 | |
| #MXS   select m.id, m.name, m.dob
 | |
| #MXS     from ancestors a, mother m
 | |
| #MXS       where m.child_id=a.id
 | |
| #MXS   
 | |
| #MXS )
 | |
| #MXS 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
 | |
| #MXS qc_mysqlembedded and qc_sqlite disagree in the used fields.
 | |
| #MXS Both return correctly the folks fields (i.e. the real ones),
 | |
| #MXS but disagree on the fields of the CTE tables.
 | |
| #
 | |
| #MXS with recursive
 | |
| #MXS ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
 | |
| #MXS                  w_id, w_name, w_dob, w_father, w_mother)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select h.*, w.*
 | |
| #MXS     from folks h, folks w,  coupled_ancestors a
 | |
| #MXS       where a.father = h.id AND a.mother = w.id
 | |
| #MXS   union 
 | |
| #MXS   select h.*, w.*
 | |
| #MXS     from folks v, folks h, folks w
 | |
| #MXS       where v.name = 'Me' and
 | |
| #MXS             (v.father = h.id AND v.mother= w.id)
 | |
| #MXS ),
 | |
| #MXS coupled_ancestors (id, name, dob, father, mother)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select h_id, h_name, h_dob, h_father, h_mother
 | |
| #MXS     from ancestor_couples
 | |
| #MXS   union all
 | |
| #MXS   select w_id, w_name, w_dob, w_father, w_mother
 | |
| #MXS     from ancestor_couples
 | |
| #MXS )
 | |
| #MXS select h_name, h_dob, w_name, w_dob
 | |
| #MXS   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
 | |
| #MXS qc_mysqlembedded and qc_sqlite disagree in the used fields.
 | |
| #MXS Both return correctly the folks fields (i.e. the real ones),
 | |
| #MXS but disagree on the fields of the CTE tables.
 | |
| #
 | |
| #MXS with recursive
 | |
| #MXS ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
 | |
| #MXS                  w_id, w_name, w_dob, w_father, w_mother)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select h.*, w.*
 | |
| #MXS     from folks h, folks w,  coupled_ancestors a
 | |
| #MXS       where a.father = h.id AND a.mother = w.id
 | |
| #MXS ),
 | |
| #MXS coupled_ancestors (id, name, dob, father, mother)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select * 
 | |
| #MXS     from folks 
 | |
| #MXS       where name = 'Me'
 | |
| #MXS   union all
 | |
| #MXS   select h_id, h_name, h_dob, h_father, h_mother
 | |
| #MXS     from ancestor_couples
 | |
| #MXS   union all
 | |
| #MXS   select w_id, w_name, w_dob, w_father, w_mother
 | |
| #MXS     from ancestor_couples
 | |
| #MXS )
 | |
| #MXS select h_name, h_dob, w_name, w_dob
 | |
| #MXS   from ancestor_couples;
 | |
| 
 | |
| --echo # mutual recursion with one select in the first definition
 | |
| #MXS qc_mysqlembedded and qc_sqlite disagree in the used fields.
 | |
| #MXS Both return correctly the folks fields (i.e. the real ones),
 | |
| #MXS but disagree on the fields of the CTE tables.
 | |
| #
 | |
| #MXS with recursive
 | |
| #MXS ancestor_couple_ids(h_id, w_id)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select a.father, a.mother
 | |
| #MXS     from coupled_ancestors a
 | |
| #MXS       where a.father is not null and a.mother is not null
 | |
| #MXS ),
 | |
| #MXS coupled_ancestors (id, name, dob, father, mother)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select * 
 | |
| #MXS     from folks 
 | |
| #MXS       where name = 'Me'
 | |
| #MXS   union all
 | |
| #MXS   select p.*
 | |
| #MXS     from folks p, ancestor_couple_ids fa
 | |
| #MXS       where p.id = fa.h_id
 | |
| #MXS   union all
 | |
| #MXS   select p.*
 | |
| #MXS     from folks p, ancestor_couple_ids ma
 | |
| #MXS       where p.id = ma.w_id
 | |
| #MXS )
 | |
| #MXS select *
 | |
| #MXS   from ancestor_couple_ids;
 | |
| 
 | |
| 
 | |
| --echo # join of a mutually recursive table with base tables
 | |
| #MXS qc_mysqlembedded and qc_sqlite disagree in the used fields.
 | |
| #MXS Both return correctly the folks fields (i.e. the real ones),
 | |
| #MXS but disagree on the fields of the CTE tables.
 | |
| #
 | |
| #MXS with recursive
 | |
| #MXS ancestor_couple_ids(h_id, w_id)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select a.father, a.mother
 | |
| #MXS     from coupled_ancestors a
 | |
| #MXS       where a.father is not null and a.mother is not null
 | |
| #MXS ),
 | |
| #MXS coupled_ancestors (id, name, dob, father, mother)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select * 
 | |
| #MXS     from folks 
 | |
| #MXS       where name = 'Me'
 | |
| #MXS   union all
 | |
| #MXS   select p.*
 | |
| #MXS     from folks p, ancestor_couple_ids fa
 | |
| #MXS       where p.id = fa.h_id
 | |
| #MXS   union all
 | |
| #MXS   select p.*
 | |
| #MXS     from folks p, ancestor_couple_ids ma
 | |
| #MXS       where p.id = ma.w_id
 | |
| #MXS )
 | |
| #MXS select h.name, h.dob, w.name, w.dob
 | |
| #MXS   from ancestor_couple_ids c, folks h, folks w
 | |
| #MXS     where c.h_id = h.id and c.w_id= w.id;
 | |
| 
 | |
| 
 | |
| --echo # join of two mutually recursive tables
 | |
| #MXS qc_mysqlembedded and qc_sqlite disagree in the used fields.
 | |
| #MXS Both return correctly the folks fields (i.e. the real ones),
 | |
| #MXS but disagree on the fields of the CTE tables.
 | |
| #
 | |
| #MXS with recursive
 | |
| #MXS ancestor_couple_ids(h_id, w_id)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select a.father, a.mother
 | |
| #MXS     from coupled_ancestors a
 | |
| #MXS       where a.father is not null and a.mother is not null
 | |
| #MXS ),
 | |
| #MXS coupled_ancestors (id, name, dob, father, mother)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select * 
 | |
| #MXS     from folks 
 | |
| #MXS       where name = 'Me'
 | |
| #MXS   union all
 | |
| #MXS   select p.*
 | |
| #MXS     from folks p, ancestor_couple_ids fa
 | |
| #MXS       where p.id = fa.h_id
 | |
| #MXS   union all
 | |
| #MXS   select p.*
 | |
| #MXS     from folks p, ancestor_couple_ids ma
 | |
| #MXS       where p.id = ma.w_id
 | |
| #MXS )
 | |
| #MXS select h.name, h.dob, w.name, w.dob
 | |
| #MXS   from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w
 | |
| #MXS     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;
 | |
| 
 | |
| #MXS qc_sqlite does not handle "SET STATEMENT ... FOR ..."
 | |
| #MXS 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;
 | |
| 
 | |
| #MXS qc_sqlite does not handle "SET STATEMENT ... FOR ..."
 | |
| #MXS set statement standard_compliant_cte=0 for
 | |
| #MXS qc_mysqlembedded reports a.id, although a actually is ancestor_ids.
 | |
| #MXS with recursive
 | |
| #MXS ancestor_ids (id)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select father from folks where name = 'Me'
 | |
| #MXS   union
 | |
| #MXS   select mother from folks where name = 'Me'
 | |
| #MXS   union
 | |
| #MXS   select father from folks left join ancestor_ids a on folks.id = a.id
 | |
| #MXS   union
 | |
| #MXS   select mother from folks left join ancestor_ids a on folks.id = a.id
 | |
| #MXS ),
 | |
| #MXS ancestors 
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select p.* from folks as p, ancestor_ids as a
 | |
| #MXS     where p.id = a.id
 | |
| #MXS )
 | |
| #MXS 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;
 | |
| 
 | |
| #MXS qc_sqlite does not handle "SET STATEMENT ... FOR ..."
 | |
| #MXS 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;
 | |
| 
 | |
| #MXS qc_sqlite does not handle "SET STATEMENT ... FOR ..."
 | |
| #MXS 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;
 | |
| 
 | |
| --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 #
 | |
| 
 | |
| #MXS qc_sqlite cannot parse this
 | |
| #MXS qc_parse                 : INF: QC_QUERY_PARSED != QC_QUERY_PARTIALLY_PARSED
 | |
| #MXS create table my_ancestors
 | |
| #MXS (
 | |
| #MXS with recursive
 | |
| #MXS ancestor_ids (id)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select father from folks where name = 'Me'
 | |
| #MXS   union
 | |
| #MXS   select mother from folks where name = 'Me'
 | |
| #MXS   union
 | |
| #MXS   select father from folks, ancestor_ids a  where folks.id = a.id
 | |
| #MXS   union
 | |
| #MXS   select mother from folks, ancestor_ids a  where folks.id = a.id
 | |
| #MXS )
 | |
| #MXS select p.* from folks as p, ancestor_ids as a where p.id = a.id
 | |
| #MXS );
 | |
| 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);
 | |
| 
 | |
| #MXS qc_mysqlembedded
 | |
| #MXS qc_get_function_info     : ERR: <(QC_USED_IN_WHERE) != <(QC_USED_IN_WHERE) >(QC_USED_IN_WHERE)
 | |
| #
 | |
| #MXS create view v1 as
 | |
| #MXS   select a from t2 where a < 3
 | |
| #MXS   union
 | |
| #MXS   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
 | |
| #MXS qc_mysqlembedded reports e. although e. is edges.
 | |
| #MXS WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
 | |
| #MXS ( SELECT a, b, 1 AS distance,
 | |
| #MXS    concat(a, '.', b, '.') AS path_string
 | |
| #MXS   FROM edges
 | |
| #MXS  
 | |
| #MXS   UNION ALL
 | |
| #MXS  
 | |
| #MXS   SELECT tc.a, e.b, tc.distance + 1,
 | |
| #MXS   concat(tc.path_string, e.b, '.') AS path_string
 | |
| #MXS   FROM edges AS e
 | |
| #MXS     JOIN transitive_closure AS tc
 | |
| #MXS       ON e.a = tc.b
 | |
| #MXS   WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
 | |
| #MXS )
 | |
| #MXS SELECT * FROM transitive_closure
 | |
| #MXS ORDER BY a, b, distance;
 | |
| 
 | |
| --sorted_result
 | |
| #MXS qc_mysqlembedded reports e. although e. is edges.
 | |
| #MXS WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
 | |
| #MXS ( SELECT a, b, 1 AS distance,
 | |
| #MXS          concat(a, '.', b, '.') AS path_string
 | |
| #MXS   FROM edges
 | |
| #MXS  WHERE a = 1
 | |
| #MXS  
 | |
| #MXS   UNION ALL
 | |
| #MXS  
 | |
| #MXS   SELECT tc.a, e.b, tc.distance + 1,
 | |
| #MXS          concat(tc.path_string, e.b, '.') AS path_string
 | |
| #MXS   FROM edges AS e
 | |
| #MXS   JOIN transitive_closure AS tc ON e.a = tc.b
 | |
| #MXS  WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
 | |
| #MXS )
 | |
| #MXS   SELECT * FROM transitive_closure
 | |
| #MXS    WHERE b = 6
 | |
| #MXS ORDER BY a, b, distance;
 | |
| 
 | |
| --sorted_result
 | |
| #MXS qc_mysqlembedded reports e. although e. is edges2.
 | |
| #MXS WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
 | |
| #MXS ( SELECT  a, b, 1 AS distance,
 | |
| #MXS           concat(a, '.', b, '.') AS path_string
 | |
| #MXS   FROM edges2
 | |
| #MXS  
 | |
| #MXS   UNION ALL
 | |
| #MXS  
 | |
| #MXS   SELECT tc.a, e.b, tc.distance + 1,
 | |
| #MXS   concat(tc.path_string, e.b, '.') AS path_string
 | |
| #MXS   FROM edges2 AS e
 | |
| #MXS     JOIN transitive_closure AS tc ON e.a = tc.b
 | |
| #MXS   WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
 | |
| #MXS )
 | |
| #MXS SELECT * FROM transitive_closure
 | |
| #MXS ORDER BY a, b, distance;
 | |
| 
 | |
| --sorted_result
 | |
| #MXS qc_mysqlembedded reports e. although e. is edges2.
 | |
| #MXS WITH RECURSIVE transitive_closure(a, b, distance, path_string)
 | |
| #MXS AS
 | |
| #MXS ( SELECT a, b, 1 AS distance,
 | |
| #MXS          concat(a, '.', b, '.') AS path_string
 | |
| #MXS   FROM edges2
 | |
| #MXS  
 | |
| #MXS   UNION ALL
 | |
| #MXS  
 | |
| #MXS   SELECT tc.a, e.b, tc.distance + 1,
 | |
| #MXS          concat(tc.path_string, e.b, '.') AS path_string
 | |
| #MXS   FROM edges2 AS e
 | |
| #MXS   JOIN transitive_closure AS tc ON e.a = tc.b
 | |
| #MXS  WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
 | |
| #MXS )
 | |
| #MXS SELECT a, b, min(distance) AS dist FROM transitive_closure
 | |
| #MXS GROUP BY a, b
 | |
| #MXS 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));
 | |
| 
 | |
| 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;
 | |
| 
 | |
| --echo #
 | |
| --echo # MDEV-10773: ANALYZE for query with recursive CTE
 | |
| --echo #
 | |
| 
 | |
| --source include/analyze-format.inc
 | |
| 
 | |
| #MXS qc_sqlite cannot parse this
 | |
| #MXS qc_parse                 : INF: QC_QUERY_PARSED != QC_QUERY_INVALID
 | |
| #MXS analyze format=json 
 | |
| #MXS with recursive src(counter) as 
 | |
| #MXS (select 1 
 | |
| #MXS  union 
 | |
| #MXS  select counter+1 from src where counter<10
 | |
| #MXS ) 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); 
 | |
| 
 | |
| #MXS qc_mysqlembedded reports a. although a. is ancestor_ids.
 | |
| #MXS with recursive
 | |
| #MXS ancestor_ids (id)
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select father from folks where name = 'Me'
 | |
| #MXS   union
 | |
| #MXS   select mother from folks where name = 'Me'
 | |
| #MXS   union
 | |
| #MXS   select father from ancestor_ids as a left join folks on folks.id = a.id
 | |
| #MXS   union
 | |
| #MXS   select mother from ancestor_ids as a left join folks on folks.id = a.id
 | |
| #MXS ),
 | |
| #MXS ancestors 
 | |
| #MXS as
 | |
| #MXS (
 | |
| #MXS   select p.* from folks as p, ancestor_ids as a
 | |
| #MXS     where p.id = a.id
 | |
| #MXS )
 | |
| #MXS 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');
 | |
| 
 | |
| #MXS qc_sqlite does not handle "SET STATEMENT ... FOR ..."
 | |
| #MXS set statement max_recursive_iterations=2, standard_compliant_cte=0 for
 | |
| #MXS qc_mysqlembedded thinks only module_arguments.m is an argument to isNull
 | |
| #MXS while qc_sqlite thinks reached_values.v is.
 | |
| #MXS with recursive
 | |
| #MXS reached_values as 
 | |
| #MXS (
 | |
| #MXS   select v from value_nodes where v in ('v3','v7','v9')
 | |
| #MXS   union
 | |
| #MXS   select module_results.v from module_results, applied_modules
 | |
| #MXS      where module_results.m = applied_modules.m
 | |
| #MXS ),
 | |
| #MXS applied_modules as
 | |
| #MXS (
 | |
| #MXS   select * from module_nodes where 1=0
 | |
| #MXS   union
 | |
| #MXS   select module_nodes.m
 | |
| #MXS   from
 | |
| #MXS     module_nodes
 | |
| #MXS     left join
 | |
| #MXS     ( 
 | |
| #MXS       module_arguments
 | |
| #MXS       left join
 | |
| #MXS       reached_values
 | |
| #MXS       on module_arguments.v = reached_values.v
 | |
| #MXS      )
 | |
| #MXS      on reached_values.v is null and
 | |
| #MXS      module_nodes.m = module_arguments.m
 | |
| #MXS   where module_arguments.m is null
 | |
| #MXS )
 | |
| #MXS 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;
 | |
| 
 | 
