Commit bdb87c49 authored by Igor Babaev's avatar Igor Babaev

Fixed mdev-15119 CTE, referencing another CTE, that is declared after,

                 does not return error

Corrected the code of st_select_lex::find_table_def_in_with_clauses() for
a proper identification of CTE references used in embedded CTEs.
parent 90885985
...@@ -1379,3 +1379,22 @@ USE db1; ...@@ -1379,3 +1379,22 @@ USE db1;
WITH cte AS (SELECT 1 AS a) SELECT db1.cte.a FROM db1.cte; WITH cte AS (SELECT 1 AS a) SELECT db1.cte.a FROM db1.cte;
ERROR 42S02: Table 'db1.cte' doesn't exist ERROR 42S02: Table 'db1.cte' doesn't exist
DROP DATABASE db1; DROP DATABASE db1;
USE test;
#
# MDEV-15119: CTE c2 specified after CTE c1 and is used in
# CTE c3 that is embedded into the spec of c1
#
CREATE TABLE t1 (i int);
INSERT INTO t1 VALUES (1),(2),(3);
WITH c1 AS (WITH c3 AS (SELECT * FROM c2) SELECT * FROM c3),
c2 AS (SELECT * FROM t1)
SELECT * FROM c1;
ERROR 42S02: Table 'test.c2' doesn't exist
WITH RECURSIVE c1 AS (WITH c3 AS (SELECT * FROM c2) SELECT * FROM c3),
c2 AS (SELECT * FROM t1)
SELECT * FROM c1;
i
1
2
3
DROP TABLE t1;
...@@ -944,3 +944,23 @@ USE db1; ...@@ -944,3 +944,23 @@ USE db1;
WITH cte AS (SELECT 1 AS a) SELECT db1.cte.a FROM db1.cte; WITH cte AS (SELECT 1 AS a) SELECT db1.cte.a FROM db1.cte;
DROP DATABASE db1; DROP DATABASE db1;
USE test;
--echo #
--echo # MDEV-15119: CTE c2 specified after CTE c1 and is used in
--echo # CTE c3 that is embedded into the spec of c1
--echo #
CREATE TABLE t1 (i int);
INSERT INTO t1 VALUES (1),(2),(3);
--error ER_NO_SUCH_TABLE
WITH c1 AS (WITH c3 AS (SELECT * FROM c2) SELECT * FROM c3),
c2 AS (SELECT * FROM t1)
SELECT * FROM c1;
WITH RECURSIVE c1 AS (WITH c3 AS (SELECT * FROM c2) SELECT * FROM c3),
c2 AS (SELECT * FROM t1)
SELECT * FROM c1;
DROP TABLE t1;
...@@ -990,23 +990,20 @@ bool With_element::is_anchor(st_select_lex *sel) ...@@ -990,23 +990,20 @@ bool With_element::is_anchor(st_select_lex *sel)
With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
{ {
st_select_lex_unit *master_unit= NULL;
With_element *found= NULL; With_element *found= NULL;
for (st_select_lex *sl= this; st_select_lex_unit *master_unit;
sl; st_select_lex *outer_sl;
sl= master_unit->outer_select()) for (st_select_lex *sl= this; sl; sl= outer_sl)
{ {
With_element *with_elem= sl->get_with_element();
/* /*
If sl->master_unit() is the spec of a with element then the search for If sl->master_unit() is the spec of a with element then the search for
a definition was already done by With_element::check_dependencies_in_spec a definition was already done by With_element::check_dependencies_in_spec
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.
*/ */
With_clause *attached_with_clause=sl->get_with_clause(); master_unit= sl->master_unit();
if (attached_with_clause && outer_sl= master_unit->outer_select();
(found= attached_with_clause->find_table_def(table, NULL))) With_element *with_elem= sl->get_with_element();
break;
if (with_elem) if (with_elem)
{ {
With_clause *containing_with_clause= with_elem->get_owner(); With_clause *containing_with_clause= with_elem->get_owner();
...@@ -1014,9 +1011,16 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) ...@@ -1014,9 +1011,16 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
NULL : with_elem; NULL : with_elem;
if ((found= containing_with_clause->find_table_def(table, barrier))) if ((found= containing_with_clause->find_table_def(table, barrier)))
break; break;
sl= sl->master_unit()->outer_select(); if (outer_sl && !outer_sl->get_with_element())
break;
}
else
{
With_clause *attached_with_clause= sl->get_with_clause();
if (attached_with_clause &&
(found= attached_with_clause->find_table_def(table, NULL)))
break;
} }
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 */
if (master_unit->is_view) if (master_unit->is_view)
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment