mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Fixed bugs: mdev-13780 CTE not found, mdev-14184 recursive CTE not found
The support of embedded CTEs was not correct in the cases when embedded CTEs were used multiple times. The problems occurred with both non-recursive (bug mdev-13780) and recursive (bug mdev-14184) embedded CTEs.
This commit is contained in:
@ -1079,3 +1079,52 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
|
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
|
||||||
NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL
|
NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
#
|
||||||
|
# MDEV-13780: tower of embedding CTEs with multiple usage of them
|
||||||
|
#
|
||||||
|
create table t1 (a int);
|
||||||
|
insert into t1 values (3), (2), (4), (7), (1), (2), (5);
|
||||||
|
with cte_e as
|
||||||
|
(
|
||||||
|
with cte_o as
|
||||||
|
(
|
||||||
|
with cte_i as (select * from t1 where a < 7)
|
||||||
|
select * from cte_i where a > 1
|
||||||
|
)
|
||||||
|
select * from cte_o as cto_o1 where a < 3
|
||||||
|
union
|
||||||
|
select * from cte_o as cto_o2 where a > 4
|
||||||
|
)
|
||||||
|
select * from cte_e as cte_e1 where a > 1
|
||||||
|
union
|
||||||
|
select * from cte_e as cte_e2;
|
||||||
|
a
|
||||||
|
2
|
||||||
|
5
|
||||||
|
explain extended with cte_e as
|
||||||
|
(
|
||||||
|
with cte_o as
|
||||||
|
(
|
||||||
|
with cte_i as (select * from t1 where a < 7)
|
||||||
|
select * from cte_i where a > 1
|
||||||
|
)
|
||||||
|
select * from cte_o as cto_o1 where a < 3
|
||||||
|
union
|
||||||
|
select * from cte_o as cto_o2 where a > 4
|
||||||
|
)
|
||||||
|
select * from cte_e as cte_e1 where a > 1
|
||||||
|
union
|
||||||
|
select * from cte_e as cte_e2;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 14 100.00 Using where
|
||||||
|
2 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
|
||||||
|
5 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
|
||||||
|
NULL UNION RESULT <union2,5> ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
6 UNION <derived9> ALL NULL NULL NULL NULL 14 100.00
|
||||||
|
9 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
|
||||||
|
12 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
|
||||||
|
NULL UNION RESULT <union9,12> ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
NULL UNION RESULT <union1,6> ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
Warnings:
|
||||||
|
Note 1003 with cte_e as (with cte_o as (with cte_i as (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1 union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1)select `cte_e1`.`a` AS `a` from `cte_e` `cte_e1` where `cte_e1`.`a` > 1 union select `cte_e2`.`a` AS `a` from `cte_e` `cte_e2`
|
||||||
|
drop table t1;
|
||||||
|
@ -2875,3 +2875,25 @@ f
|
|||||||
2
|
2
|
||||||
set standard_compliant_cte=default;
|
set standard_compliant_cte=default;
|
||||||
DROP TABLE t;
|
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
|
||||||
|
@ -743,3 +743,31 @@ eval $q;
|
|||||||
eval explain $q;
|
eval explain $q;
|
||||||
|
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-13780: tower of embedding CTEs with multiple usage of them
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
create table t1 (a int);
|
||||||
|
insert into t1 values (3), (2), (4), (7), (1), (2), (5);
|
||||||
|
|
||||||
|
let $q=
|
||||||
|
with cte_e as
|
||||||
|
(
|
||||||
|
with cte_o as
|
||||||
|
(
|
||||||
|
with cte_i as (select * from t1 where a < 7)
|
||||||
|
select * from cte_i where a > 1
|
||||||
|
)
|
||||||
|
select * from cte_o as cto_o1 where a < 3
|
||||||
|
union
|
||||||
|
select * from cte_o as cto_o2 where a > 4
|
||||||
|
)
|
||||||
|
select * from cte_e as cte_e1 where a > 1
|
||||||
|
union
|
||||||
|
select * from cte_e as cte_e2;
|
||||||
|
|
||||||
|
eval $q;
|
||||||
|
eval explain extended $q;
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
|
@ -1928,3 +1928,22 @@ set standard_compliant_cte=default;
|
|||||||
|
|
||||||
DROP TABLE t;
|
DROP TABLE t;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # mdev-14184: recursive CTE embedded into CTE with multiple references
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
WITH
|
||||||
|
cte1 AS (
|
||||||
|
SELECT n FROM (
|
||||||
|
WITH RECURSIVE rec_cte(n) AS (
|
||||||
|
SELECT 1 as n1
|
||||||
|
UNION ALL
|
||||||
|
SELECT n+1 as n2 FROM rec_cte WHERE n < 3
|
||||||
|
) SELECT n FROM rec_cte
|
||||||
|
) AS X
|
||||||
|
),
|
||||||
|
cte2 as (
|
||||||
|
SELECT 2 FROM cte1
|
||||||
|
)
|
||||||
|
SELECT *
|
||||||
|
FROM cte1;
|
||||||
|
@ -349,7 +349,10 @@ void With_element::check_dependencies_in_select(st_select_lex *sl,
|
|||||||
/* Now look for the dependencies in the subqueries of sl */
|
/* Now look for the dependencies in the subqueries of sl */
|
||||||
st_select_lex_unit *inner_unit= sl->first_inner_unit();
|
st_select_lex_unit *inner_unit= sl->first_inner_unit();
|
||||||
for (; inner_unit; inner_unit= inner_unit->next_unit())
|
for (; inner_unit; inner_unit= inner_unit->next_unit())
|
||||||
check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map);
|
{
|
||||||
|
if (!inner_unit->with_element)
|
||||||
|
check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -838,7 +841,6 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
|
|||||||
with_table->next_global= spec_tables;
|
with_table->next_global= spec_tables;
|
||||||
}
|
}
|
||||||
res= &lex->unit;
|
res= &lex->unit;
|
||||||
res->set_with_clause(owner);
|
|
||||||
|
|
||||||
lex->unit.include_down(with_table->select_lex);
|
lex->unit.include_down(with_table->select_lex);
|
||||||
lex->unit.set_slave(with_select);
|
lex->unit.set_slave(with_select);
|
||||||
@ -847,6 +849,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
|
|||||||
insert_chain_before(
|
insert_chain_before(
|
||||||
(st_select_lex_node **) &(old_lex->all_selects_list),
|
(st_select_lex_node **) &(old_lex->all_selects_list),
|
||||||
with_select));
|
with_select));
|
||||||
|
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
|
||||||
|
res= NULL;
|
||||||
lex_end(lex);
|
lex_end(lex);
|
||||||
err:
|
err:
|
||||||
if (arena)
|
if (arena)
|
||||||
@ -990,14 +994,18 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
|
|||||||
and it was unsuccesful. Yet for units cloned from the spec it has not
|
and it was unsuccesful. Yet for units cloned from the spec it has not
|
||||||
been done yet.
|
been done yet.
|
||||||
*/
|
*/
|
||||||
if (with_elem && sl->master_unit() == with_elem->spec)
|
With_clause *attached_with_clause=sl->get_with_clause();
|
||||||
|
if (attached_with_clause &&
|
||||||
|
(found= attached_with_clause->find_table_def(table, NULL)))
|
||||||
break;
|
break;
|
||||||
With_clause *with_clause=sl->get_with_clause();
|
if (with_elem)
|
||||||
if (with_clause)
|
|
||||||
{
|
{
|
||||||
With_element *barrier= with_clause->with_recursive ? NULL : with_elem;
|
With_clause *containing_with_clause= with_elem->get_owner();
|
||||||
if ((found= with_clause->find_table_def(table, barrier)))
|
With_element *barrier= containing_with_clause->with_recursive ?
|
||||||
|
NULL : with_elem;
|
||||||
|
if ((found= containing_with_clause->find_table_def(table, barrier)))
|
||||||
break;
|
break;
|
||||||
|
sl= sl->master_unit()->outer_select();
|
||||||
}
|
}
|
||||||
master_unit= sl->master_unit();
|
master_unit= sl->master_unit();
|
||||||
/* Do not look for the table's definition beyond the scope of the view */
|
/* Do not look for the table's definition beyond the scope of the view */
|
||||||
|
Reference in New Issue
Block a user