Commit 4a8d3771 authored by Igor Babaev's avatar Igor Babaev

Fixed bug mdev-10058.

This was a bug in the parser. As a result it could accept queries
with invalid derived tables if they used With clauses.
parent b7994495
...@@ -759,3 +759,20 @@ a ...@@ -759,3 +759,20 @@ a
30 30
drop view v1; drop view v1;
drop table t1; drop table t1;
#
# Bug mdev-10058: Invalid derived table with WITH clause
#
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
CREATE TABLE t3 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
INSERT INTO t2 VALUES (1),(2),(3);
INSERT INTO t3 VALUES (1),(2),(3);
SELECT * FROM (WITH a AS (SELECT * FROM t1) (t2 NATURAL JOIN t3));
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 't2 NATURAL JOIN t3))' at line 1
SELECT * FROM (WITH a AS (SELECT * FROM t1) SELECT * FROM t2 NATURAL JOIN t3) AS d1;
a
1
2
3
DROP TABLE t1,t2,t3;
...@@ -448,3 +448,22 @@ with t1 as (select * from v1) select * from t1; ...@@ -448,3 +448,22 @@ with t1 as (select * from v1) select * from t1;
drop view v1; drop view v1;
drop table t1; drop table t1;
--echo #
--echo # Bug mdev-10058: Invalid derived table with WITH clause
--echo #
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
CREATE TABLE t3 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
INSERT INTO t2 VALUES (1),(2),(3);
INSERT INTO t3 VALUES (1),(2),(3);
--ERROR ER_PARSE_ERROR
SELECT * FROM (WITH a AS (SELECT * FROM t1) (t2 NATURAL JOIN t3));
SELECT * FROM (WITH a AS (SELECT * FROM t1) SELECT * FROM t2 NATURAL JOIN t3) AS d1;
DROP TABLE t1,t2,t3;
...@@ -11018,20 +11018,20 @@ table_factor: ...@@ -11018,20 +11018,20 @@ table_factor:
and our parser. Possibly this rule could be replaced by our and our parser. Possibly this rule could be replaced by our
query_expression_body. query_expression_body.
*/ */
| '('opt_with_clause get_select_lex select_derived_union ')' opt_table_alias | '(' get_select_lex select_derived_union ')' opt_table_alias
{ {
/* Use $3 instead of Lex->current_select as derived table will /* Use $2 instead of Lex->current_select as derived table will
alter value of Lex->current_select. */ alter value of Lex->current_select. */
if (!($4 || $6) && $3->embedding && if (!($3 || $5) && $2->embedding &&
!$3->embedding->nested_join->join_list.elements) !$2->embedding->nested_join->join_list.elements)
{ {
/* we have a derived table ($4 == NULL) but no alias, /* we have a derived table ($3 == NULL) but no alias,
Since we are nested in further parentheses so we Since we are nested in further parentheses so we
can pass NULL to the outer level parentheses can pass NULL to the outer level parentheses
Permits parsing of "((((select ...))) as xyz)" */ Permits parsing of "((((select ...))) as xyz)" */
$$= 0; $$= 0;
} }
else if (!$4) else if (!$3)
{ {
/* Handle case of derived table, alias may be NULL if there /* Handle case of derived table, alias may be NULL if there
are no outer parentheses, add_table_to_list() will throw are no outer parentheses, add_table_to_list() will throw
...@@ -11039,13 +11039,12 @@ table_factor: ...@@ -11039,13 +11039,12 @@ table_factor:
LEX *lex=Lex; LEX *lex=Lex;
SELECT_LEX *sel= lex->current_select; SELECT_LEX *sel= lex->current_select;
SELECT_LEX_UNIT *unit= sel->master_unit(); SELECT_LEX_UNIT *unit= sel->master_unit();
unit->set_with_clause($2);
lex->current_select= sel= unit->outer_select(); lex->current_select= sel= unit->outer_select();
Table_ident *ti= new (thd->mem_root) Table_ident(unit); Table_ident *ti= new (thd->mem_root) Table_ident(unit);
if (ti == NULL) if (ti == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
if (!($$= sel->add_table_to_list(lex->thd, if (!($$= sel->add_table_to_list(lex->thd,
ti, $6, 0, ti, $5, 0,
TL_READ, MDL_SHARED_READ))) TL_READ, MDL_SHARED_READ)))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -11053,11 +11052,11 @@ table_factor: ...@@ -11053,11 +11052,11 @@ table_factor:
lex->pop_context(); lex->pop_context();
lex->nest_level--; lex->nest_level--;
} }
/*else if (($4->select_lex && /*else if (($3->select_lex &&
$4->select_lex->master_unit()->is_union() && $3->select_lex->master_unit()->is_union() &&
($4->select_lex->master_unit()->first_select() == ($3->select_lex->master_unit()->first_select() ==
$4->select_lex || !$4->lifted)) || $6)*/ $3->select_lex || !$3->lifted)) || $5)*/
else if ($6 != NULL) else if ($5 != NULL)
{ {
/* /*
Tables with or without joins within parentheses cannot Tables with or without joins within parentheses cannot
...@@ -11070,7 +11069,7 @@ table_factor: ...@@ -11070,7 +11069,7 @@ table_factor:
{ {
/* nested join: FROM (t1 JOIN t2 ...), /* nested join: FROM (t1 JOIN t2 ...),
nest_level is the same as in the outer query */ nest_level is the same as in the outer query */
$$= $4; $$= $3;
} }
/* /*
Fields in derived table can be used in upper select in Fields in derived table can be used in upper select in
...@@ -11082,6 +11081,26 @@ table_factor: ...@@ -11082,6 +11081,26 @@ table_factor:
!$$->derived->first_select()->next_select()) !$$->derived->first_select()->next_select())
$$->select_lex->add_where_field($$->derived->first_select()); $$->select_lex->add_where_field($$->derived->first_select());
} }
/* Represents derived table with WITH clause */
| '(' get_select_lex subselect_start
with_clause query_expression_body
subselect_end ')' opt_table_alias
{
LEX *lex=Lex;
SELECT_LEX *sel= $2;
SELECT_LEX_UNIT *unit= $5->master_unit();
Table_ident *ti= new (thd->mem_root) Table_ident(unit);
if (ti == NULL)
MYSQL_YYABORT;
$5->set_with_clause($4);
lex->current_select= sel;
if (!($$= sel->add_table_to_list(lex->thd,
ti, $8, 0,
TL_READ, MDL_SHARED_READ)))
MYSQL_YYABORT;
sel->add_joined_table($$);
}
; ;
/* /*
...@@ -14014,7 +14033,6 @@ opt_with_clause: ...@@ -14014,7 +14033,6 @@ opt_with_clause:
| with_clause | with_clause
{ {
$$= $1; $$= $1;
Lex->derived_tables|= DERIVED_WITH;
} }
; ;
...@@ -14026,6 +14044,7 @@ with_clause: ...@@ -14026,6 +14044,7 @@ with_clause:
new With_clause($2, Lex->curr_with_clause); new With_clause($2, Lex->curr_with_clause);
if (with_clause == NULL) if (with_clause == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->derived_tables|= DERIVED_WITH;
Lex->curr_with_clause= with_clause; Lex->curr_with_clause= with_clause;
with_clause->add_to_list(Lex->with_clauses_list_last_next); with_clause->add_to_list(Lex->with_clauses_list_last_next);
} }
......
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