mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
7498978e6a
UNION ALL queries are a subject of optimization introduced in MDEV-334 when creation of a temporary table is skipped. While there is a check for this optimization in Explain_union::print_explain() there was no such in Explain_union::print_explain_json(). This resulted in printing irrelevant data like: "union_result": { "table_name": "<union2,3>", "access_type": "ALL", "r_loops": 0, "r_rows": null in case when creation of the temporary table was actually optimized out. This commits adds a check whether the temporary table was actually created during the UNION ALL processing and eliminates printing of the irrelevant data.
4876 lines
136 KiB
Text
4876 lines
136 KiB
Text
create table t1 (a int, b varchar(32));
|
|
insert into t1 values
|
|
(4,'aaaa' ), (7,'bb'), (1,'ccc'), (4,'dd');
|
|
insert into t1 values
|
|
(3,'eee'), (7,'bb'), (1,'fff'), (4,'ggg');
|
|
with recursive
|
|
t as
|
|
(
|
|
select * from t1 where t1.b >= 'c'
|
|
union
|
|
select * from r
|
|
),
|
|
r as
|
|
(
|
|
select * from t
|
|
union
|
|
select t1.* from t1,r where r.a+1 = t1.a
|
|
)
|
|
select * from r;
|
|
ERROR HY000: Unacceptable mutual recursion with anchored table 't'
|
|
with recursive
|
|
a1(a,b) as
|
|
(select * from t1 where t1.a>3
|
|
union
|
|
select * from b1 where b1.a >3
|
|
union
|
|
select * from c1 where c1.a>3),
|
|
b1(a,b) as
|
|
(select * from a1 where a1.b > 'ccc'
|
|
union
|
|
select * from c1 where c1.b > 'ddd'),
|
|
c1(a,b) as
|
|
(select * from a1 where a1.a<6 and a1.b< 'zz'
|
|
union
|
|
select * from b1 where b1.b > 'auu')
|
|
select * from c1;
|
|
ERROR HY000: Unacceptable mutual recursion with anchored table 'a1'
|
|
drop table t1;
|
|
# WITH RECURSIVE vs just WITH
|
|
create table t1 (a int);
|
|
insert into t1 values
|
|
(0), (1), (2), (3), (4);
|
|
create table t2 (a int);
|
|
insert into t2 values
|
|
(1), (2), (3), (4), (5);
|
|
# just WITH : s refers to t defined after s
|
|
with
|
|
s(a) as (select t.a + 10 from t),
|
|
t(a) as (select t1.a from t1)
|
|
select * from s;
|
|
ERROR 42S02: Table 'test.t' doesn't exist
|
|
# WITH RECURSIVE: s refers to t defined after s
|
|
with recursive
|
|
s(a) as (select t.a + 10 from t),
|
|
t(a) as (select t1.a from t1)
|
|
select * from s;
|
|
a
|
|
10
|
|
11
|
|
12
|
|
13
|
|
14
|
|
# just WITH : defined t1 is non-recursive and uses base tables t1,t2
|
|
with
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
a
|
|
3
|
|
1
|
|
2
|
|
4
|
|
5
|
|
explain
|
|
with
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 30
|
|
2 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where
|
|
3 UNION t1 ALL NULL NULL NULL NULL 5
|
|
3 UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
|
#WITH RECURSIVE : defined t1 is recursive and uses only base table t2
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
a
|
|
3
|
|
4
|
|
5
|
|
explain
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
|
|
2 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 5
|
|
3 RECURSIVE UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
|
# just WITH : types of t1 columns are determined by all parts of union
|
|
create view v1 as
|
|
with
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a+1 from t1,t2 where t1.a=t2.a
|
|
)
|
|
select * from t1;
|
|
show columns from v1;
|
|
Field Type Null Key Default Extra
|
|
a bigint(12) YES NULL
|
|
# WITH RECURSIVE : types of t1 columns are determined by anchor parts
|
|
create view v2 as
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select a from t2 where t2.a=3
|
|
union
|
|
select t2.a+1 from t1,t2 where t1.a=t2.a
|
|
)
|
|
select * from t1;
|
|
show columns from v2;
|
|
Field Type Null Key Default Extra
|
|
a int(11) YES NULL
|
|
drop view v1,v2;
|
|
drop table t1,t2;
|
|
create table folks(id int, name char(32), dob date, father int, mother int);
|
|
insert into folks values
|
|
(100, 'Me', '2000-01-01', 20, 30),
|
|
(20, 'Dad', '1970-02-02', 10, 9),
|
|
(30, 'Mom', '1975-03-03', 8, 7),
|
|
(10, 'Grandpa Bill', '1940-04-05', null, null),
|
|
(9, 'Grandma Ann', '1941-10-15', null, null),
|
|
(25, 'Uncle Jim', '1968-11-18', 8, 7),
|
|
(98, 'Sister Amy', '2001-06-20', 20, 30),
|
|
(7, 'Grandma Sally', '1943-08-23', null, 6),
|
|
(8, 'Grandpa Ben', '1940-10-21', null, null),
|
|
(6, 'Grandgrandma Martha', '1923-05-17', null, null),
|
|
(67, 'Cousin Eddie', '1992-02-28', 25, 27),
|
|
(27, 'Auntie Melinda', '1971-03-29', null, null);
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the first select in the specification
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.id, p.name, p.dob, p.father, p.mother
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the last select in the specification
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select p.*
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
union
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the first select in the specification
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Cousin Eddie'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
67 Cousin Eddie 1992-02-28 25 27
|
|
25 Uncle Jim 1968-11-18 8 7
|
|
27 Auntie Melinda 1971-03-29 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# simple recursion with or in anchor and or in recursive part
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' or name='Sister Amy'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
98 Sister Amy 2001-06-20 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# two recursive definition, one uses another
|
|
with recursive
|
|
prev_gen
|
|
as
|
|
(
|
|
select folks.*
|
|
from folks, prev_gen
|
|
where folks.id=prev_gen.father or folks.id=prev_gen.mother
|
|
union
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
union
|
|
select *
|
|
from ancestors
|
|
union
|
|
select *
|
|
from prev_gen
|
|
)
|
|
select ancestors.name, ancestors.dob from ancestors;
|
|
name dob
|
|
Me 2000-01-01
|
|
Dad 1970-02-02
|
|
Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05
|
|
Grandma Ann 1941-10-15
|
|
Grandma Sally 1943-08-23
|
|
Grandpa Ben 1940-10-21
|
|
Grandgrandma Martha 1923-05-17
|
|
# recursive definition with two attached non-recursive
|
|
with recursive
|
|
ancestors(id,name,dob)
|
|
as
|
|
(
|
|
with
|
|
father(child_id,id,name,dob)
|
|
as
|
|
(
|
|
select folks.id, f.id, f.name, f.dob
|
|
from folks, folks f
|
|
where folks.father=f.id
|
|
),
|
|
mother(child_id,id,name,dob)
|
|
as
|
|
(
|
|
select folks.id, m.id, m.name, m.dob
|
|
from folks, folks m
|
|
where folks.mother=m.id
|
|
)
|
|
select folks.id, folks.name, folks.dob
|
|
from folks
|
|
where name='Me'
|
|
union
|
|
select f.id, f.name, f.dob
|
|
from ancestors a, father f
|
|
where f.child_id=a.id
|
|
union
|
|
select m.id, m.name, m.dob
|
|
from ancestors a, mother m
|
|
where m.child_id=a.id
|
|
)
|
|
select ancestors.name, ancestors.dob from ancestors;
|
|
name dob
|
|
Me 2000-01-01
|
|
Dad 1970-02-02
|
|
Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05
|
|
Grandpa Ben 1940-10-21
|
|
Grandma Ann 1941-10-15
|
|
Grandma Sally 1943-08-23
|
|
Grandgrandma Martha 1923-05-17
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the first select in the specification
|
|
with recursive
|
|
descendants
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Grandpa Bill'
|
|
union
|
|
select folks.*
|
|
from folks, descendants as d
|
|
where d.id=folks.father or d.id=folks.mother
|
|
)
|
|
select * from descendants;
|
|
id name dob father mother
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
20 Dad 1970-02-02 10 9
|
|
100 Me 2000-01-01 20 30
|
|
98 Sister Amy 2001-06-20 20 30
|
|
# simple recursion with one anchor and one recursive select
|
|
# the anchor is the first select in the specification
|
|
with recursive
|
|
descendants
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Grandma Sally'
|
|
union
|
|
select folks.*
|
|
from folks, descendants as d
|
|
where d.id=folks.father or d.id=folks.mother
|
|
)
|
|
select * from descendants;
|
|
id name dob father mother
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
30 Mom 1975-03-03 8 7
|
|
25 Uncle Jim 1968-11-18 8 7
|
|
100 Me 2000-01-01 20 30
|
|
98 Sister Amy 2001-06-20 20 30
|
|
67 Cousin Eddie 1992-02-28 25 27
|
|
# simple recursive table used three times in the main query
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father OR p.id = a.mother
|
|
)
|
|
select *
|
|
from ancestors t1, ancestors t2
|
|
where exists (select * from ancestors a
|
|
where a.father=t1.id AND a.mother=t2.id);
|
|
id name dob father mother id name dob father mother
|
|
20 Dad 1970-02-02 10 9 30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL 9 Grandma Ann 1941-10-15 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL 7 Grandma Sally 1943-08-23 NULL 6
|
|
# simple recursive table used three times in the main query
|
|
with
|
|
ancestor_couples(husband, h_dob, wife, w_dob)
|
|
as
|
|
(
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father OR p.id = a.mother
|
|
)
|
|
select t1.name, t1.dob, t2.name, t2.dob
|
|
from ancestors t1, ancestors t2
|
|
where exists (select * from ancestors a
|
|
where a.father=t1.id AND a.mother=t2.id)
|
|
)
|
|
select * from ancestor_couples;
|
|
husband h_dob wife w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# simple recursion with two selects in recursive part
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# mutual recursion with renaming
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# mutual recursion with union all
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union all
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# mutual recursion with renaming
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# mutual recursion with union all
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union all
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# mutual recursion with one select in the first definition
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
where a.father is not null and a.mother is not null
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select *
|
|
from ancestor_couple_ids;
|
|
h_id w_id
|
|
20 30
|
|
10 9
|
|
8 7
|
|
# join of a mutually recursive table with base tables
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
where a.father is not null and a.mother is not null
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select h.name, h.dob, w.name, w.dob
|
|
from ancestor_couple_ids c, folks h, folks w
|
|
where c.h_id = h.id and c.w_id= w.id;
|
|
name dob name dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# join of two mutually recursive tables
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
where a.father is not null and a.mother is not null
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select h.name, h.dob, w.name, w.dob
|
|
from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w
|
|
where c.h_id = h.id and c.w_id= w.id;
|
|
name dob name dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
explain extended
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
where a.father is not null and a.mother is not null
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select h.name, h.dob, w.name, w.dob
|
|
from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w
|
|
where c.h_id = h.id and c.w_id= w.id;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
1 PRIMARY <derived3> ref key0 key0 5 c.h_id 2 100.00
|
|
1 PRIMARY <derived3> ref key0 key0 5 c.w_id 2 100.00
|
|
3 DERIVED folks ALL NULL NULL NULL NULL 12 100.00 Using where
|
|
4 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2 100.00
|
|
4 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join)
|
|
5 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2 100.00
|
|
5 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union3,4,5> ALL NULL NULL NULL NULL NULL NULL
|
|
2 DERIVED <derived3> ALL NULL NULL NULL NULL 12 100.00 Using where
|
|
Warnings:
|
|
Note 1003 with recursive ancestor_couple_ids(h_id,w_id) as (/* select#2 */ select `a`.`father` AS `h_id`,`a`.`mother` AS `w_id` from `coupled_ancestors` `a` where `a`.`father` is not null and `a`.`mother` is not null), coupled_ancestors(id,name,dob,father,mother) as (/* select#3 */ select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' union all /* select#4 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `fa` where `test`.`p`.`id` = `fa`.`h_id` union all /* select#5 */ select `test`.`p`.`id` AS `id`,`test`.`p`.`name` AS `name`,`test`.`p`.`dob` AS `dob`,`test`.`p`.`father` AS `father`,`test`.`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestor_couple_ids` `ma` where `test`.`p`.`id` = `ma`.`w_id`)/* select#1 */ select `h`.`name` AS `name`,`h`.`dob` AS `dob`,`w`.`name` AS `name`,`w`.`dob` AS `dob` from `ancestor_couple_ids` `c` join `coupled_ancestors` `h` join `coupled_ancestors` `w` where `h`.`id` = `c`.`h_id` and `w`.`id` = `c`.`w_id`
|
|
# simple mutual recursion
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select *
|
|
from ancestor_couple_ids;
|
|
h_id w_id
|
|
20 30
|
|
10 9
|
|
8 7
|
|
NULL NULL
|
|
NULL NULL
|
|
NULL NULL
|
|
NULL 6
|
|
NULL NULL
|
|
# join of two mutually recursive tables
|
|
with recursive
|
|
ancestor_couple_ids(h_id, w_id)
|
|
as
|
|
(
|
|
select a.father, a.mother
|
|
from coupled_ancestors a
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids fa
|
|
where p.id = fa.h_id
|
|
union all
|
|
select p.*
|
|
from folks p, ancestor_couple_ids ma
|
|
where p.id = ma.w_id
|
|
)
|
|
select h.name, h.dob, w.name, w.dob
|
|
from ancestor_couple_ids c, coupled_ancestors h, coupled_ancestors w
|
|
where c.h_id = h.id and c.w_id= w.id;
|
|
name dob name dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
# execution of prepared query using a recursive table
|
|
prepare stmt1 from "
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.id, p.name, p.dob, p.father, p.mother
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
";
|
|
execute stmt1;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
execute stmt1;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
deallocate prepare stmt1;
|
|
# view using a recursive table
|
|
create view v1 as
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.id, p.name, p.dob, p.father, p.mother
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
show create view v1;
|
|
View Create View character_set_client collation_connection
|
|
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS with recursive ancestors as (select `folks`.`id` AS `id`,`folks`.`name` AS `name`,`folks`.`dob` AS `dob`,`folks`.`father` AS `father`,`folks`.`mother` AS `mother` from `folks` where `folks`.`name` = 'Me' and `folks`.`dob` = '2000-01-01' union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `a`) where `p`.`id` = `a`.`father` or `p`.`id` = `a`.`mother`)select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors` latin1 latin1_swedish_ci
|
|
select * from v1;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
create view v2 as
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
show create view v2;
|
|
View Create View character_set_client collation_connection
|
|
v2 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS with recursive ancestors as (select `folks`.`id` AS `id`,`folks`.`name` AS `name`,`folks`.`dob` AS `dob`,`folks`.`father` AS `father`,`folks`.`mother` AS `mother` from `folks` where `folks`.`name` = 'Me' union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `fa`) where `p`.`id` = `fa`.`father` union select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from (`folks` `p` join `ancestors` `ma`) where `p`.`id` = `ma`.`mother`)select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors` latin1 latin1_swedish_ci
|
|
select * from v2;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop view v1,v2;
|
|
explain extended
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me' and dob = '2000-01-01'
|
|
union
|
|
select p.id, p.name, p.dob, p.father, p.mother
|
|
from folks as p, ancestors AS a
|
|
where p.id = a.father or p.id = a.mother
|
|
)
|
|
select * from ancestors;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12 100.00
|
|
2 DERIVED folks ALL NULL NULL NULL NULL 12 100.00 Using where
|
|
3 RECURSIVE UNION p ALL NULL NULL NULL NULL 12 100.00
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 12 100.00 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
Warnings:
|
|
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`folks`.`id` AS `id`,`test`.`folks`.`name` AS `name`,`test`.`folks`.`dob` AS `dob`,`test`.`folks`.`father` AS `father`,`test`.`folks`.`mother` AS `mother` from `test`.`folks` where `test`.`folks`.`name` = 'Me' and `test`.`folks`.`dob` = DATE'2000-01-01' union /* select#3 */ select `p`.`id` AS `id`,`p`.`name` AS `name`,`p`.`dob` AS `dob`,`p`.`father` AS `father`,`p`.`mother` AS `mother` from `test`.`folks` `p` join `ancestors` `a` where `a`.`father` = `p`.`id` or `a`.`mother` = `p`.`id`)/* select#1 */ select `ancestors`.`id` AS `id`,`ancestors`.`name` AS `name`,`ancestors`.`dob` AS `dob`,`ancestors`.`father` AS `father`,`ancestors`.`mother` AS `mother` from `ancestors`
|
|
# recursive spec with two anchor selects and two recursive ones
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select p.* from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
# recursive spec using union all
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union all
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me' and father is not null
|
|
union all
|
|
select mother, 1 from folks where name = 'Me' and mother is not null
|
|
union all
|
|
select father, fa.generation+1 from folks, ancestor_ids fa
|
|
where folks.id = fa.id and (father not in (select id from ancestor_ids))
|
|
union all
|
|
select mother, ma.generation+1 from folks, ancestor_ids ma
|
|
where folks.id = ma.id and (mother not in (select id from ancestor_ids))
|
|
)
|
|
select generation, name from ancestor_ids a, folks
|
|
where a.id = folks.id;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids'
|
|
set standard_compliant_cte=0;
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me' and father is not null
|
|
union all
|
|
select mother from folks where name = 'Me' and mother is not null
|
|
union all
|
|
select father, fa.generation+1 from folks, ancestor_ids fa
|
|
where folks.id = fa.id and (father not in (select id from ancestor_ids))
|
|
union all
|
|
select mother, ma.generation+1 from folks, ancestor_ids ma
|
|
where folks.id = ma.id and (mother not in (select id from ancestor_ids))
|
|
)
|
|
select generation, name from ancestor_ids a, folks
|
|
where a.id = folks.id;
|
|
ERROR HY000: WITH column list and SELECT field list have different column counts
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me' and father is not null
|
|
union all
|
|
select mother, 1 from folks where name = 'Me' and mother is not null
|
|
union all
|
|
select father, fa.generation+1 from folks, ancestor_ids fa
|
|
where folks.id = fa.id and father is not null and
|
|
(father not in (select id from ancestor_ids))
|
|
union all
|
|
select mother, ma.generation+1 from folks, ancestor_ids ma
|
|
where folks.id = ma.id and mother is not null and
|
|
(mother not in (select id from ancestor_ids))
|
|
)
|
|
select generation, name from ancestor_ids a, folks
|
|
where a.id = folks.id;
|
|
generation name
|
|
1 Dad
|
|
1 Mom
|
|
2 Grandpa Bill
|
|
2 Grandma Ann
|
|
2 Grandma Sally
|
|
2 Grandpa Ben
|
|
3 Grandgrandma Martha
|
|
set standard_compliant_cte=1;
|
|
with recursive
|
|
coupled_ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me' and father is not null
|
|
union
|
|
select mother from folks where name = 'Me' and mother is not null
|
|
union
|
|
select n.father
|
|
from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n
|
|
where folks.father = fa.id and folks.mother = ma.id and
|
|
(fa.id = n.id or ma.id = n.id) and
|
|
n.father is not null and n.mother is not null
|
|
union
|
|
select n.mother
|
|
from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n
|
|
where folks.father = fa.id and folks.mother = ma.id and
|
|
(fa.id = n.id or ma.id = n.id) and
|
|
n.father is not null and n.mother is not null
|
|
)
|
|
select p.* from coupled_ancestor_ids a, folks p
|
|
where a.id = p.id;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'coupled_ancestor_ids'
|
|
set statement standard_compliant_cte=0 for
|
|
with recursive
|
|
coupled_ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me' and father is not null
|
|
union
|
|
select mother from folks where name = 'Me' and mother is not null
|
|
union
|
|
select n.father
|
|
from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n
|
|
where folks.father = fa.id and folks.mother = ma.id and
|
|
(fa.id = n.id or ma.id = n.id) and
|
|
n.father is not null and n.mother is not null
|
|
union
|
|
select n.mother
|
|
from folks, coupled_ancestor_ids fa, coupled_ancestor_ids ma, folks n
|
|
where folks.father = fa.id and folks.mother = ma.id and
|
|
(fa.id = n.id or ma.id = n.id) and
|
|
n.father is not null and n.mother is not null
|
|
)
|
|
select p.* from coupled_ancestor_ids a, folks p
|
|
where a.id = p.id;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks left join ancestor_ids a on folks.id = a.id
|
|
union
|
|
select mother from folks left join ancestor_ids a on folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select p.* from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids'
|
|
set statement standard_compliant_cte=0 for
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks left join ancestor_ids a on folks.id = a.id
|
|
union
|
|
select mother from folks left join ancestor_ids a on folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select p.* from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
25 Uncle Jim 1968-11-18 8 7
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
27 Auntie Melinda 1971-03-29 NULL NULL
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me'
|
|
union
|
|
select mother, 1 from folks where name = 'Me'
|
|
union
|
|
select father, a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
union
|
|
select mother, a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select generation, name from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
generation name
|
|
1 Dad
|
|
1 Mom
|
|
2 Grandpa Bill
|
|
2 Grandma Ann
|
|
2 Grandma Sally
|
|
2 Grandpa Ben
|
|
3 Grandgrandma Martha
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me'
|
|
union
|
|
select mother, 1 from folks where name = 'Me'
|
|
union
|
|
select max(father), max(a.generation)+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
group by a.generation
|
|
union
|
|
select max(mother), max(a.generation)+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
group by a.generation
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select generation, name from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'ancestor_ids'
|
|
set statement standard_compliant_cte=0 for
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me'
|
|
union
|
|
select mother, 1 from folks where name = 'Me'
|
|
union
|
|
select max(father), a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
group by a.generation
|
|
union
|
|
select max(mother), a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
group by a.generation
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select generation, name from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
generation name
|
|
1 Dad
|
|
1 Mom
|
|
2 Grandpa Bill
|
|
2 Grandma Ann
|
|
set statement max_recursive_iterations=1 for
|
|
with recursive
|
|
ancestor_ids (id, generation)
|
|
as
|
|
(
|
|
select father, 1 from folks where name = 'Me'
|
|
union
|
|
select mother, 1 from folks where name = 'Me'
|
|
union
|
|
select father, a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
union
|
|
select mother, a.generation+1 from folks, ancestor_ids a
|
|
where folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select generation, name from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
generation name
|
|
1 Dad
|
|
1 Mom
|
|
2 Grandpa Bill
|
|
2 Grandma Ann
|
|
2 Grandma Sally
|
|
2 Grandpa Ben
|
|
# query with recursive tables using key access
|
|
alter table folks add primary key (id);
|
|
explain
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 12
|
|
2 DERIVED folks ALL NULL NULL NULL NULL 12 Using where
|
|
3 RECURSIVE UNION p ALL PRIMARY NULL NULL NULL 12
|
|
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.p.id 2
|
|
4 RECURSIVE UNION p ALL PRIMARY NULL NULL NULL 12
|
|
4 RECURSIVE UNION <derived2> ref key0 key0 5 test.p.id 2
|
|
NULL UNION RESULT <union2,3,4> ALL NULL NULL NULL NULL NULL
|
|
with recursive
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as fa
|
|
where p.id = fa.father
|
|
union
|
|
select p.*
|
|
from folks as p, ancestors as ma
|
|
where p.id = ma.mother
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
100 Me 2000-01-01 20 30
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
#
|
|
# EXPLAIN FORMAT=JSON on a query where one recursive CTE uses another:
|
|
#
|
|
explain
|
|
with recursive
|
|
prev_gen
|
|
as
|
|
(
|
|
select folks.*
|
|
from folks, prev_gen
|
|
where folks.id=prev_gen.father or folks.id=prev_gen.mother
|
|
union
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
union
|
|
select *
|
|
from ancestors
|
|
union
|
|
select *
|
|
from prev_gen
|
|
)
|
|
select ancestors.name, ancestors.dob from ancestors;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 24
|
|
4 DERIVED folks ALL NULL NULL NULL NULL 12 Using where
|
|
6 UNION <derived3> ALL NULL NULL NULL NULL 12
|
|
5 RECURSIVE UNION <derived4> ALL NULL NULL NULL NULL 24
|
|
NULL UNION RESULT <union4,6,5> ALL NULL NULL NULL NULL NULL
|
|
3 DERIVED folks ALL NULL NULL NULL NULL 12 Using where
|
|
2 RECURSIVE UNION folks ALL PRIMARY NULL NULL NULL 12
|
|
2 RECURSIVE UNION <derived3> ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union3,2> ALL NULL NULL NULL NULL NULL
|
|
explain FORMAT=JSON
|
|
with recursive
|
|
prev_gen
|
|
as
|
|
(
|
|
select folks.*
|
|
from folks, prev_gen
|
|
where folks.id=prev_gen.father or folks.id=prev_gen.mother
|
|
union
|
|
select *
|
|
from folks
|
|
where name='Me'
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name='Me2'
|
|
union
|
|
select *
|
|
from ancestors where id < 234
|
|
union
|
|
select *
|
|
from prev_gen where id < 345
|
|
)
|
|
select ancestors.name, ancestors.dob from ancestors;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"table_name": "<derived4>",
|
|
"access_type": "ALL",
|
|
"rows": 24,
|
|
"filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union4,6,5>",
|
|
"access_type": "ALL",
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 4,
|
|
"table": {
|
|
"table_name": "folks",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"attached_condition": "folks.`name` = 'Me2'"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 6,
|
|
"operation": "UNION",
|
|
"table": {
|
|
"table_name": "<derived3>",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"attached_condition": "prev_gen.`id` < 345",
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union3,2>",
|
|
"access_type": "ALL",
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"table": {
|
|
"table_name": "folks",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"attached_condition": "folks.`name` = 'Me'"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"operation": "UNION",
|
|
"table": {
|
|
"table_name": "folks",
|
|
"access_type": "ALL",
|
|
"possible_keys": ["PRIMARY"],
|
|
"rows": 12,
|
|
"filtered": 100
|
|
},
|
|
"block-nl-join": {
|
|
"table": {
|
|
"table_name": "<derived3>",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100
|
|
},
|
|
"buffer_type": "flat",
|
|
"buffer_size": "256Kb",
|
|
"join_type": "BNL",
|
|
"attached_condition": "prev_gen.father = folks.`id` or prev_gen.mother = folks.`id`"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 5,
|
|
"operation": "UNION",
|
|
"table": {
|
|
"table_name": "<derived4>",
|
|
"access_type": "ALL",
|
|
"rows": 24,
|
|
"filtered": 100,
|
|
"attached_condition": "ancestors.`id` < 234"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#
|
|
explain format=json
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union all
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"table_name": "<derived3>",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union3,2>",
|
|
"access_type": "ALL",
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"table": {
|
|
"table_name": "v",
|
|
"access_type": "ALL",
|
|
"rows": 12,
|
|
"filtered": 100,
|
|
"attached_condition": "v.`name` = 'Me' and v.father is not null and v.mother is not null"
|
|
},
|
|
"table": {
|
|
"table_name": "h",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "4",
|
|
"used_key_parts": ["id"],
|
|
"ref": ["test.v.father"],
|
|
"rows": 1,
|
|
"filtered": 100
|
|
},
|
|
"table": {
|
|
"table_name": "w",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "4",
|
|
"used_key_parts": ["id"],
|
|
"ref": ["test.v.mother"],
|
|
"rows": 1,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"operation": "UNION",
|
|
"table": {
|
|
"table_name": "<derived4>",
|
|
"access_type": "ALL",
|
|
"rows": 2,
|
|
"filtered": 100,
|
|
"attached_condition": "a.father is not null and a.mother is not null"
|
|
},
|
|
"table": {
|
|
"table_name": "h",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "4",
|
|
"used_key_parts": ["id"],
|
|
"ref": ["a.father"],
|
|
"rows": 1,
|
|
"filtered": 100
|
|
},
|
|
"table": {
|
|
"table_name": "w",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "4",
|
|
"used_key_parts": ["id"],
|
|
"ref": ["a.mother"],
|
|
"rows": 1,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
create table my_ancestors
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
delete from my_ancestors;
|
|
insert into my_ancestors
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop table my_ancestors;
|
|
WITH RECURSIVE
|
|
positions(i) AS (
|
|
VALUES(0)
|
|
UNION SELECT ALL
|
|
i+1 FROM positions WHERE i < 4*4-1
|
|
),
|
|
solutions(board, n_queens) AS (
|
|
SELECT REPEAT('-', 4*4), 0
|
|
FROM positions
|
|
UNION
|
|
SELECT
|
|
concat(substr(board, 1, i),'*',substr(board, i+2)),n_queens + 1 AS n_queens
|
|
FROM positions AS ps, solutions
|
|
WHERE n_queens < 4
|
|
AND substr(board,1,i) != '*'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM positions WHERE
|
|
substr(board,i+1,1) = '*' AND
|
|
(
|
|
i % 4 = ps.i % 4 OR
|
|
i div 4 = ps.i div 4 OR
|
|
i div 4 + (i % 4) = ps.i div 4 + (ps.i % 4) OR
|
|
i div 4 - (i % 4) = ps.i div 4 - (ps.i % 4)
|
|
)
|
|
)
|
|
)
|
|
SELECT regexp_replace(board,concat('(',REPEAT('.', 4),')'),'\\1\n') n_queens FROM solutions WHERE n_queens = 4;
|
|
n_queens
|
|
-*--
|
|
---*
|
|
*---
|
|
--*-
|
|
|
|
--*-
|
|
*---
|
|
---*
|
|
-*--
|
|
|
|
#
|
|
# MDEV-10883: execution of prepared statement from SELECT
|
|
# with recursive CTE that renames columns
|
|
#
|
|
prepare stmt from"
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
";
|
|
execute stmt;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
deallocate prepare stmt;
|
|
#
|
|
# MDEV-10881: execution of prepared statement from
|
|
# CREATE ... SELECT, INSERT ... SELECT
|
|
#
|
|
prepare stmt from"
|
|
create table my_ancestors
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
";
|
|
execute stmt;
|
|
deallocate prepare stmt;
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
delete from my_ancestors;
|
|
prepare stmt from"
|
|
insert into my_ancestors
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id;
|
|
";
|
|
execute stmt;
|
|
deallocate prepare stmt;
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop table my_ancestors;
|
|
#
|
|
# MDEV-10933: WITH clause together with SELECT in parenthesis
|
|
# CREATE SELECT
|
|
#
|
|
create table my_ancestors
|
|
(
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from folks, ancestor_ids a where folks.id = a.id
|
|
union
|
|
select mother from folks, ancestor_ids a where folks.id = a.id
|
|
)
|
|
select p.* from folks as p, ancestor_ids as a where p.id = a.id
|
|
);
|
|
select * from my_ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop table my_ancestors;
|
|
drop table folks;
|
|
#
|
|
# MDEV-10372: [bb-10.2-mdev9864 tree] EXPLAIN with recursive CTE enters endless recursion
|
|
#
|
|
create table t1(a int);
|
|
insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
|
|
explain format=json
|
|
with recursive t as (select a from t1 union select a+10 from t where a < 1000)
|
|
select * from t;
|
|
EXPLAIN
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"table_name": "<derived2>",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union2,3>",
|
|
"access_type": "ALL",
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"operation": "UNION",
|
|
"table": {
|
|
"table_name": "<derived2>",
|
|
"access_type": "ALL",
|
|
"rows": 10,
|
|
"filtered": 100,
|
|
"attached_condition": "t.a < 1000"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
drop table t1;
|
|
#
|
|
# MDEV-10737: recursive union with several anchors at the end
|
|
#
|
|
WITH RECURSIVE cte(n) AS
|
|
( SELECT n+1 FROM cte WHERE n < 5 UNION SELECT 1 UNION SELECT 1 )
|
|
SELECT * FROM cte;
|
|
n
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
#
|
|
# MDEV-10736: recursive definition with anchor over a table with blob
|
|
#
|
|
CREATE TABLE t1 (f VARCHAR(1024));
|
|
WITH RECURSIVE cte(f) AS
|
|
(SELECT t1.f FROM t1 UNION ALL SELECT cte.f FROM cte)
|
|
SELECT * FROM cte as t;
|
|
f
|
|
DROP TABLE t1;
|
|
#
|
|
# MDEV-10899: mergeable derived in the spec of recursive CTE
|
|
#
|
|
create table t1 (a int);
|
|
insert into t1 values
|
|
(0), (1), (2), (3), (4);
|
|
create table t2 (a int);
|
|
insert into t2 values
|
|
(1), (2), (3), (4), (5);
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select x.a from (select a from t2 where t2.a=3) x
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
a
|
|
3
|
|
4
|
|
5
|
|
explain
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select x.a from (select a from t2 where t2.a=3) x
|
|
union
|
|
select t2.a from t1,t2 where t1.a+1=t2.a
|
|
)
|
|
select * from t1;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
|
|
2 DERIVED t2 ALL NULL NULL NULL NULL 5 Using where
|
|
4 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 5
|
|
4 RECURSIVE UNION t2 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
|
drop table t1,t2;
|
|
#
|
|
# MDEV-11278: non-mergeable view in the spec of recursive CTE
|
|
#
|
|
create table t1 (a int);
|
|
insert into t1 values
|
|
(0), (1), (2), (3), (4);
|
|
create table t2 (a int);
|
|
insert into t2 values
|
|
(1), (2), (3), (4), (5);
|
|
create view v1 as
|
|
select a from t2 where a < 3
|
|
union
|
|
select a from t2 where a > 4;
|
|
with recursive
|
|
t1 as
|
|
(
|
|
select a from v1 where a=1
|
|
union
|
|
select v1.a from t1,v1 where t1.a+1=v1.a
|
|
)
|
|
select * from t1;
|
|
a
|
|
1
|
|
2
|
|
drop view v1;
|
|
drop table t1,t2;
|
|
#
|
|
# MDEV-11259: recursive CTE with concatenation operation
|
|
#
|
|
DROP TABLE IF EXISTS edges;
|
|
Warnings:
|
|
Note 1051 Unknown table 'test.edges'
|
|
CREATE TABLE edges(
|
|
a int(10) unsigned NOT NULL,
|
|
b int(10) unsigned NOT NULL,
|
|
PRIMARY KEY (a,b),
|
|
KEY b(b)
|
|
);
|
|
INSERT INTO edges
|
|
VALUES (1,3),(2,1),(2,4),(3,4),(3,5),(3,6),(4,7),(5,1),(5,6),(6,1);
|
|
DROP TABLE IF EXISTS edges2;
|
|
Warnings:
|
|
Note 1051 Unknown table 'test.edges2'
|
|
CREATE VIEW edges2 (a, b) AS
|
|
SELECT a, b FROM edges UNION ALL SELECT b, a FROM edges;
|
|
WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
|
|
( SELECT a, b, 1 AS distance,
|
|
concat(a, '.', b, '.') AS path_string
|
|
FROM edges
|
|
UNION ALL
|
|
SELECT tc.a, e.b, tc.distance + 1,
|
|
concat(tc.path_string, e.b, '.') AS path_string
|
|
FROM edges AS e
|
|
JOIN transitive_closure AS tc
|
|
ON e.a = tc.b
|
|
WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
|
|
)
|
|
SELECT * FROM transitive_closure
|
|
ORDER BY a, b, distance;
|
|
a b distance path_string
|
|
1 3 1 1.3.
|
|
1 4 2 1.3.4.
|
|
1 5 2 1.3.5.
|
|
1 6 2 1.3.6.
|
|
1 6 3 1.3.5.6.
|
|
1 7 3 1.3.4.7.
|
|
2 1 1 2.1.
|
|
2 3 2 2.1.3.
|
|
2 4 1 2.4.
|
|
2 4 3 2.1.3.4.
|
|
2 5 3 2.1.3.5.
|
|
2 6 3 2.1.3.6.
|
|
2 6 4 2.1.3.5.6.
|
|
2 7 2 2.4.7.
|
|
2 7 4 2.1.3.4.7.
|
|
3 1 2 3.5.1.
|
|
3 1 2 3.6.1.
|
|
3 1 3 3.5.6.1.
|
|
3 4 1 3.4.
|
|
3 5 1 3.5.
|
|
3 6 1 3.6.
|
|
3 6 2 3.5.6.
|
|
3 7 2 3.4.7.
|
|
4 7 1 4.7.
|
|
5 1 1 5.1.
|
|
5 1 2 5.6.1.
|
|
5 3 2 5.1.3.
|
|
5 3 3 5.6.1.3.
|
|
5 4 3 5.1.3.4.
|
|
5 4 4 5.6.1.3.4.
|
|
5 6 1 5.6.
|
|
5 6 3 5.1.3.6.
|
|
5 7 4 5.1.3.4.7.
|
|
5 7 5 5.6.1.3.4.7.
|
|
6 1 1 6.1.
|
|
6 3 2 6.1.3.
|
|
6 4 3 6.1.3.4.
|
|
6 5 3 6.1.3.5.
|
|
6 7 4 6.1.3.4.7.
|
|
WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
|
|
( SELECT a, b, 1 AS distance,
|
|
concat(a, '.', b, '.') AS path_string
|
|
FROM edges
|
|
WHERE a = 1 -- source
|
|
UNION ALL
|
|
SELECT tc.a, e.b, tc.distance + 1,
|
|
concat(tc.path_string, e.b, '.') AS path_string
|
|
FROM edges AS e
|
|
JOIN transitive_closure AS tc ON e.a = tc.b
|
|
WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
|
|
)
|
|
SELECT * FROM transitive_closure
|
|
WHERE b = 6 -- destination
|
|
ORDER BY a, b, distance;
|
|
a b distance path_string
|
|
1 6 2 1.3.6.
|
|
1 6 3 1.3.5.6.
|
|
WITH RECURSIVE transitive_closure(a, b, distance, path_string) AS
|
|
( SELECT a, b, 1 AS distance,
|
|
concat(a, '.', b, '.') AS path_string
|
|
FROM edges2
|
|
UNION ALL
|
|
SELECT tc.a, e.b, tc.distance + 1,
|
|
concat(tc.path_string, e.b, '.') AS path_string
|
|
FROM edges2 AS e
|
|
JOIN transitive_closure AS tc ON e.a = tc.b
|
|
WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
|
|
)
|
|
SELECT * FROM transitive_closure
|
|
ORDER BY a, b, distance;
|
|
a b distance path_string
|
|
1 2 1 1.2.
|
|
1 2 3 1.3.4.2.
|
|
1 2 4 1.5.3.4.2.
|
|
1 2 4 1.6.3.4.2.
|
|
1 2 5 1.5.6.3.4.2.
|
|
1 2 5 1.6.5.3.4.2.
|
|
1 3 1 1.3.
|
|
1 3 2 1.5.3.
|
|
1 3 2 1.6.3.
|
|
1 3 3 1.2.4.3.
|
|
1 3 3 1.5.6.3.
|
|
1 3 3 1.6.5.3.
|
|
1 4 2 1.2.4.
|
|
1 4 2 1.3.4.
|
|
1 4 3 1.5.3.4.
|
|
1 4 3 1.6.3.4.
|
|
1 4 4 1.5.6.3.4.
|
|
1 4 4 1.6.5.3.4.
|
|
1 5 1 1.5.
|
|
1 5 2 1.3.5.
|
|
1 5 2 1.6.5.
|
|
1 5 3 1.3.6.5.
|
|
1 5 3 1.6.3.5.
|
|
1 5 4 1.2.4.3.5.
|
|
1 5 5 1.2.4.3.6.5.
|
|
1 6 1 1.6.
|
|
1 6 2 1.3.6.
|
|
1 6 2 1.5.6.
|
|
1 6 3 1.3.5.6.
|
|
1 6 3 1.5.3.6.
|
|
1 6 4 1.2.4.3.6.
|
|
1 6 5 1.2.4.3.5.6.
|
|
1 7 3 1.2.4.7.
|
|
1 7 3 1.3.4.7.
|
|
1 7 4 1.5.3.4.7.
|
|
1 7 4 1.6.3.4.7.
|
|
1 7 5 1.5.6.3.4.7.
|
|
1 7 5 1.6.5.3.4.7.
|
|
2 1 1 2.1.
|
|
2 1 3 2.4.3.1.
|
|
2 1 4 2.4.3.5.1.
|
|
2 1 4 2.4.3.6.1.
|
|
2 1 5 2.4.3.5.6.1.
|
|
2 1 5 2.4.3.6.5.1.
|
|
2 3 2 2.1.3.
|
|
2 3 2 2.4.3.
|
|
2 3 3 2.1.5.3.
|
|
2 3 3 2.1.6.3.
|
|
2 3 4 2.1.5.6.3.
|
|
2 3 4 2.1.6.5.3.
|
|
2 4 1 2.4.
|
|
2 4 3 2.1.3.4.
|
|
2 4 4 2.1.5.3.4.
|
|
2 4 4 2.1.6.3.4.
|
|
2 4 5 2.1.5.6.3.4.
|
|
2 4 5 2.1.6.5.3.4.
|
|
2 5 2 2.1.5.
|
|
2 5 3 2.1.3.5.
|
|
2 5 3 2.1.6.5.
|
|
2 5 3 2.4.3.5.
|
|
2 5 4 2.1.3.6.5.
|
|
2 5 4 2.1.6.3.5.
|
|
2 5 4 2.4.3.1.5.
|
|
2 5 4 2.4.3.6.5.
|
|
2 5 5 2.4.3.1.6.5.
|
|
2 5 5 2.4.3.6.1.5.
|
|
2 6 2 2.1.6.
|
|
2 6 3 2.1.3.6.
|
|
2 6 3 2.1.5.6.
|
|
2 6 3 2.4.3.6.
|
|
2 6 4 2.1.3.5.6.
|
|
2 6 4 2.1.5.3.6.
|
|
2 6 4 2.4.3.1.6.
|
|
2 6 4 2.4.3.5.6.
|
|
2 6 5 2.4.3.1.5.6.
|
|
2 6 5 2.4.3.5.1.6.
|
|
2 7 2 2.4.7.
|
|
2 7 4 2.1.3.4.7.
|
|
2 7 5 2.1.5.3.4.7.
|
|
2 7 5 2.1.6.3.4.7.
|
|
2 7 6 2.1.5.6.3.4.7.
|
|
2 7 6 2.1.6.5.3.4.7.
|
|
3 1 1 3.1.
|
|
3 1 2 3.5.1.
|
|
3 1 2 3.6.1.
|
|
3 1 3 3.4.2.1.
|
|
3 1 3 3.5.6.1.
|
|
3 1 3 3.6.5.1.
|
|
3 2 2 3.1.2.
|
|
3 2 2 3.4.2.
|
|
3 2 3 3.5.1.2.
|
|
3 2 3 3.6.1.2.
|
|
3 2 4 3.5.6.1.2.
|
|
3 2 4 3.6.5.1.2.
|
|
3 4 1 3.4.
|
|
3 4 3 3.1.2.4.
|
|
3 4 4 3.5.1.2.4.
|
|
3 4 4 3.6.1.2.4.
|
|
3 4 5 3.5.6.1.2.4.
|
|
3 4 5 3.6.5.1.2.4.
|
|
3 5 1 3.5.
|
|
3 5 2 3.1.5.
|
|
3 5 2 3.6.5.
|
|
3 5 3 3.1.6.5.
|
|
3 5 3 3.6.1.5.
|
|
3 5 4 3.4.2.1.5.
|
|
3 5 5 3.4.2.1.6.5.
|
|
3 6 1 3.6.
|
|
3 6 2 3.1.6.
|
|
3 6 2 3.5.6.
|
|
3 6 3 3.1.5.6.
|
|
3 6 3 3.5.1.6.
|
|
3 6 4 3.4.2.1.6.
|
|
3 6 5 3.4.2.1.5.6.
|
|
3 7 2 3.4.7.
|
|
3 7 4 3.1.2.4.7.
|
|
3 7 5 3.5.1.2.4.7.
|
|
3 7 5 3.6.1.2.4.7.
|
|
3 7 6 3.5.6.1.2.4.7.
|
|
3 7 6 3.6.5.1.2.4.7.
|
|
4 1 2 4.2.1.
|
|
4 1 2 4.3.1.
|
|
4 1 3 4.3.5.1.
|
|
4 1 3 4.3.6.1.
|
|
4 1 4 4.3.5.6.1.
|
|
4 1 4 4.3.6.5.1.
|
|
4 2 1 4.2.
|
|
4 2 3 4.3.1.2.
|
|
4 2 4 4.3.5.1.2.
|
|
4 2 4 4.3.6.1.2.
|
|
4 2 5 4.3.5.6.1.2.
|
|
4 2 5 4.3.6.5.1.2.
|
|
4 3 1 4.3.
|
|
4 3 3 4.2.1.3.
|
|
4 3 4 4.2.1.5.3.
|
|
4 3 4 4.2.1.6.3.
|
|
4 3 5 4.2.1.5.6.3.
|
|
4 3 5 4.2.1.6.5.3.
|
|
4 5 2 4.3.5.
|
|
4 5 3 4.2.1.5.
|
|
4 5 3 4.3.1.5.
|
|
4 5 3 4.3.6.5.
|
|
4 5 4 4.2.1.3.5.
|
|
4 5 4 4.2.1.6.5.
|
|
4 5 4 4.3.1.6.5.
|
|
4 5 4 4.3.6.1.5.
|
|
4 5 5 4.2.1.3.6.5.
|
|
4 5 5 4.2.1.6.3.5.
|
|
4 6 2 4.3.6.
|
|
4 6 3 4.2.1.6.
|
|
4 6 3 4.3.1.6.
|
|
4 6 3 4.3.5.6.
|
|
4 6 4 4.2.1.3.6.
|
|
4 6 4 4.2.1.5.6.
|
|
4 6 4 4.3.1.5.6.
|
|
4 6 4 4.3.5.1.6.
|
|
4 6 5 4.2.1.3.5.6.
|
|
4 6 5 4.2.1.5.3.6.
|
|
4 7 1 4.7.
|
|
5 1 1 5.1.
|
|
5 1 2 5.3.1.
|
|
5 1 2 5.6.1.
|
|
5 1 3 5.3.6.1.
|
|
5 1 3 5.6.3.1.
|
|
5 1 4 5.3.4.2.1.
|
|
5 1 5 5.6.3.4.2.1.
|
|
5 2 2 5.1.2.
|
|
5 2 3 5.3.1.2.
|
|
5 2 3 5.3.4.2.
|
|
5 2 3 5.6.1.2.
|
|
5 2 4 5.1.3.4.2.
|
|
5 2 4 5.3.6.1.2.
|
|
5 2 4 5.6.3.1.2.
|
|
5 2 4 5.6.3.4.2.
|
|
5 2 5 5.1.6.3.4.2.
|
|
5 2 5 5.6.1.3.4.2.
|
|
5 3 1 5.3.
|
|
5 3 2 5.1.3.
|
|
5 3 2 5.6.3.
|
|
5 3 3 5.1.6.3.
|
|
5 3 3 5.6.1.3.
|
|
5 3 4 5.1.2.4.3.
|
|
5 3 5 5.6.1.2.4.3.
|
|
5 4 2 5.3.4.
|
|
5 4 3 5.1.2.4.
|
|
5 4 3 5.1.3.4.
|
|
5 4 3 5.6.3.4.
|
|
5 4 4 5.1.6.3.4.
|
|
5 4 4 5.3.1.2.4.
|
|
5 4 4 5.6.1.2.4.
|
|
5 4 4 5.6.1.3.4.
|
|
5 4 5 5.3.6.1.2.4.
|
|
5 4 5 5.6.3.1.2.4.
|
|
5 6 1 5.6.
|
|
5 6 2 5.1.6.
|
|
5 6 2 5.3.6.
|
|
5 6 3 5.1.3.6.
|
|
5 6 3 5.3.1.6.
|
|
5 6 5 5.1.2.4.3.6.
|
|
5 6 5 5.3.4.2.1.6.
|
|
5 7 3 5.3.4.7.
|
|
5 7 4 5.1.2.4.7.
|
|
5 7 4 5.1.3.4.7.
|
|
5 7 4 5.6.3.4.7.
|
|
5 7 5 5.1.6.3.4.7.
|
|
5 7 5 5.3.1.2.4.7.
|
|
5 7 5 5.6.1.2.4.7.
|
|
5 7 5 5.6.1.3.4.7.
|
|
5 7 6 5.3.6.1.2.4.7.
|
|
5 7 6 5.6.3.1.2.4.7.
|
|
6 1 1 6.1.
|
|
6 1 2 6.3.1.
|
|
6 1 2 6.5.1.
|
|
6 1 3 6.3.5.1.
|
|
6 1 3 6.5.3.1.
|
|
6 1 4 6.3.4.2.1.
|
|
6 1 5 6.5.3.4.2.1.
|
|
6 2 2 6.1.2.
|
|
6 2 3 6.3.1.2.
|
|
6 2 3 6.3.4.2.
|
|
6 2 3 6.5.1.2.
|
|
6 2 4 6.1.3.4.2.
|
|
6 2 4 6.3.5.1.2.
|
|
6 2 4 6.5.3.1.2.
|
|
6 2 4 6.5.3.4.2.
|
|
6 2 5 6.1.5.3.4.2.
|
|
6 2 5 6.5.1.3.4.2.
|
|
6 3 1 6.3.
|
|
6 3 2 6.1.3.
|
|
6 3 2 6.5.3.
|
|
6 3 3 6.1.5.3.
|
|
6 3 3 6.5.1.3.
|
|
6 3 4 6.1.2.4.3.
|
|
6 3 5 6.5.1.2.4.3.
|
|
6 4 2 6.3.4.
|
|
6 4 3 6.1.2.4.
|
|
6 4 3 6.1.3.4.
|
|
6 4 3 6.5.3.4.
|
|
6 4 4 6.1.5.3.4.
|
|
6 4 4 6.3.1.2.4.
|
|
6 4 4 6.5.1.2.4.
|
|
6 4 4 6.5.1.3.4.
|
|
6 4 5 6.3.5.1.2.4.
|
|
6 4 5 6.5.3.1.2.4.
|
|
6 5 1 6.5.
|
|
6 5 2 6.1.5.
|
|
6 5 2 6.3.5.
|
|
6 5 3 6.1.3.5.
|
|
6 5 3 6.3.1.5.
|
|
6 5 5 6.1.2.4.3.5.
|
|
6 5 5 6.3.4.2.1.5.
|
|
6 7 3 6.3.4.7.
|
|
6 7 4 6.1.2.4.7.
|
|
6 7 4 6.1.3.4.7.
|
|
6 7 4 6.5.3.4.7.
|
|
6 7 5 6.1.5.3.4.7.
|
|
6 7 5 6.3.1.2.4.7.
|
|
6 7 5 6.5.1.2.4.7.
|
|
6 7 5 6.5.1.3.4.7.
|
|
6 7 6 6.3.5.1.2.4.7.
|
|
6 7 6 6.5.3.1.2.4.7.
|
|
7 1 3 7.4.2.1.
|
|
7 1 3 7.4.3.1.
|
|
7 1 4 7.4.3.5.1.
|
|
7 1 4 7.4.3.6.1.
|
|
7 1 5 7.4.3.5.6.1.
|
|
7 1 5 7.4.3.6.5.1.
|
|
7 2 2 7.4.2.
|
|
7 2 4 7.4.3.1.2.
|
|
7 2 5 7.4.3.5.1.2.
|
|
7 2 5 7.4.3.6.1.2.
|
|
7 2 6 7.4.3.5.6.1.2.
|
|
7 2 6 7.4.3.6.5.1.2.
|
|
7 3 2 7.4.3.
|
|
7 3 4 7.4.2.1.3.
|
|
7 3 5 7.4.2.1.5.3.
|
|
7 3 5 7.4.2.1.6.3.
|
|
7 3 6 7.4.2.1.5.6.3.
|
|
7 3 6 7.4.2.1.6.5.3.
|
|
7 4 1 7.4.
|
|
7 5 3 7.4.3.5.
|
|
7 5 4 7.4.2.1.5.
|
|
7 5 4 7.4.3.1.5.
|
|
7 5 4 7.4.3.6.5.
|
|
7 5 5 7.4.2.1.3.5.
|
|
7 5 5 7.4.2.1.6.5.
|
|
7 5 5 7.4.3.1.6.5.
|
|
7 5 5 7.4.3.6.1.5.
|
|
7 5 6 7.4.2.1.3.6.5.
|
|
7 5 6 7.4.2.1.6.3.5.
|
|
7 6 3 7.4.3.6.
|
|
7 6 4 7.4.2.1.6.
|
|
7 6 4 7.4.3.1.6.
|
|
7 6 4 7.4.3.5.6.
|
|
7 6 5 7.4.2.1.3.6.
|
|
7 6 5 7.4.2.1.5.6.
|
|
7 6 5 7.4.3.1.5.6.
|
|
7 6 5 7.4.3.5.1.6.
|
|
7 6 6 7.4.2.1.3.5.6.
|
|
7 6 6 7.4.2.1.5.3.6.
|
|
WITH RECURSIVE transitive_closure(a, b, distance, path_string)
|
|
AS
|
|
( SELECT a, b, 1 AS distance,
|
|
concat(a, '.', b, '.') AS path_string
|
|
FROM edges2
|
|
UNION ALL
|
|
SELECT tc.a, e.b, tc.distance + 1,
|
|
concat(tc.path_string, e.b, '.') AS path_string
|
|
FROM edges2 AS e
|
|
JOIN transitive_closure AS tc ON e.a = tc.b
|
|
WHERE tc.path_string NOT LIKE concat('%', e.b, '.%')
|
|
)
|
|
SELECT a, b, min(distance) AS dist FROM transitive_closure
|
|
GROUP BY a, b
|
|
ORDER BY a, dist, b;
|
|
a b dist
|
|
1 2 1
|
|
1 3 1
|
|
1 4 2
|
|
1 5 1
|
|
1 6 1
|
|
1 7 3
|
|
2 1 1
|
|
2 3 2
|
|
2 4 1
|
|
2 5 2
|
|
2 6 2
|
|
2 7 2
|
|
3 1 1
|
|
3 2 2
|
|
3 4 1
|
|
3 5 1
|
|
3 6 1
|
|
3 7 2
|
|
4 1 2
|
|
4 2 1
|
|
4 3 1
|
|
4 5 2
|
|
4 6 2
|
|
4 7 1
|
|
5 1 1
|
|
5 2 2
|
|
5 3 1
|
|
5 4 2
|
|
5 6 1
|
|
5 7 3
|
|
6 1 1
|
|
6 2 2
|
|
6 3 1
|
|
6 4 2
|
|
6 5 1
|
|
6 7 3
|
|
7 1 3
|
|
7 2 2
|
|
7 3 2
|
|
7 4 1
|
|
7 5 3
|
|
7 6 3
|
|
DROP VIEW edges2;
|
|
DROP TABLE edges;
|
|
#
|
|
# MDEV-11674: recursive CTE table that cannot be stored
|
|
# in a heap table
|
|
#
|
|
create table t1 (id int, test_data varchar(36));
|
|
insert into t1(id, test_data)
|
|
select id, test_data
|
|
from (
|
|
with recursive data_generator(id, test_data) as (
|
|
select 1 as id, uuid() as test_data
|
|
union all
|
|
select id + 1, uuid() from data_generator where id < 150000
|
|
)
|
|
select * from data_generator
|
|
) as a;
|
|
drop table t1;
|
|
#
|
|
# MDEV-10773: ANALYZE for query with recursive CTE
|
|
#
|
|
analyze format=json
|
|
with recursive src(counter) as
|
|
(select 1
|
|
union
|
|
select counter+1 from src where counter<10
|
|
) select * from src;
|
|
ANALYZE
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"r_loops": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"table": {
|
|
"table_name": "<derived2>",
|
|
"access_type": "ALL",
|
|
"r_loops": 1,
|
|
"rows": 2,
|
|
"r_rows": 10,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union2,3>",
|
|
"access_type": "ALL",
|
|
"r_loops": 0,
|
|
"r_rows": null,
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"table": {
|
|
"message": "No tables used"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"operation": "UNION",
|
|
"r_loops": 10,
|
|
"r_total_time_ms": "REPLACED",
|
|
"table": {
|
|
"table_name": "<derived2>",
|
|
"access_type": "ALL",
|
|
"r_loops": 10,
|
|
"rows": 2,
|
|
"r_rows": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 90,
|
|
"attached_condition": "src.counter < 10"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#
|
|
# mdev-12360: recursive reference in left operand of LEFT JOIN
|
|
#
|
|
create table folks(id int, name char(32), dob date, father int, mother int);
|
|
insert into folks values
|
|
(100, 'Me', '2000-01-01', 20, 30),
|
|
(20, 'Dad', '1970-02-02', 10, 9),
|
|
(30, 'Mom', '1975-03-03', 8, 7),
|
|
(10, 'Grandpa Bill', '1940-04-05', null, null),
|
|
(9, 'Grandma Ann', '1941-10-15', null, null),
|
|
(25, 'Uncle Jim', '1968-11-18', 8, 7),
|
|
(98, 'Sister Amy', '2001-06-20', 20, 30),
|
|
(7, 'Grandma Sally', '1943-08-23', null, 6),
|
|
(8, 'Grandpa Ben', '1940-10-21', null, null),
|
|
(6, 'Grandgrandma Martha', '1923-05-17', null, null),
|
|
(67, 'Cousin Eddie', '1992-02-28', 25, 27),
|
|
(27, 'Auntie Melinda', '1971-03-29', null, null);
|
|
with recursive
|
|
ancestor_ids (id)
|
|
as
|
|
(
|
|
select father from folks where name = 'Me'
|
|
union
|
|
select mother from folks where name = 'Me'
|
|
union
|
|
select father from ancestor_ids as a left join folks on folks.id = a.id
|
|
union
|
|
select mother from ancestor_ids as a left join folks on folks.id = a.id
|
|
),
|
|
ancestors
|
|
as
|
|
(
|
|
select p.* from folks as p, ancestor_ids as a
|
|
where p.id = a.id
|
|
)
|
|
select * from ancestors;
|
|
id name dob father mother
|
|
20 Dad 1970-02-02 10 9
|
|
30 Mom 1975-03-03 8 7
|
|
10 Grandpa Bill 1940-04-05 NULL NULL
|
|
9 Grandma Ann 1941-10-15 NULL NULL
|
|
7 Grandma Sally 1943-08-23 NULL 6
|
|
8 Grandpa Ben 1940-10-21 NULL NULL
|
|
6 Grandgrandma Martha 1923-05-17 NULL NULL
|
|
drop table folks;
|
|
#
|
|
# mdev-12368: crash with mutually recursive CTE
|
|
# that arenot Standard compliant
|
|
#
|
|
create table value_nodes (v char(4));
|
|
create table module_nodes(m char(4));
|
|
create table module_arguments(m char(4), v char(4));
|
|
create table module_results(m char(4), v char(4));
|
|
with recursive
|
|
reached_values as
|
|
(
|
|
select v from value_nodes where v in ('v3','v7','v9')
|
|
union
|
|
select module_results.v from module_results, applied_modules
|
|
where module_results.m = applied_modules.m
|
|
),
|
|
applied_modules as
|
|
(
|
|
select module_nodes.m
|
|
from
|
|
module_nodes
|
|
left join
|
|
(
|
|
module_arguments
|
|
left join
|
|
reached_values
|
|
on module_arguments.v = reached_values.v
|
|
)
|
|
on reached_values.v is null and
|
|
module_nodes.m = module_arguments.m
|
|
where module_arguments.m is null
|
|
)
|
|
select * from reached_values;
|
|
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'applied_modules'
|
|
drop table value_nodes, module_nodes, module_arguments, module_results;
|
|
#
|
|
# mdev-12375: query using one of two mutually recursive CTEs
|
|
# whose non-recursive part returns an empty set
|
|
#
|
|
create table value_nodes (v char(4));
|
|
insert into value_nodes values
|
|
('v1'), ('v2'), ('v3'), ('v4'), ('v5'), ('v6'), ('v7'), ('v8'), ('v9'),
|
|
('v10'), ('v11'), ('v12'), ('v13'), ('v14'), ('v15'), ('v16');
|
|
create table module_nodes(m char(4));
|
|
insert into module_nodes values
|
|
('m1'), ('m2'), ('m3'), ('m4'), ('m5'), ('m6'), ('m7');
|
|
create table module_arguments(m char(4), v char(4));
|
|
insert into module_arguments values
|
|
('m1','v3'), ('m1','v9'),
|
|
('m2','v4'), ('m2','v3'), ('m2','v7'),
|
|
('m3','v6'),
|
|
('m4','v4'), ('m4','v1'),
|
|
('m5','v10'), ('m5','v8'), ('m5','v3'),
|
|
('m6','v8'), ('m6','v1'),
|
|
('m7','v11'), ('m7','v12');
|
|
create table module_results(m char(4), v char(4));
|
|
insert into module_results values
|
|
('m1','v4'),
|
|
('m2','v1'), ('m2','v6'),
|
|
('m3','v10'),
|
|
('m4','v8'),
|
|
('m5','v11'), ('m5','v9'),
|
|
('m6','v12'), ('m6','v4'),
|
|
('m7','v2');
|
|
set statement max_recursive_iterations=2, standard_compliant_cte=0 for
|
|
with recursive
|
|
reached_values as
|
|
(
|
|
select v from value_nodes where v in ('v3','v7','v9')
|
|
union
|
|
select module_results.v from module_results, applied_modules
|
|
where module_results.m = applied_modules.m
|
|
),
|
|
applied_modules as
|
|
(
|
|
select * from module_nodes where 1=0
|
|
union
|
|
select module_nodes.m
|
|
from
|
|
module_nodes
|
|
left join
|
|
(
|
|
module_arguments
|
|
left join
|
|
reached_values
|
|
on module_arguments.v = reached_values.v
|
|
)
|
|
on reached_values.v is null and
|
|
module_nodes.m = module_arguments.m
|
|
where module_arguments.m is null
|
|
)
|
|
select * from applied_modules;
|
|
m
|
|
m1
|
|
m2
|
|
drop table value_nodes, module_nodes, module_arguments, module_results;
|
|
#
|
|
# mdev-12519: recursive references in subqueries
|
|
#
|
|
create table t1 (lp char(4) not null, rp char(4) not null);
|
|
insert into t1 values
|
|
('p1','p2'), ('p2','p3'), ('p3','p4'), ('p4','p5'),
|
|
('p2','p7'), ('p7','p8'), ('p8','p3'), ('p8','p4');
|
|
set standard_compliant_cte=0;
|
|
with recursive
|
|
reachables(p) as
|
|
(
|
|
select lp from t1 where lp = 'p1'
|
|
union
|
|
select t1.rp from reachables, t1
|
|
where t1.lp = reachables.p
|
|
)
|
|
select * from reachables;
|
|
p
|
|
p1
|
|
p2
|
|
p3
|
|
p7
|
|
p4
|
|
p8
|
|
p5
|
|
with recursive
|
|
reachables(p) as
|
|
(
|
|
select lp from t1 where lp = 'p1'
|
|
union
|
|
select t1.rp from reachables, t1
|
|
where 'p3' not in (select * from reachables) and
|
|
t1.lp = reachables.p
|
|
)
|
|
select * from reachables;
|
|
p
|
|
p1
|
|
p2
|
|
p3
|
|
p7
|
|
with recursive
|
|
reachables(p) as
|
|
(
|
|
select lp from t1 where lp = 'p1'
|
|
union
|
|
select t1.rp from reachables, t1
|
|
where 'p3' not in (select p from reachables where p <= 'p5'
|
|
union
|
|
select p from reachables where p > 'p5') and
|
|
t1.lp = reachables.p
|
|
)
|
|
select * from reachables;
|
|
p
|
|
p1
|
|
p2
|
|
p3
|
|
p7
|
|
prepare stmt from "
|
|
with recursive
|
|
reachables(p) as
|
|
(
|
|
select lp from t1 where lp = 'p1'
|
|
union
|
|
select t1.rp from reachables, t1
|
|
where 'p3' not in (select p from reachables where p <= 'p5'
|
|
union
|
|
select p from reachables where p > 'p5') and
|
|
t1.lp = reachables.p
|
|
)
|
|
select * from reachables;
|
|
";
|
|
execute stmt;
|
|
p
|
|
p1
|
|
p2
|
|
p3
|
|
p7
|
|
execute stmt;
|
|
p
|
|
p1
|
|
p2
|
|
p3
|
|
p7
|
|
deallocate prepare stmt;
|
|
drop table t1;
|
|
create table objects(v char(4) not null);
|
|
insert into objects values
|
|
('v1'), ('v2'), ('v3'), ('v4'), ('v5'),
|
|
('v6'), ('v7'), ('v8'), ('v9'), ('v10');
|
|
create table modules(m char(4) not null);
|
|
insert into modules values
|
|
('m1'), ('m2'), ('m3'), ('m4');
|
|
create table module_arguments(m char(4) not null, v char(4) not null);
|
|
insert into module_arguments values
|
|
('m1','v3'), ('m1','v9'),
|
|
('m2','v4'), ('m2','v7'),
|
|
('m3','v6'), ('m4','v2');
|
|
create table module_results(m char(4) not null, v char(4) not null);
|
|
insert into module_results values
|
|
('m1','v4'),
|
|
('m2','v1'), ('m2','v6'),
|
|
('m3','v10'), ('m4','v7');
|
|
set standard_compliant_cte=0;
|
|
with recursive
|
|
reached_objects as
|
|
(
|
|
select v, 'init' as m from objects where v in ('v3','v7','v9')
|
|
union
|
|
select module_results.v, module_results.m from module_results, applied_modules
|
|
where module_results.m = applied_modules.m
|
|
),
|
|
applied_modules as
|
|
(
|
|
select * from modules where 1=0
|
|
union
|
|
select modules.m
|
|
from
|
|
modules
|
|
where
|
|
not exists (select * from module_arguments
|
|
where module_arguments.m = modules.m and
|
|
module_arguments.v not in
|
|
(select v from reached_objects))
|
|
)
|
|
select * from reached_objects;
|
|
v m
|
|
v3 init
|
|
v7 init
|
|
v9 init
|
|
v4 m1
|
|
v1 m2
|
|
v6 m2
|
|
v10 m3
|
|
with recursive
|
|
reached_objects as
|
|
(
|
|
select v, 'init' as m from objects where v in ('v3','v7','v9')
|
|
union
|
|
select module_results.v, module_results.m from module_results, applied_modules
|
|
where module_results.m = applied_modules.m
|
|
),
|
|
applied_modules as
|
|
(
|
|
select * from modules where 1=0
|
|
union
|
|
select modules.m
|
|
from
|
|
modules
|
|
where
|
|
'v6' not in (select v from reached_objects) and
|
|
not exists (select * from module_arguments
|
|
where module_arguments.m = modules.m and
|
|
module_arguments.v not in
|
|
(select v from reached_objects))
|
|
)
|
|
select * from reached_objects;
|
|
v m
|
|
v3 init
|
|
v7 init
|
|
v9 init
|
|
v4 m1
|
|
v1 m2
|
|
v6 m2
|
|
prepare stmt from "
|
|
with recursive
|
|
reached_objects as
|
|
(
|
|
select v, 'init' as m from objects where v in ('v3','v7','v9')
|
|
union
|
|
select module_results.v, module_results.m from module_results, applied_modules
|
|
where module_results.m = applied_modules.m
|
|
),
|
|
applied_modules as
|
|
(
|
|
select * from modules where 1=0
|
|
union
|
|
select modules.m
|
|
from
|
|
modules
|
|
where
|
|
'v6' not in (select v from reached_objects) and
|
|
not exists (select * from module_arguments
|
|
where module_arguments.m = modules.m and
|
|
module_arguments.v not in
|
|
(select v from reached_objects))
|
|
)
|
|
select * from reached_objects;
|
|
";
|
|
execute stmt;
|
|
v m
|
|
v3 init
|
|
v7 init
|
|
v9 init
|
|
v4 m1
|
|
v1 m2
|
|
v6 m2
|
|
execute stmt;
|
|
v m
|
|
v3 init
|
|
v7 init
|
|
v9 init
|
|
v4 m1
|
|
v1 m2
|
|
v6 m2
|
|
deallocate prepare stmt;
|
|
drop table objects, modules, module_arguments, module_results;
|
|
set standard_compliant_cte=default;
|
|
select @@standard_compliant_cte;
|
|
@@standard_compliant_cte
|
|
1
|
|
#
|
|
# mdev-12554: impossible where in recursive select
|
|
#
|
|
CREATE TABLE t1 (i int);
|
|
INSERT INTO t1 VALUES (1),(2);
|
|
WITH RECURSIVE
|
|
cte(f) AS ( SELECT i FROM t1 UNION SELECT f FROM t1, cte WHERE 1=0 )
|
|
SELECT * FROM cte;
|
|
f
|
|
1
|
|
2
|
|
DROP TABLE t1;
|
|
#
|
|
# mdev-12556: recursive execution uses Aria temporary tables
|
|
#
|
|
CREATE TABLE t (c1 varchar(255), c2 tinytext);
|
|
INSERT INTO t VALUES ('a','a'),('b','b'),('c','c'),('d','d');
|
|
ANALYZE WITH RECURSIVE cte(f) AS (
|
|
SELECT c1 FROM t
|
|
UNION
|
|
SELECT c1 FROM t, cte
|
|
) SELECT COUNT(*) FROM cte;
|
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
|
|
2 DERIVED t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
|
|
3 RECURSIVE UNION t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL 0.00 NULL NULL
|
|
WITH RECURSIVE cte(f) AS (
|
|
SELECT c1 FROM t
|
|
UNION
|
|
SELECT c1 FROM t, cte
|
|
) SELECT COUNT(*) FROM cte;
|
|
COUNT(*)
|
|
4
|
|
ANALYZE WITH RECURSIVE cte(f) AS (
|
|
SELECT c2 FROM t
|
|
UNION
|
|
SELECT c2 FROM t, cte
|
|
) SELECT COUNT(*) FROM cte;
|
|
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
|
|
2 DERIVED t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
|
|
3 RECURSIVE UNION t ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 4 4.00 100.00 100.00 Using join buffer (flat, BNL join)
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL 0.00 NULL NULL
|
|
WITH RECURSIVE cte(f) AS (
|
|
SELECT c2 FROM t
|
|
UNION
|
|
SELECT c2 FROM t, cte
|
|
) SELECT COUNT(*) FROM cte;
|
|
COUNT(*)
|
|
4
|
|
DROP TABLE t;
|
|
#
|
|
# mdev-12563: no recursive references on the top level of the CTE spec
|
|
#
|
|
CREATE TABLE t (i int);
|
|
INSERT INTO t VALUES (3), (1),(2);
|
|
SET standard_compliant_cte=0;
|
|
WITH RECURSIVE cte(f) AS (
|
|
SELECT i FROM t
|
|
UNION
|
|
SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte )
|
|
) SELECT * FROM cte;
|
|
f
|
|
3
|
|
1
|
|
2
|
|
WITH RECURSIVE cte(f) AS (
|
|
SELECT i FROM t
|
|
UNION
|
|
SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte WHERE i < 2 )
|
|
UNION
|
|
SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte WHERE i > 2 )
|
|
) SELECT * FROM cte;
|
|
f
|
|
3
|
|
1
|
|
2
|
|
WITH RECURSIVE cte(f) AS (
|
|
SELECT i FROM t
|
|
UNION
|
|
SELECT i FROM t
|
|
WHERE i NOT IN ( SELECT * FROM cte WHERE i < 2
|
|
UNION
|
|
SELECT * FROM cte WHERE i > 2)
|
|
) SELECT * FROM cte;
|
|
f
|
|
3
|
|
1
|
|
2
|
|
WITH RECURSIVE cte(f) AS (
|
|
SELECT i FROM t
|
|
UNION
|
|
SELECT i FROM t
|
|
WHERE i NOT IN ( SELECT * FROM t
|
|
WHERE i IN ( SELECT * FROM cte ) GROUP BY i )
|
|
) SELECT * FROM cte;
|
|
f
|
|
3
|
|
1
|
|
2
|
|
WITH RECURSIVE cte(f) AS (
|
|
SELECT i FROM t
|
|
UNION
|
|
SELECT i FROM t WHERE i NOT IN ( SELECT * FROM cte )
|
|
UNION
|
|
SELECT * FROM cte WHERE f > 2
|
|
) SELECT * FROM cte;
|
|
f
|
|
3
|
|
1
|
|
2
|
|
set standard_compliant_cte=default;
|
|
DROP TABLE t;
|
|
#
|
|
# mdev-14184: recursive CTE embedded into CTE with multiple references
|
|
#
|
|
WITH
|
|
cte1 AS (
|
|
SELECT n FROM (
|
|
WITH RECURSIVE rec_cte(n) AS (
|
|
SELECT 1 as n1
|
|
UNION ALL
|
|
SELECT n+1 as n2 FROM rec_cte WHERE n < 3
|
|
) SELECT n FROM rec_cte
|
|
) AS X
|
|
),
|
|
cte2 as (
|
|
SELECT 2 FROM cte1
|
|
)
|
|
SELECT *
|
|
FROM cte1;
|
|
n
|
|
1
|
|
2
|
|
3
|
|
#
|
|
# mdev-14629: a user-defined variable is defined by the recursive CTE
|
|
#
|
|
set @var=
|
|
(
|
|
with recursive cte_tab(a) as (
|
|
select 1
|
|
union
|
|
select a+1 from cte_tab
|
|
where a<3)
|
|
select count(*) from cte_tab
|
|
);
|
|
select @var;
|
|
@var
|
|
3
|
|
create table t1(a int, b int);
|
|
insert into t1 values (3,8),(1,5),(5,7),(7,4),(4,3);
|
|
set @var=
|
|
(
|
|
with recursive summ(a,s) as (
|
|
select 1, 0 union
|
|
select t1.b, t1.b+summ.s from summ, t1
|
|
where summ.a=t1.a)
|
|
select s from summ
|
|
order by a desc
|
|
limit 1
|
|
);
|
|
select @var;
|
|
@var
|
|
27
|
|
set @var=
|
|
(
|
|
with recursive
|
|
cte_1 as (
|
|
select 1
|
|
union
|
|
select * from cte_2),
|
|
cte_2 as (
|
|
select * from cte_1
|
|
union
|
|
select a from t1, cte_2
|
|
where t1.a=cte_2.a)
|
|
select * from cte_2
|
|
limit 1
|
|
);
|
|
ERROR HY000: Unacceptable mutual recursion with anchored table 'cte_1'
|
|
drop table t1;
|
|
#
|
|
# mdev-14777: crash caused by the same as in mdev-14755
|
|
#
|
|
CREATE TABLE t1 (i1 int NOT NULL, i2 int);
|
|
CREATE TABLE t2 (d1 int NOT NULL PRIMARY KEY);
|
|
CREATE TABLE t3 (i int );
|
|
insert into t1 select seq,seq from seq_1_to_100000;
|
|
insert into t2 select seq from seq_1000_to_100000;
|
|
insert into t3 select seq from seq_1_to_1000;
|
|
SELECT *
|
|
FROM
|
|
(
|
|
SELECT *
|
|
FROM
|
|
(
|
|
WITH RECURSIVE rt AS
|
|
(
|
|
SELECT i2 P, i1 C FROM t1 WHERE i1 IN (SELECT d1 FROM t2)
|
|
UNION
|
|
SELECT t1.i2 P, rt.C C FROM t1, rt
|
|
)
|
|
SELECT C,P
|
|
FROM ( SELECT P,C FROM rt WHERE NOT EXISTS (SELECT 1 FROM t1) ) Y
|
|
) X
|
|
WHERE 1 = 1
|
|
) K, t3;
|
|
C P i
|
|
drop table t1,t2,t3;
|
|
#
|
|
# mdev-14879: subquery with recursive reference in WHERE of CTE
|
|
#
|
|
create table flights
|
|
(departure varchar(32),
|
|
arrival varchar(32),
|
|
carrier varchar(20),
|
|
flight_number char(7));
|
|
insert into flights values
|
|
('Seattle', 'Frankfurt', 'Lufthansa', 'LH 491'),
|
|
('Seattle', 'Chicago', 'American', 'AA 2573'),
|
|
('Seattle', 'Los Angeles', 'Alaska Air', 'AS 410'),
|
|
('Chicago', 'New York', 'American', 'AA 375'),
|
|
('Chicago', 'Montreal', 'Air Canada', 'AC 3053'),
|
|
('Los Angeles', 'New York', 'Delta', 'DL 1197'),
|
|
('Moscow', 'Tokyo', 'Aeroflot', 'SU 264'),
|
|
('New York', 'Paris', 'Air France', 'AF 23'),
|
|
('Frankfurt', 'Moscow', 'Lufthansa', 'LH 1444'),
|
|
('Tokyo', 'Seattle', 'ANA', 'NH 178'),
|
|
('Los Angeles', 'Tokyo', 'ANA', 'NH 175'),
|
|
('Moscow', 'Los Angeles', 'Aeroflot', 'SU 106'),
|
|
('Montreal', 'Paris', 'Air Canada', 'AC 870'),
|
|
('Cairo', 'Paris', 'Air France', 'AF 503'),
|
|
('New York', 'Seattle', 'American', 'AA 45'),
|
|
('Paris', 'Chicago', 'Air France', 'AF 6734');
|
|
with recursive destinations (city) as
|
|
( select a.arrival from flights a where a.departure='Cairo'
|
|
union
|
|
select b.arrival from destinations r, flights b where r.city=b.departure)
|
|
select * from destinations;
|
|
city
|
|
Paris
|
|
Chicago
|
|
New York
|
|
Montreal
|
|
Seattle
|
|
Frankfurt
|
|
Los Angeles
|
|
Moscow
|
|
Tokyo
|
|
set standard_compliant_cte=0;
|
|
with recursive destinations (city, legs) as
|
|
(
|
|
select a.arrival, 1 from flights a where a.departure='Cairo'
|
|
union
|
|
select b.arrival, r.legs + 1 from destinations r, flights b
|
|
where r.city=b.departure and b.arrival not in (select city from destinations)
|
|
)
|
|
select * from destinations;
|
|
city legs
|
|
Paris 1
|
|
Chicago 2
|
|
New York 3
|
|
Montreal 3
|
|
Seattle 4
|
|
Frankfurt 5
|
|
Los Angeles 5
|
|
Moscow 6
|
|
Tokyo 6
|
|
explain extended with recursive destinations (city, legs) as
|
|
(
|
|
select a.arrival, 1 from flights a where a.departure='Cairo'
|
|
union
|
|
select b.arrival, r.legs + 1 from destinations r, flights b
|
|
where r.city=b.departure and b.arrival not in (select city from destinations)
|
|
)
|
|
select * from destinations;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 16 100.00
|
|
2 DERIVED a ALL NULL NULL NULL NULL 16 100.00 Using where
|
|
3 RECURSIVE UNION b ALL NULL NULL NULL NULL 16 100.00 Using where
|
|
3 RECURSIVE UNION <derived2> ref key0 key0 35 test.b.departure 2 100.00
|
|
4 DEPENDENT SUBQUERY <derived2> ALL NULL NULL NULL NULL 16 100.00 Using where
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
Warnings:
|
|
Note 1003 with recursive destinations(city,legs) as (/* select#2 */ select `test`.`a`.`arrival` AS `city`,1 AS `legs` from `test`.`flights` `a` where `test`.`a`.`departure` = 'Cairo' union /* select#3 */ select `test`.`b`.`arrival` AS `arrival`,`r`.`legs` + 1 AS `r.legs + 1` from `destinations` `r` join `test`.`flights` `b` where `r`.`city` = `test`.`b`.`departure` and !<in_optimizer>(`test`.`b`.`arrival`,<exists>(/* select#4 */ select `destinations`.`city` from `destinations` where trigcond(`test`.`b`.`arrival` = `destinations`.`city` or `destinations`.`city` is null) having trigcond(`destinations`.`city` is null))))/* select#1 */ select `destinations`.`city` AS `city`,`destinations`.`legs` AS `legs` from `destinations`
|
|
set standard_compliant_cte=default;
|
|
drop table flights;
|
|
#
|
|
# MDEV-15162: Setting user variable in recursive CTE
|
|
#
|
|
SET @c=1;
|
|
WITH RECURSIVE cte AS
|
|
(SELECT 5
|
|
UNION
|
|
SELECT @c:=@c+1 FROM cte WHERE @c<3)
|
|
SELECT * FROM cte;
|
|
5
|
|
5
|
|
2
|
|
3
|
|
#
|
|
# MDEV-15575: using recursive cte with big_tables enabled
|
|
#
|
|
set big_tables=1;
|
|
with recursive qn as
|
|
(select 123 as a union all select 1+a from qn where a<130)
|
|
select * from qn;
|
|
a
|
|
123
|
|
124
|
|
125
|
|
126
|
|
127
|
|
128
|
|
129
|
|
130
|
|
set big_tables=default;
|
|
#
|
|
# MDEV-15571: using recursive cte with big_tables enabled
|
|
#
|
|
create table t1 (a bigint);
|
|
insert into t1 values(1);
|
|
set big_tables=1;
|
|
with recursive qn as
|
|
(
|
|
select a from t1
|
|
union all
|
|
select a*2000 from qn where a<10000000000000000000
|
|
)
|
|
select * from qn;
|
|
ERROR 22003: BIGINT value is out of range in '`qn`.`a` * 2000'
|
|
set big_tables=default;
|
|
drop table t1;
|
|
#
|
|
# MDEV-15556: using recursive cte with big_tables enabled
|
|
# when recursive tables are accessed by key
|
|
#
|
|
SET big_tables=1;
|
|
CREATE TABLE t1 (id int, name char(10), leftpar int, rightpar int);
|
|
INSERT INTO t1 VALUES
|
|
(1, "A", 2, 3), (2, "LA", 4, 5), (4, "LLA", 6, 7),
|
|
(6, "LLLA", NULL, NULL), (7, "RLLA", NULL, NULL), (5, "RLA", 8, 9),
|
|
(8, "LRLA", NULL, NULL), (9, "RRLA", NULL, NULL), (3, "RA", 10, 11),
|
|
(10, "LRA", 12, 13), (11, "RRA", 14, 15), (15, "RRRA", NULL, NULL),
|
|
(16, "B", 17, 18), (17, "LB", NULL, NULL), (18, "RB", NULL, NULL);
|
|
CREATE TABLE t2 SELECT * FROM t1 ORDER BY rand();
|
|
WITH RECURSIVE tree_of_a AS
|
|
(SELECT *, cast(id AS char(200)) AS path FROM t2 WHERE name="A"
|
|
UNION ALL
|
|
SELECT t2.*, concat(tree_of_a.path,",",t2.id)
|
|
FROM t2 JOIN tree_of_a ON t2.id=tree_of_a.leftpar
|
|
UNION ALL
|
|
SELECT t2.*, concat(tree_of_a.path,",",t2.id)
|
|
FROM t2 JOIN tree_of_a ON t2.id=tree_of_a.rightpar)
|
|
SELECT * FROM tree_of_a
|
|
ORDER BY path;
|
|
id name leftpar rightpar path
|
|
1 A 2 3 1
|
|
2 LA 4 5 1,2
|
|
4 LLA 6 7 1,2,4
|
|
6 LLLA NULL NULL 1,2,4,6
|
|
7 RLLA NULL NULL 1,2,4,7
|
|
5 RLA 8 9 1,2,5
|
|
8 LRLA NULL NULL 1,2,5,8
|
|
9 RRLA NULL NULL 1,2,5,9
|
|
3 RA 10 11 1,3
|
|
10 LRA 12 13 1,3,10
|
|
11 RRA 14 15 1,3,11
|
|
15 RRRA NULL NULL 1,3,11,15
|
|
EXPLAIN WITH RECURSIVE tree_of_a AS
|
|
(SELECT *, cast(id AS char(200)) AS path FROM t2 WHERE name="A"
|
|
UNION ALL
|
|
SELECT t2.*, concat(tree_of_a.path,",",t2.id)
|
|
FROM t2 JOIN tree_of_a ON t2.id=tree_of_a.leftpar
|
|
UNION ALL
|
|
SELECT t2.*, concat(tree_of_a.path,",",t2.id)
|
|
FROM t2 JOIN tree_of_a ON t2.id=tree_of_a.rightpar)
|
|
SELECT * FROM tree_of_a
|
|
ORDER BY path;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 15 Using filesort
|
|
2 DERIVED t2 ALL NULL NULL NULL NULL 15 Using where
|
|
3 RECURSIVE UNION t2 ALL NULL NULL NULL NULL 15 Using where
|
|
3 RECURSIVE UNION <derived2> ref key0 key0 5 test.t2.id 2
|
|
4 RECURSIVE UNION t2 ALL NULL NULL NULL NULL 15 Using where
|
|
4 RECURSIVE UNION <derived2> ref key0 key0 5 test.t2.id 2
|
|
NULL UNION RESULT <union2,3,4> ALL NULL NULL NULL NULL NULL
|
|
DROP TABLE t1,t2;
|
|
SET big_tables=0;
|
|
#
|
|
# MDEV-15840: recursive tables are accessed by key
|
|
# (the same problem as for MDEV-15556)
|
|
#
|
|
CREATE TABLE t1 (p1 text,k2 int, p2 text, k1 int);
|
|
INSERT INTO t1 select seq, seq, seq, seq from seq_1_to_1000;
|
|
CREATE PROCEDURE getNums()
|
|
BEGIN
|
|
WITH RECURSIVE cte as
|
|
(
|
|
SELECT * FROM t1
|
|
UNION
|
|
SELECT c.* FROM t1 c JOIN cte p ON c.p1 = p.p2 AND c.k2 = p.k1
|
|
)
|
|
SELECT * FROM cte LIMIT 10;
|
|
END |
|
|
call getNums();
|
|
p1 k2 p2 k1
|
|
1 1 1 1
|
|
2 2 2 2
|
|
3 3 3 3
|
|
4 4 4 4
|
|
5 5 5 5
|
|
6 6 6 6
|
|
7 7 7 7
|
|
8 8 8 8
|
|
9 9 9 9
|
|
10 10 10 10
|
|
DROP PROCEDURE getNums;
|
|
DROP TABLE t1;
|
|
#
|
|
# MDEV-15894: aggregate/winfow functions in non-recorsive part
|
|
#
|
|
create table t1(b int);
|
|
insert into t1 values(10),(20),(10);
|
|
with recursive qn as
|
|
(select max(b) as a from t1 union
|
|
select a from qn)
|
|
select * from qn;
|
|
a
|
|
20
|
|
with recursive qn as
|
|
(select rank() over (order by b) as a from t1 union
|
|
select a from qn)
|
|
select * from qn;
|
|
a
|
|
1
|
|
3
|
|
drop table t1;
|
|
#
|
|
# MDEV-16086: tmp table for CTE is created as ARIA tables
|
|
#
|
|
CREATE TABLE t1 (
|
|
Id int(11) not null AUTO_INCREMENT,
|
|
Parent varchar(15) not null,
|
|
Child varchar(15) not null,
|
|
PRIMARY KEY (Id)
|
|
) ENGINE = MyISAM;
|
|
INSERT INTO t1 (Parent, Child) VALUES
|
|
('123', '456'),('456', '789'),('321', '654'),('654', '987');
|
|
WITH RECURSIVE cte AS
|
|
( SELECT b.Parent,
|
|
b.Child,
|
|
CAST(CONCAT(b.Child,',') AS CHAR(513)) Path
|
|
FROM t1 b
|
|
LEFT OUTER JOIN t1 bc ON b.Child = bc.Parent
|
|
WHERE bc.Id IS NULL
|
|
UNION ALL SELECT c.Parent,
|
|
c.Child,
|
|
CONCAT(p.Path,c.Child,',') Path
|
|
FROM t1 c
|
|
INNER JOIN cte p ON c.Child = p.Parent)
|
|
SELECT *
|
|
FROM cte
|
|
ORDER BY Path;
|
|
Parent Child Path
|
|
456 789 789,
|
|
123 456 789,456,
|
|
654 987 987,
|
|
321 654 987,654,
|
|
DROP TABLE t1;
|
|
#
|
|
# MDEV-16212: recursive CTE with global ORDER BY
|
|
#
|
|
set statement max_recursive_iterations = 2 for
|
|
WITH RECURSIVE qn AS (
|
|
SELECT 1 FROM dual UNION ALL
|
|
SELECT 1 FROM qn
|
|
ORDER BY (SELECT * FROM qn))
|
|
SELECT count(*) FROM qn;
|
|
ERROR 42000: This version of MariaDB doesn't yet support 'global ORDER_BY/LIMIT in recursive CTE spec'
|
|
#
|
|
# MDEV-15581: mix of ALL and DISTINCT UNION in recursive CTE
|
|
#
|
|
create table t1(a int);
|
|
insert into t1 values(1),(2);
|
|
insert into t1 values(1),(2);
|
|
set @c=0, @d=0;
|
|
WITH RECURSIVE qn AS
|
|
(
|
|
select 1,0 as col from t1
|
|
union distinct
|
|
select 1,0 from t1
|
|
union all
|
|
select 3, 0*(@c:=@c+1) from qn where @c<1
|
|
union all
|
|
select 3, 0*(@d:=@d+1) from qn where @d<1
|
|
)
|
|
select * from qn;
|
|
ERROR 42000: This version of MariaDB doesn't yet support 'mix of ALL and DISTINCT UNION operations in recursive CTE spec'
|
|
drop table t1;
|
|
#
|
|
# MDEV-16629: function with recursive CTE using a base table
|
|
#
|
|
CREATE TABLE t1 (id int);
|
|
INSERT INTO t1 VALUES (0), (1),(2);
|
|
WITH recursive cte AS
|
|
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
|
|
SELECT count(id) FROM cte;
|
|
count(id)
|
|
4
|
|
CREATE OR REPLACE FUNCTION func() RETURNS int
|
|
RETURN
|
|
(
|
|
WITH recursive cte AS
|
|
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
|
|
SELECT count(id) FROM cte
|
|
);
|
|
SELECT func();
|
|
func()
|
|
4
|
|
DROP FUNCTION func;
|
|
DROP TABLE t1;
|
|
#
|
|
# MDEV-16661: function with recursive CTE using no base tables
|
|
# (fixed by the patch for MDEV-16629)
|
|
#
|
|
CREATE OR REPLACE FUNCTION func() RETURNS int
|
|
RETURN
|
|
(
|
|
WITH RECURSIVE cte AS
|
|
(SELECT 1 as id UNION SELECT * FROM cte)
|
|
SELECT count(id) FROM cte
|
|
);
|
|
SELECT func();
|
|
func()
|
|
1
|
|
DROP FUNCTION func;
|
|
#
|
|
# MDEV-17024: two materialized CTEs using the same recursive CTE
|
|
#
|
|
create table t1 (id int);
|
|
insert into t1 values (1), (2), (3);
|
|
with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte1, cte2;
|
|
c1 c2
|
|
2 1
|
|
explain extended with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte1, cte2;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 6 100.00
|
|
1 PRIMARY <derived5> ALL NULL NULL NULL NULL 6 100.00 Using join buffer (flat, BNL join)
|
|
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
4 DERIVED <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
4 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
|
5 DERIVED <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
5 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
|
Warnings:
|
|
Note 1003 with recursive rcte(a) as (/* select#2 */ select 1 AS `a` union /* select#3 */ select cast(`rcte`.`a` + 1 as unsigned) AS `cast(a+1 as unsigned)` from `rcte` where `rcte`.`a` < 10), cte1 as (/* select#4 */ select count(0) AS `c1` from `rcte` join `test`.`t1` where `rcte`.`a` between 3 and 5 and `test`.`t1`.`id` = `rcte`.`a` - 3), cte2 as (/* select#5 */ select count(0) AS `c2` from `rcte` join `test`.`t1` where `rcte`.`a` between 7 and 8 and `test`.`t1`.`id` = `rcte`.`a` - 7)/* select#1 */ select `cte1`.`c1` AS `c1`,`cte2`.`c2` AS `c2` from `cte1` join `cte2`
|
|
prepare stmt from "with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte1, cte2";
|
|
execute stmt;
|
|
c1 c2
|
|
2 1
|
|
execute stmt;
|
|
c1 c2
|
|
2 1
|
|
create table t2 (c1 int, c2 int);
|
|
create procedure p() insert into t2 with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte1, cte2;
|
|
call p();
|
|
select * from t2;
|
|
c1 c2
|
|
2 1
|
|
with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte1;
|
|
c1
|
|
2
|
|
with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from t1),
|
|
cte2 as
|
|
(select count(*) as c2 from t2)
|
|
select * from cte1,cte2;
|
|
c1 c2
|
|
3 1
|
|
with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte1, cte2 where cte1.c1 = 3;
|
|
c1 c2
|
|
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;
|
|
c2 c1
|
|
1 2
|
|
explain extended with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte2, cte1;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived5> ALL NULL NULL NULL NULL 6 100.00
|
|
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 6 100.00 Using join buffer (flat, BNL join)
|
|
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
5 DERIVED <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
5 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
|
4 DERIVED <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
4 DERIVED t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
|
Warnings:
|
|
Note 1003 with recursive rcte(a) as (/* select#2 */ select 1 AS `a` union /* select#3 */ select cast(`rcte`.`a` + 1 as unsigned) AS `cast(a+1 as unsigned)` from `rcte` where `rcte`.`a` < 10), cte1 as (/* select#4 */ select count(0) AS `c1` from `rcte` join `test`.`t1` where `rcte`.`a` between 3 and 5 and `test`.`t1`.`id` = `rcte`.`a` - 3), cte2 as (/* select#5 */ select count(0) AS `c2` from `rcte` join `test`.`t1` where `rcte`.`a` between 7 and 8 and `test`.`t1`.`id` = `rcte`.`a` - 7)/* select#1 */ select `cte2`.`c2` AS `c2`,`cte1`.`c1` AS `c1` from `cte2` join `cte1`
|
|
prepare stmt from "with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte2, cte1";
|
|
execute stmt;
|
|
c2 c1
|
|
1 2
|
|
execute stmt;
|
|
c2 c1
|
|
1 2
|
|
drop procedure p;
|
|
drop table t2;
|
|
create table t2 (c1 int, c2 int);
|
|
create procedure p() insert into t2 with recursive
|
|
rcte(a) as
|
|
(select 1 union select cast(a+1 as unsigned) from rcte where a < 10),
|
|
cte1 as
|
|
(select count(*) as c1 from rcte,t1 where a between 3 and 5 and id=a-3),
|
|
cte2 as
|
|
(select count(*) as c2 from rcte,t1 where a between 7 and 8 and id=a-7)
|
|
select * from cte2, cte1;
|
|
call p();
|
|
select * from t2;
|
|
c1 c2
|
|
1 2
|
|
drop procedure p;
|
|
drop table t1,t2;
|
|
#
|
|
# MDEV-17201: recursive part with LIMIT
|
|
#
|
|
CREATE TABLE purchases (
|
|
id int unsigned NOT NULL AUTO_INCREMENT,
|
|
pdate date NOT NULL,
|
|
quantity int unsigned NOT NULL,
|
|
p_id int unsigned NOT NULL,
|
|
PRIMARY KEY (id)
|
|
);
|
|
INSERT INTO purchases(pdate, quantity, p_id) VALUES
|
|
('2014-11-01',5 ,1),('2014-11-03', 3 ,1),
|
|
('2014-11-01',2 ,2),('2014-11-03', 4 ,2);
|
|
CREATE TABLE expired (
|
|
edate date NOT NULL,
|
|
quantity int unsigned NOT NULL,
|
|
p_id int unsigned NOT NULL,
|
|
PRIMARY KEY (edate,p_id)
|
|
);
|
|
INSERT INTO expired VALUES ('2014-11-12', 5 ,1),('2014-11-08', 1 ,2);
|
|
WITH RECURSIVE expired_map AS (
|
|
SELECT edate AS expired_date,
|
|
CAST(NULL AS date) AS purchase_date,
|
|
0 AS quantity,
|
|
e.p_id,
|
|
(SELECT MAX(id)+1 FROM purchases p
|
|
WHERE pdate <= edate AND p.p_id =p_id) AS purchase_processed,
|
|
quantity AS unresolved
|
|
FROM expired e
|
|
UNION
|
|
( SELECT expired_date,
|
|
pdate,
|
|
IF(p.quantity < m.unresolved, p.quantity, m.unresolved),
|
|
p.p_id,
|
|
p.id,
|
|
IF(p.quantity < m.unresolved, m.unresolved - p.quantity, 0)
|
|
FROM purchases p JOIN expired_map m ON p.p_id = m.p_id
|
|
WHERE p.id < m.purchase_processed AND m.unresolved > 0
|
|
ORDER BY p.id DESC
|
|
LIMIT 1
|
|
)
|
|
)
|
|
SELECT * FROM expired_map;
|
|
expired_date purchase_date quantity p_id purchase_processed unresolved
|
|
2014-11-12 NULL 0 1 5 5
|
|
2014-11-08 NULL 0 2 5 1
|
|
2014-11-08 2014-11-03 1 2 4 0
|
|
DROP TABLE purchases, expired;
|
|
#
|
|
# MDEV-17635: Two recursive CTEs, the second using the first
|
|
#
|
|
WITH RECURSIVE
|
|
x AS (SELECT 0 as k UNION ALL SELECT k + 1 FROM x WHERE k < 1),
|
|
z AS
|
|
( SELECT k1 AS cx, k2 AS cy, k1, k2
|
|
FROM (SELECT k AS k1 FROM x) x1 JOIN (SELECT k AS k2 FROM x) y1
|
|
UNION
|
|
SELECT 1,1,1,1 FROM z)
|
|
SELECT * FROM z;
|
|
cx cy k1 k2
|
|
0 0 0 0
|
|
1 0 1 0
|
|
0 1 0 1
|
|
1 1 1 1
|
|
# https://wiki.postgresql.org/wiki/Mandelbrot_set:
|
|
WITH RECURSIVE x(i) AS (
|
|
SELECT CAST(0 AS DECIMAL(13, 10))
|
|
UNION ALL
|
|
SELECT i + 1
|
|
FROM x
|
|
WHERE i < 101
|
|
),
|
|
Z(Ix, Iy, Cx, Cy, X, Y, I) AS (
|
|
SELECT Ix, Iy, X, Y, X, Y, 0
|
|
FROM (SELECT CAST(-2.2 + 0.031 * i AS DECIMAL(13, 10)) AS X,
|
|
i AS Ix FROM x) AS xgen
|
|
CROSS JOIN (
|
|
SELECT CAST(-1.5 + 0.031 * i AS DECIMAL(13, 10)) AS Y,
|
|
i AS iY FROM x
|
|
) AS ygen
|
|
UNION ALL
|
|
SELECT Ix, Iy, Cx, Cy,
|
|
CAST(X * X - Y * Y + Cx AS DECIMAL(13, 10)) AS X,
|
|
CAST(Y * X * 2 + Cy AS DECIMAL(13, 10)), I + 1
|
|
FROM Z
|
|
WHERE X * X + Y * Y < 16.0
|
|
AND I < 27
|
|
),
|
|
Zt (Ix, Iy, I) AS (
|
|
SELECT Ix, Iy, MAX(I) AS I
|
|
FROM Z
|
|
GROUP BY Iy, Ix
|
|
ORDER BY Iy, Ix
|
|
)
|
|
SELECT GROUP_CONCAT(
|
|
SUBSTRING(
|
|
' .,,,-----++++%%%%@@@@#### ',
|
|
GREATEST(I, 1),
|
|
1
|
|
) ORDER BY Ix SEPARATOR ''
|
|
) AS 'Mandelbrot Set'
|
|
FROM Zt
|
|
GROUP BY Iy
|
|
ORDER BY Iy;
|
|
Mandelbrot Set
|
|
....................................................................................
|
|
.......................................................................................
|
|
.........................................................................................
|
|
...........................................................................................
|
|
....................................................,,,,,,,,,.................................
|
|
................................................,,,,,,,,,,,,,,,,,,.............................
|
|
..............................................,,,,,,,,,,,,,,,,,,,,,,,,..........................
|
|
............................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,........................
|
|
..........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,......................
|
|
.........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,....................
|
|
........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...................
|
|
.......................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.................
|
|
.......................................,,,,,,,,,,,,,,,,,,,,,,,,--,,,,,,,,,,,,,,,,,,,,................
|
|
......................................,,,,,,,,,,,,,,,,,,,,,,,,,,-+--,,,,,,,,,,,,,,,,,,,...............
|
|
....................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----,,,,,,,,,,,,,,,,,,,..............
|
|
...................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,--- -----,,,,,,,,,,,,,,,,,.............
|
|
.................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---++--++,,,,,,,,,,,,,,,,,,............
|
|
................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----%++---,,,,,,,,,,,,,,,,,............
|
|
..............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+%----,,,,,,,,,,,,,,,,,,...........
|
|
.............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----- %%+----,,,,,,,,,,,,,,,,,,..........
|
|
...........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---%-+% ----,,,,,,,,,,,,,,,,,,,.........
|
|
..........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---+ +## %+%---,,,,,,,,,,,,,,,,,,.........
|
|
........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----# # +---,,,,,,,,,,,,,,,,,,........
|
|
.......................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------% %-----,,,,,,,,,,,,,,,,,........
|
|
.....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---------+ ------,,,,,,,,,,,,,,,,,.......
|
|
....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----------+@ +-----------,,,,,,,,,,,,.......
|
|
..................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----@-------++ ++-----------,,,,,,,,,,,,......
|
|
.................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--+@% ---+ +@%%@ %%+@+@%------+-,,,,,,,,,,,......
|
|
................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---- # ++% % @-----++--,,,,,,,,,,,.....
|
|
..............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----+ % %%++ %+%@-,,,,,,,,,,,.....
|
|
.............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+# #% ++-,,,,,,,,,,,,....
|
|
............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------+ @---,,,,,,,,,,,,....
|
|
..........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------++% ---,,,,,,,,,,,,....
|
|
.........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--------+ + %+---,,,,,,,,,,,,,...
|
|
........,,,,,,,,,,,,,,,,,,,,,--------------------@ +----,,,,,,,,,,,,...
|
|
.......,,,,,,,,,,,,,,,,,,,,,,- +-----------------+ ----,,,,,,,,,,,,...
|
|
.......,,,,,,,,,,,,,,,,,,,,,--++------+---------+% +++--,,,,,,,,,,,,..
|
|
......,,,,,,,,,,,,,,,,,,,,,,--%+-----++--------- #+-,,,,,,,,,,,,..
|
|
.....,,,,,,,,,,,,,,,,,,,,,,----#%++--+@ -+-----+% --,,,,,,,,,,,,..
|
|
.....,,,,,,,,,,,,,,,,,,,,,,-----+## ++@ + +----% +--,,,,,,,,,,,,,..
|
|
....,,,,,,,,,,,,,,,,,,,,,,------+@ @ @@++++# +--,,,,,,,,,,,,,..
|
|
....,,,,,,,,,,,,,,,,,,,,,-------% #++% -,,,,,,,,,,,,,..
|
|
...,,,,,,,,,,,,,,,,,,,,,------++%# %%@ %-,,,,,,,,,,,,,,.
|
|
...,,,,,,,,,,,,,,,,,,,--------+ % +--,,,,,,,,,,,,,,.
|
|
...,,,,,,,,,,,,,,,,,,-----+--++@ # --,,,,,,,,,,,,,,.
|
|
..,,,,,,,,,,,,,,,,,-------%+++% @--,,,,,,,,,,,,,,,.
|
|
..,,,,,,,,,,,-------------+ @#@ ---,,,,,,,,,,,,,,,.
|
|
..,,,,,,,,,---@--------@-+% +---,,,,,,,,,,,,,,,.
|
|
..,,,,,------- +-++++-+%%% +----,,,,,,,,,,,,,,,.
|
|
..,,,,,,------%--------++% +----,,,,,,,,,,,,,,,.
|
|
..,,,,,,,,,,--+----------++# ---,,,,,,,,,,,,,,,.
|
|
..,,,,,,,,,,,,------------+@@@% +--,,,,,,,,,,,,,,,.
|
|
..,,,,,,,,,,,,,,,,,------- +++% %--,,,,,,,,,,,,,,,.
|
|
...,,,,,,,,,,,,,,,,,,---------+@ @ --,,,,,,,,,,,,,,.
|
|
...,,,,,,,,,,,,,,,,,,,,------- # %@ +--,,,,,,,,,,,,,,.
|
|
...,,,,,,,,,,,,,,,,,,,,,-------++@ %+ %-,,,,,,,,,,,,,,.
|
|
....,,,,,,,,,,,,,,,,,,,,,------- %++% %-,,,,,,,,,,,,,..
|
|
....,,,,,,,,,,,,,,,,,,,,,,------+# %# #@ ++++ +--,,,,,,,,,,,,,..
|
|
.....,,,,,,,,,,,,,,,,,,,,,,-----+ %%++% +@+----+ +--,,,,,,,,,,,,,..
|
|
.....,,,,,,,,,,,,,,,,,,,,,,,---%+++--+#+--------% #--,,,,,,,,,,,,..
|
|
......,,,,,,,,,,,,,,,,,,,,,,--++-----%%--------- @#--,,,,,,,,,,,,..
|
|
.......,,,,,,,,,,,,,,,,,,,,,---------------------+@ +-++,,,,,,,,,,,,...
|
|
........,,,,,,,,,,,,,,,,,,,,,--------------------+ ----,,,,,,,,,,,,...
|
|
.........,,,,,,,,,,,,,,,,,,,,----,,,------------- #+----,,,,,,,,,,,,...
|
|
..........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------+ + +---,,,,,,,,,,,,,...
|
|
...........,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--------+%# #---,,,,,,,,,,,,....
|
|
............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------+# @ @---,,,,,,,,,,,,....
|
|
.............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+# + @--,,,,,,,,,,,,....
|
|
..............,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---+% %+@ %+-+ +++%-,,,,,,,,,,,.....
|
|
................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----% %@++ # % -----++-,,,,,,,,,,,,.....
|
|
.................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-- ++ ---+ + +%@ %++++++------%-,,,,,,,,,,,......
|
|
...................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---- -------++ +------------,,,,,,,,,,,,......
|
|
....................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----------+% +--------,,,,,,,,,,,,,,,.......
|
|
......................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,--------+# -----,,,,,,,,,,,,,,,,,,.......
|
|
.......................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-------+ #----,,,,,,,,,,,,,,,,,,........
|
|
.........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,----+% %#---,,,,,,,,,,,,,,,,,,,........
|
|
..........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---+%+%@ %+%%--,,,,,,,,,,,,,,,,,,.........
|
|
............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---+-+% %----,,,,,,,,,,,,,,,,,,..........
|
|
.............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+%@+---,,,,,,,,,,,,,,,,,,,..........
|
|
...............................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----+%----,,,,,,,,,,,,,,,,,,...........
|
|
................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-----%+ +--,,,,,,,,,,,,,,,,,............
|
|
..................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,---++----,,,,,,,,,,,,,,,,,.............
|
|
...................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,---@-----,,,,,,,,,,,,,,,,,.............
|
|
.....................................,,,,,,,,,,,,,,,,,,,,,,,,,,,-----,,,,,,,,,,,,,,,,,,,..............
|
|
.....................................,,,,,,,,,,,,,,,,,,,,,,,,,,--%,,,,,,,,,,,,,,,,,,,,...............
|
|
.......................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.................
|
|
........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,..................
|
|
........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...................
|
|
.........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,....................
|
|
..........................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,......................
|
|
............................................,,,,,,,,,,,,,,,,,,,,,,,,,,,,........................
|
|
.............................................,,,,,,,,,,,,,,,,,,,,,,,,..........................
|
|
................................................,,,,,,,,,,,,,,,,,.............................
|
|
.....................................................,,,,....................................
|
|
...........................................................................................
|
|
.........................................................................................
|
|
......................................................................................
|
|
....................................................................................
|
|
.................................................................................
|
|
..............................................................................
|
|
...........................................................................
|
|
........................................................................
|
|
#
|
|
# MDEV-17871: EXPLAIN for query with not used recursive cte
|
|
#
|
|
create table t1 (a int);
|
|
insert into t1 values (2), (1), (4), (3);
|
|
explain extended
|
|
with recursive cte as
|
|
(select * from t1 where a=1 union select a+1 from cte where a<3)
|
|
select * from cte as t;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
|
|
2 DERIVED t1 ALL NULL NULL NULL NULL 4 100.00 Using where
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 4 100.00 Using where
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
Warnings:
|
|
Note 1003 with recursive cte as (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 union /* select#3 */ select `cte`.`a` + 1 AS `a+1` from `cte` where `cte`.`a` < 3)/* select#1 */ select `t`.`a` AS `a` from `cte` `t`
|
|
with recursive cte as
|
|
(select * from t1 where a=1 union select a+1 from cte where a<3)
|
|
select * from cte as t;
|
|
a
|
|
1
|
|
2
|
|
3
|
|
explain extended
|
|
with recursive cte as
|
|
(select * from t1 where a=1 union select a+1 from cte where a<3)
|
|
select * from t1 as t;
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY t ALL NULL NULL NULL NULL 4 100.00
|
|
Warnings:
|
|
Note 1003 with recursive cte as (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 union /* select#3 */ select `cte`.`a` + 1 AS `a+1` from `cte` where `cte`.`a` < 3)/* select#1 */ select `test`.`t`.`a` AS `a` from `test`.`t1` `t`
|
|
with recursive cte as
|
|
(select * from t1 where a=1 union select a+1 from cte where a<3)
|
|
select * from t1 as t;
|
|
a
|
|
2
|
|
1
|
|
4
|
|
3
|
|
create table t2 ( i1 int, i2 int);
|
|
insert into t2 values (1,1),(2,2);
|
|
explain
|
|
with recursive cte as
|
|
( select * from t2 union select s1.* from t2 as s1, cte where s1.i1 = cte.i2 )
|
|
select * from t2 as t;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY t ALL NULL NULL NULL NULL 2
|
|
drop table t1,t2;
|
|
#
|
|
# MDEV-22042: ANALYZE of query using stored function and recursive CTE
|
|
#
|
|
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);
|
|
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$$
|
|
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);
|
|
fv
|
|
NULL
|
|
explain 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);
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
|
|
1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 23 func 1
|
|
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2
|
|
4 DERIVED t2 const PRIMARY PRIMARY 22 const 1 Using index
|
|
5 RECURSIVE UNION <derived4> ALL NULL NULL NULL NULL 2 Using where
|
|
5 RECURSIVE UNION tt2 ref b1 b1 23 cte.a2 2
|
|
NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL
|
|
analyze format=json 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);
|
|
ANALYZE
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"r_loops": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"const_condition": "1",
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"r_loops": 1,
|
|
"rows": 3,
|
|
"r_rows": 3,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100
|
|
},
|
|
"table": {
|
|
"table_name": "<subquery3>",
|
|
"access_type": "eq_ref",
|
|
"possible_keys": ["distinct_key"],
|
|
"key": "distinct_key",
|
|
"key_length": "23",
|
|
"used_key_parts": ["a2"],
|
|
"ref": ["func"],
|
|
"r_loops": 3,
|
|
"rows": 1,
|
|
"r_rows": 0.3333,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100,
|
|
"materialized": {
|
|
"unique": 1,
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"table": {
|
|
"table_name": "<derived4>",
|
|
"access_type": "ALL",
|
|
"r_loops": 1,
|
|
"rows": 2,
|
|
"r_rows": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union4,5>",
|
|
"access_type": "ALL",
|
|
"r_loops": 0,
|
|
"r_rows": null,
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 4,
|
|
"r_loops": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"table": {
|
|
"table_name": "t2",
|
|
"access_type": "const",
|
|
"possible_keys": ["PRIMARY"],
|
|
"key": "PRIMARY",
|
|
"key_length": "22",
|
|
"used_key_parts": ["a2"],
|
|
"ref": ["const"],
|
|
"r_loops": 0,
|
|
"rows": 1,
|
|
"r_rows": null,
|
|
"filtered": 100,
|
|
"r_filtered": null,
|
|
"using_index": true
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 5,
|
|
"operation": "UNION",
|
|
"r_loops": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"table": {
|
|
"table_name": "<derived4>",
|
|
"access_type": "ALL",
|
|
"r_loops": 1,
|
|
"rows": 2,
|
|
"r_rows": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100,
|
|
"attached_condition": "cte.a2 is not null"
|
|
},
|
|
"table": {
|
|
"table_name": "tt2",
|
|
"access_type": "ref",
|
|
"possible_keys": ["b1"],
|
|
"key": "b1",
|
|
"key_length": "23",
|
|
"used_key_parts": ["b1"],
|
|
"ref": ["cte.a2"],
|
|
"r_loops": 1,
|
|
"rows": 2,
|
|
"r_rows": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
drop function f1;
|
|
drop table t1,t2;
|
|
#
|
|
# MDEV-22748: two materialized CTEs using the same recursive CTE
|
|
# (see also test case for MDEV-17024)
|
|
#
|
|
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');
|
|
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);
|
|
YEAR d1 d2
|
|
2018 2018-01-01 2018-09-20
|
|
EXPLAIN EXTENDED 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);
|
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
|
1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00
|
|
1 PRIMARY <derived5> ref key0 key0 5 const 0 0.00
|
|
1 PRIMARY <derived4> ref key0 key0 5 const 0 0.00
|
|
2 DERIVED t1 system NULL NULL NULL NULL 1 100.00
|
|
3 RECURSIVE UNION t1 system NULL NULL NULL NULL 1 100.00
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2 100.00 Using where
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
|
4 DERIVED <derived2> ALL NULL NULL NULL NULL 2 100.00
|
|
4 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
|
|
5 DERIVED <derived2> ALL NULL NULL NULL NULL 2 100.00
|
|
5 DERIVED t3 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
|
|
Warnings:
|
|
Note 1003 with recursive cte as (/* select#2 */ select year(`test`.`t1`.`d1`) AS `YEAR`,`test`.`t1`.`d1` AS `st`,`test`.`t1`.`d1` + interval 1 month AS `fn` from `test`.`t1` union all /* select#3 */ select year(`cte`.`st` + interval 1 month) AS `YEAR(cte.st + INTERVAL 1 MONTH)`,`cte`.`st` + interval 1 month AS `cte.st + INTERVAL 1 MONTH`,`test`.`t1`.`d2` + interval 1 day AS `t1.d2 + INTERVAL 1 DAY` from `cte` join `test`.`t1` where `cte`.`st` + interval 1 month < `test`.`t1`.`d2`), cte2 as (/* select#4 */ select `cte`.`YEAR` AS `YEAR`,count(0) AS `COUNT(*)` from `cte` join `test`.`t2` where `test`.`t2`.`tm` between `cte`.`st` and `cte`.`fn`), cte3 as (/* select#5 */ select `cte`.`YEAR` AS `YEAR`,count(0) AS `COUNT(*)` from `cte` join `test`.`t3` where `test`.`t3`.`tm` between `cte`.`st` and `cte`.`fn`)/* select#1 */ select 2018 AS `YEAR`,'2018-01-01' AS `d1`,'2018-09-20' AS `d2` from `cte2` join `cte3` where `cte3`.`YEAR` = 2018 and `cte2`.`YEAR` = 2018
|
|
PREPARE stmt FROM "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)";
|
|
EXECUTE stmt;
|
|
YEAR d1 d2
|
|
2018 2018-01-01 2018-09-20
|
|
EXECUTE stmt;
|
|
YEAR d1 d2
|
|
2018 2018-01-01 2018-09-20
|
|
CREATE TABLE t4 (YEAR int(4), d1 date , d2 date);
|
|
CREATE PROCEDURE p() INSERT INTO t4 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);
|
|
CALL p();
|
|
SELECT * FROM t4;
|
|
YEAR d1 d2
|
|
2018 2018-01-01 2018-09-20
|
|
DROP PROCEDURE p;
|
|
DROP TABLE t1,t2,t3,t4;
|
|
#
|
|
# MDEV-23619: recursive CTE used only in the second operand of UNION
|
|
#
|
|
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);
|
|
explain 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;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
|
|
2 DERIVED s ALL NULL NULL NULL NULL 4
|
|
3 RECURSIVE UNION t1 ALL NULL NULL NULL NULL 4 Using where
|
|
3 RECURSIVE UNION <derived2> ref key0 key0 9 test.t1.c 2
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
|
4 UNION <derived2> ALL NULL NULL NULL NULL 4
|
|
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;
|
|
b
|
|
0
|
|
3
|
|
7
|
|
1
|
|
3
|
|
analyze format=json 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;
|
|
ANALYZE
|
|
{
|
|
"query_block": {
|
|
"union_result": {
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"table": {
|
|
"message": "No tables used"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 4,
|
|
"operation": "UNION",
|
|
"r_loops": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"table": {
|
|
"table_name": "<derived2>",
|
|
"access_type": "ALL",
|
|
"r_loops": 1,
|
|
"rows": 4,
|
|
"r_rows": 4,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100,
|
|
"materialized": {
|
|
"query_block": {
|
|
"recursive_union": {
|
|
"table_name": "<union2,3>",
|
|
"access_type": "ALL",
|
|
"r_loops": 0,
|
|
"r_rows": null,
|
|
"query_specifications": [
|
|
{
|
|
"query_block": {
|
|
"select_id": 2,
|
|
"r_loops": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"table": {
|
|
"table_name": "s",
|
|
"access_type": "ALL",
|
|
"r_loops": 1,
|
|
"rows": 4,
|
|
"r_rows": 4,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"query_block": {
|
|
"select_id": 3,
|
|
"operation": "UNION",
|
|
"r_loops": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"table": {
|
|
"table_name": "t1",
|
|
"access_type": "ALL",
|
|
"r_loops": 1,
|
|
"rows": 4,
|
|
"r_rows": 4,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100,
|
|
"attached_condition": "t1.c is not null"
|
|
},
|
|
"table": {
|
|
"table_name": "<derived2>",
|
|
"access_type": "ref",
|
|
"possible_keys": ["key0"],
|
|
"key": "key0",
|
|
"key_length": "9",
|
|
"used_key_parts": ["a"],
|
|
"ref": ["test.t1.c"],
|
|
"r_loops": 4,
|
|
"rows": 2,
|
|
"r_rows": 0.5,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
prepare stmt from "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";
|
|
execute stmt;
|
|
b
|
|
0
|
|
3
|
|
7
|
|
1
|
|
3
|
|
execute stmt;
|
|
b
|
|
0
|
|
3
|
|
7
|
|
1
|
|
3
|
|
deallocate prepare stmt;
|
|
#checking hanging cte that uses a recursive cte
|
|
explain 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;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY tt ALL NULL NULL NULL NULL 4
|
|
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;
|
|
a b c
|
|
1 3 12
|
|
2 7 15
|
|
3 1 3
|
|
4 3 1
|
|
analyze format=json 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;
|
|
ANALYZE
|
|
{
|
|
"query_block": {
|
|
"select_id": 1,
|
|
"r_loops": 1,
|
|
"r_total_time_ms": "REPLACED",
|
|
"table": {
|
|
"table_name": "tt",
|
|
"access_type": "ALL",
|
|
"r_loops": 1,
|
|
"rows": 4,
|
|
"r_rows": 4,
|
|
"r_total_time_ms": "REPLACED",
|
|
"filtered": 100,
|
|
"r_filtered": 100
|
|
}
|
|
}
|
|
}
|
|
prepare stmt from "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";
|
|
execute stmt;
|
|
a b c
|
|
1 3 12
|
|
2 7 15
|
|
3 1 3
|
|
4 3 1
|
|
execute stmt;
|
|
a b c
|
|
1 3 12
|
|
2 7 15
|
|
3 1 3
|
|
4 3 1
|
|
deallocate prepare stmt;
|
|
drop table t1;
|
|
#
|
|
# MDEV-24019: query with recursive CTE when no default database is set
|
|
#
|
|
drop database test;
|
|
with recursive a as
|
|
(select 1 from dual union select * from a as r)
|
|
select * from a;
|
|
1
|
|
1
|
|
create database db1;
|
|
create table db1.t1 (a int);
|
|
insert into db1.t1 values (3), (7), (1);
|
|
with recursive cte as
|
|
(select * from db1.t1 union select * from (select * from cte) as t)
|
|
select * from cte;
|
|
a
|
|
3
|
|
7
|
|
1
|
|
explain with recursive cte as
|
|
(select * from db1.t1 union select * from (select * from cte) as t)
|
|
select * from cte;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
|
|
2 DERIVED t1 ALL NULL NULL NULL NULL 3
|
|
3 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 3
|
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
|
|
prepare stmt from "with recursive cte as
|
|
(select * from db1.t1 union select * from (select * from cte) as t)
|
|
select * from cte";
|
|
execute stmt;
|
|
a
|
|
3
|
|
7
|
|
1
|
|
execute stmt;
|
|
a
|
|
3
|
|
7
|
|
1
|
|
deallocate prepare stmt;
|
|
drop database db1;
|
|
create database test;
|
|
use test;
|
|
#
|
|
# MDEV-23406: query with mutually recursive CTEs when big_tables=1
|
|
#
|
|
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);
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
union
|
|
select h.*, w.*
|
|
from folks v, folks h, folks w
|
|
where v.name = 'Me' and
|
|
(v.father = h.id AND v.mother= w.id)
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
explain 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;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 1728
|
|
4 DERIVED <derived3> ALL NULL NULL NULL NULL 1728
|
|
5 RECURSIVE UNION <derived3> ALL NULL NULL NULL NULL 1728
|
|
NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL
|
|
3 DERIVED v ALL NULL NULL NULL NULL 12 Using where
|
|
3 DERIVED h ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
|
|
3 DERIVED w ALL NULL NULL NULL NULL 12 Using where; Using join buffer (incremental, BNL join)
|
|
2 RECURSIVE UNION <derived4> ALL NULL NULL NULL NULL 2
|
|
2 RECURSIVE UNION h ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
|
|
2 RECURSIVE UNION w ALL NULL NULL NULL NULL 12 Using where; Using join buffer (incremental, BNL join)
|
|
NULL UNION RESULT <union3,2> ALL NULL NULL NULL NULL NULL
|
|
prepare stmt from "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";
|
|
execute stmt;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
execute stmt;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
deallocate prepare stmt;
|
|
with recursive
|
|
ancestor_couples(h_id, h_name, h_dob, h_father, h_mother,
|
|
w_id, w_name, w_dob, w_father, w_mother)
|
|
as
|
|
(
|
|
select h.*, w.*
|
|
from folks h, folks w, coupled_ancestors a
|
|
where a.father = h.id AND a.mother = w.id
|
|
),
|
|
coupled_ancestors (id, name, dob, father, mother)
|
|
as
|
|
(
|
|
select *
|
|
from folks
|
|
where name = 'Me'
|
|
union all
|
|
select h_id, h_name, h_dob, h_father, h_mother
|
|
from ancestor_couples
|
|
union all
|
|
select w_id, w_name, w_dob, w_father, w_mother
|
|
from ancestor_couples
|
|
)
|
|
select h_name, h_dob, w_name, w_dob
|
|
from ancestor_couples;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
explain 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;
|
|
id select_type table type possible_keys key key_len ref rows Extra
|
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
|
3 DERIVED folks ALL NULL NULL NULL NULL 12 Using where
|
|
4 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2
|
|
5 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 2
|
|
NULL UNION RESULT <union3,4,5> ALL NULL NULL NULL NULL NULL
|
|
2 DERIVED h ALL NULL NULL NULL NULL 12
|
|
2 DERIVED <derived3> ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
|
|
2 DERIVED w ALL NULL NULL NULL NULL 12 Using where; Using join buffer (incremental, BNL join)
|
|
prepare stmt from "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";
|
|
execute stmt;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
execute stmt;
|
|
h_name h_dob w_name w_dob
|
|
Dad 1970-02-02 Mom 1975-03-03
|
|
Grandpa Bill 1940-04-05 Grandma Ann 1941-10-15
|
|
Grandpa Ben 1940-10-21 Grandma Sally 1943-08-23
|
|
deallocate prepare stmt;
|
|
drop table folks;
|
|
set big_tables=@save_big_tables;
|
|
#
|
|
# MDEV-26135: execution of PS for query with hanging recursive CTE
|
|
#
|
|
create table t1 (a int);
|
|
insert into t1 values (5), (7);
|
|
create table t2 (b int);
|
|
insert into t2 values (3), (7), (1);
|
|
with recursive r as (select a from t1 union select a+1 from r where a < 10)
|
|
select * from t2;
|
|
b
|
|
3
|
|
7
|
|
1
|
|
prepare stmt from "with recursive r as (select a from t1 union select a+1 from r where a < 10)
|
|
select * from t2";
|
|
execute stmt;
|
|
b
|
|
3
|
|
7
|
|
1
|
|
execute stmt;
|
|
b
|
|
3
|
|
7
|
|
1
|
|
deallocate prepare stmt;
|
|
drop table t1,t2;
|
|
#
|
|
# MDEV-26189: Unknown column reference within hanging recursive CTE
|
|
#
|
|
create table t1 (a int);
|
|
insert into t1 values (3), (7), (1);
|
|
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 42S22: Unknown column 'r.b' in 'where clause'
|
|
explain 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 42S22: Unknown column 'r.b' in 'where clause'
|
|
create procedure sp1() 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;
|
|
call sp1();
|
|
ERROR 42S22: Unknown column 'r.b' in 'where clause'
|
|
call sp1();
|
|
ERROR 42S22: Unknown column 'r.b' in 'where clause'
|
|
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 42S22: Unknown column 's1.b' in 'where clause'
|
|
explain 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 42S22: Unknown column 's1.b' in 'where clause'
|
|
create procedure sp2() 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;
|
|
call sp2();
|
|
ERROR 42S22: Unknown column 's1.b' in 'where clause'
|
|
call sp2();
|
|
ERROR 42S22: Unknown column 's1.b' in 'where clause'
|
|
drop procedure sp1;
|
|
drop procedure sp2;
|
|
drop table t1;
|
|
#
|
|
# MDEV-26202: Recursive CTE used indirectly twice
|
|
# (fixed by the patch forMDEV-26025)
|
|
#
|
|
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;
|
|
a a
|
|
1 1
|
|
2 1
|
|
3 1
|
|
1 2
|
|
2 2
|
|
3 2
|
|
1 3
|
|
2 3
|
|
3 3
|
|
#
|
|
# End of 10.2 tests
|
|
#
|
|
#
|
|
# MDEV-14217 [db crash] Recursive CTE when SELECT includes new field
|
|
#
|
|
CREATE TEMPORARY TABLE a_tbl (
|
|
a VARCHAR(33) PRIMARY KEY,
|
|
b VARCHAR(33)
|
|
);
|
|
INSERT INTO a_tbl VALUES ('block0', 'block0'), ('block1', NULL);
|
|
WITH RECURSIVE Q0 AS (
|
|
SELECT T0.a, T0.b, 5
|
|
FROM a_tbl T0
|
|
WHERE b IS NULL
|
|
UNION ALL
|
|
SELECT T1.a, T1.b
|
|
FROM Q0
|
|
JOIN a_tbl T1
|
|
ON T1.a=Q0.a
|
|
) SELECT distinct(Q0.a), Q0.b
|
|
FROM Q0;
|
|
ERROR 21000: The used SELECT statements have a different number of columns
|
|
DROP TABLE a_tbl;
|
|
WITH RECURSIVE x AS (SELECT 1,2 UNION ALL SELECT 1 FROM x) SELECT * FROM x;
|
|
ERROR 21000: The used SELECT statements have a different number of columns
|
|
#
|
|
# MDEV-15162: Setting user variable in recursive CTE
|
|
#
|
|
SET @c=1;
|
|
WITH RECURSIVE cte AS
|
|
(SELECT 5
|
|
UNION
|
|
SELECT @c:=@c+1 FROM cte WHERE @c<3)
|
|
SELECT * FROM cte;
|
|
5
|
|
5
|
|
2
|
|
3
|
|
#
|
|
# MDEV-14883: recursive references in operands of INTERSECT / EXCEPT
|
|
#
|
|
create table flights
|
|
(departure varchar(32),
|
|
arrival varchar(32),
|
|
carrier varchar(20),
|
|
flight_number char(7));
|
|
insert into flights values
|
|
('Seattle', 'Frankfurt', 'Lufthansa', 'LH 491'),
|
|
('Seattle', 'Amsterdam', 'KLM', 'KL 6032'),
|
|
('Seattle', 'Chicago', 'American', 'AA 2573'),
|
|
('Seattle', 'Los Angeles', 'Alaska Air', 'AS 410'),
|
|
('Chicago', 'New York', 'American', 'AA 375'),
|
|
('Chicago', 'Montreal', 'Air Canada', 'AC 3053'),
|
|
('Los Angeles', 'New York', 'Delta', 'DL 1197'),
|
|
('New York', 'London', 'British Airways', 'BA 1511'),
|
|
('London', 'Moscow', 'British Airways', 'BA 233'),
|
|
('Moscow', 'Tokyo', 'Aeroflot', 'SU 264'),
|
|
('Moscow', 'Dubai', 'Emirates', 'EK 2421'),
|
|
('Dubai', 'Tokyo', 'Emirates', 'EK 318'),
|
|
('Dubai', 'Bangkok', 'Emirates', 'EK 2142'),
|
|
('Beijing', 'Bangkok', 'Air China', 'CA 757'),
|
|
('Beijing', 'Tokyo', 'Air China', 'CA 6653'),
|
|
('Moscow', 'Bangkok', 'Aeroflot', 'SU 270'),
|
|
('New York', 'Reykjavik', 'Icelandair', 'FL 416'),
|
|
('New York', 'Paris', 'Air France', 'AF 23'),
|
|
('Amsterdam', 'Moscow', 'KLM', 'KL 903'),
|
|
('Frankfurt', 'Dubai', 'Lufthansa', 'LH 630'),
|
|
('Frankfurt', 'Moscow', 'Lufthansa', 'LH 1444'),
|
|
('Reykjavik', 'London', 'British Airways', 'BA 2229'),
|
|
('Frankfurt', 'Beijing', 'Air China', 'CA 966'),
|
|
('Tokyo', 'Seattle', 'ANA', 'NH 178'),
|
|
('Los Angeles', 'Tokyo', 'ANA', 'NH 175'),
|
|
('Moscow', 'Los Angeles', 'Aeroflot', 'SU 106'),
|
|
('Montreal', 'Paris', 'Air Canada', 'AC 870'),
|
|
('London', 'Delhi', 'British Airways', 'BA 143'),
|
|
('Delhi', 'Bangkok', 'Air India', 'AI 306'),
|
|
('Delhi', 'Dubai', 'Air India', 'AI 995'),
|
|
('Dubai', 'Cairo', 'Emirates', 'EK 927'),
|
|
('Cairo', 'Paris', 'Air France', 'AF 503'),
|
|
('Amsterdam', 'New York', 'Delta', 'DL 47'),
|
|
('New York', 'Seattle', 'American', 'AA 45'),
|
|
('Paris', 'Chicago', 'Air France', 'AF 6734');
|
|
create table distances
|
|
(city1 varchar(32),
|
|
city2 varchar(32),
|
|
dist int);
|
|
insert into distances values
|
|
('Seattle', 'Frankfurt', 5080),
|
|
('Seattle', 'Amsterdam', 4859),
|
|
('Seattle', 'Chicago', 1733),
|
|
('Seattle', 'Los Angeles', 960),
|
|
('Chicago', 'New York', 712),
|
|
('Chicago', 'Montreal', 746),
|
|
('Los Angeles', 'New York', 2446),
|
|
('New York', 'London', 3459),
|
|
('London', 'Moscow', 1554),
|
|
('Moscow', 'Tokyo', 4647),
|
|
('Moscow', 'Dubai', 2298),
|
|
('Dubai', 'Tokyo', 4929),
|
|
('Dubai', 'Bangkok', 3050),
|
|
('Beijing', 'Bangkok', 2046),
|
|
('Beijing', 'Tokyo', 1301),
|
|
('Moscow', 'Bangkok', 4390),
|
|
('New York', 'Reykjavik', 2613),
|
|
('New York', 'Paris', 3625),
|
|
('Amsterdam', 'Moscow', 1334),
|
|
('Frankfurt', 'Dubai', 3003),
|
|
('Frankfurt', 'Moscow', 1256),
|
|
('Reykjavik', 'London', 1173),
|
|
('Frankfurt', 'Beijing', 4836),
|
|
('Tokyo', 'Seattle', 4783),
|
|
('Los Angeles', 'Tokyo', 5479),
|
|
('Moscow', 'Los Angeles', 6071),
|
|
('Moscow', 'Reykjavik', 2052),
|
|
('Montreal', 'Paris', 3425),
|
|
('London', 'Delhi', 4159),
|
|
('London', 'Paris', 214),
|
|
('Delhi', 'Bangkok', 1810),
|
|
('Delhi', 'Dubai', 1369),
|
|
('Delhi', 'Beijing', 2350),
|
|
('Dubai', 'Cairo', 1501),
|
|
('Cairo', 'Paris', 1992),
|
|
('Amsterdam', 'New York', 3643),
|
|
('New York', 'Seattle', 2402),
|
|
('Paris', 'Chicago', 4136),
|
|
('Paris', 'Los Angeles', 5647);
|
|
with recursive destinations (city) as
|
|
(
|
|
select a.arrival from flights a where a.departure = 'Seattle'
|
|
union
|
|
select b.arrival from destinations r, flights b where r.city = b.departure
|
|
)
|
|
select * from destinations;
|
|
city
|
|
Frankfurt
|
|
Amsterdam
|
|
Chicago
|
|
Los Angeles
|
|
New York
|
|
Montreal
|
|
Moscow
|
|
Dubai
|
|
Beijing
|
|
Tokyo
|
|
London
|
|
Bangkok
|
|
Reykjavik
|
|
Paris
|
|
Seattle
|
|
Cairo
|
|
Delhi
|
|
with recursive destinations (city) as
|
|
(
|
|
select a.arrival from flights a, distances d
|
|
where a.departure = 'Seattle' and
|
|
a.departure = d.city1 and a.arrival = d.city2 and
|
|
d.dist < 4000
|
|
union
|
|
select b.arrival from destinations r, flights b, distances d
|
|
where r.city = b.departure and
|
|
b.departure = d.city1 and b.arrival = d.city2 and
|
|
d.dist < 4000
|
|
)
|
|
select * from destinations;
|
|
city
|
|
Chicago
|
|
Los Angeles
|
|
New York
|
|
Montreal
|
|
London
|
|
Reykjavik
|
|
Paris
|
|
Seattle
|
|
Moscow
|
|
Dubai
|
|
Bangkok
|
|
Cairo
|
|
set standard_compliant_cte=0;
|
|
with recursive legs_to_destinations
|
|
(departure, arrival, dist, leg_no, acc_mileage) as
|
|
(
|
|
select a.departure, a.arrival, d.dist, 1, d.dist
|
|
from flights a, distances d
|
|
where a.departure = 'Seattle' and
|
|
a.departure = d.city1 and a.arrival = d.city2 and
|
|
d.dist < 4000
|
|
union all
|
|
select b.departure, b.arrival, d.dist, r.leg_no + 1, r.acc_mileage + d.dist
|
|
from legs_to_destinations r, flights b, distances d
|
|
where r.arrival = b.departure and
|
|
b.departure = d.city1 and b.arrival = d.city2 and
|
|
d.dist < 4000 and
|
|
b.arrival not in (select arrival from legs_to_destinations)
|
|
)
|
|
select * from legs_to_destinations;
|
|
departure arrival dist leg_no acc_mileage
|
|
Seattle Chicago 1733 1 1733
|
|
Seattle Los Angeles 960 1 960
|
|
Chicago New York 712 2 2445
|
|
Chicago Montreal 746 2 2479
|
|
Los Angeles New York 2446 2 3406
|
|
New York London 3459 3 6865
|
|
New York London 3459 3 5904
|
|
New York Reykjavik 2613 3 6019
|
|
New York Reykjavik 2613 3 5058
|
|
New York Paris 3625 3 7031
|
|
New York Paris 3625 3 6070
|
|
Montreal Paris 3425 3 5904
|
|
New York Seattle 2402 3 5808
|
|
New York Seattle 2402 3 4847
|
|
London Moscow 1554 4 7458
|
|
London Moscow 1554 4 8419
|
|
Moscow Dubai 2298 5 10717
|
|
Moscow Dubai 2298 5 9756
|
|
Dubai Bangkok 3050 6 12806
|
|
Dubai Bangkok 3050 6 13767
|
|
Dubai Cairo 1501 6 11257
|
|
Dubai Cairo 1501 6 12218
|
|
set standard_compliant_cte=default;
|
|
with recursive destinations (city) as
|
|
(
|
|
select a.arrival from flights a, distances d
|
|
where a.departure = 'Seattle' and
|
|
a.departure = d.city1 and a.arrival = d.city2 and
|
|
d.dist < 4000
|
|
union
|
|
select b.arrival from destinations r, flights b
|
|
where r.city = b.departure
|
|
intersect
|
|
select city2 from destinations s, distances d
|
|
where s.city = d.city1 and d.dist < 4000
|
|
)
|
|
select * from destinations;
|
|
city
|
|
Chicago
|
|
Los Angeles
|
|
New York
|
|
Montreal
|
|
London
|
|
Reykjavik
|
|
Paris
|
|
Seattle
|
|
Moscow
|
|
Dubai
|
|
Bangkok
|
|
Cairo
|
|
with recursive destinations (city) as
|
|
(
|
|
select a.arrival from flights a where a.departure = 'Seattle'
|
|
union
|
|
select * from
|
|
(
|
|
select b.arrival from destinations r, flights b
|
|
where r.city = b.departure
|
|
except
|
|
select arrival from flights
|
|
where arrival in
|
|
('New York', 'London', 'Moscow', 'Dubai', 'Cairo', 'Tokyo')
|
|
) t
|
|
)
|
|
select * from destinations;
|
|
city
|
|
Frankfurt
|
|
Amsterdam
|
|
Chicago
|
|
Los Angeles
|
|
Montreal
|
|
Beijing
|
|
Bangkok
|
|
Paris
|
|
drop table flights, distances;
|
|
#
|
|
# MDEV-15159: Forced nullability of columns in recursive CTE
|
|
#
|
|
WITH RECURSIVE cte AS (
|
|
SELECT 1 AS a UNION ALL
|
|
SELECT NULL FROM cte WHERE a IS NOT NULL)
|
|
SELECT * FROM cte;
|
|
a
|
|
1
|
|
NULL
|
|
CREATE TABLE t1 (a int NOT NULL);
|
|
INSERT INTO t1 VALUES (0);
|
|
WITH RECURSIVE cte AS
|
|
(SELECT a FROM t1 where a=0 UNION SELECT NULL FROM cte)
|
|
SELECT * FROM cte;
|
|
a
|
|
0
|
|
NULL
|
|
DROP TABLE t1;
|
|
# End of 10.3 tests
|