Commit c0a59b46 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from...

MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from create_select, select_paren_derived, select_derived2, query_specification

This change refactors the "table_expression" rule in sql_yacc.yy.

Queries with subselects and derived tables, as well as "CREATE TABLE ... SELECT"
now return syntax error instead of "Incorrect usage of PROCEDURE and ...".
parent 7905ea89
......@@ -19,7 +19,7 @@ test.t1.empty_string 0 0 4 0 0.0000 NULL CHAR(0) NOT NULL
test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL
test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL
create table t2 select * from t1 procedure analyse();
ERROR HY000: Incorrect usage of PROCEDURE and non-SELECT
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 'procedure analyse()' at line 1
drop table t1;
EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
ERROR HY000: Incorrect usage of PROCEDURE and subquery
......@@ -120,7 +120,7 @@ CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1),(2);
# should not crash
CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE();
ERROR HY000: Incorrect usage of PROCEDURE and non-SELECT
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 'PROCEDURE ANALYSE()' at line 1
DROP TABLE t1;
End of 5.0 tests
#
......@@ -149,3 +149,25 @@ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_
test.t2.f2 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL
DROP TABLE t1, t2;
End of 5.1 tests
#
# Start of 10.2 tests
#
(SELECT 1 FROM DUAL PROCEDURE ANALYSE());
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
1 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL
((SELECT 1 FROM DUAL PROCEDURE ANALYSE()));
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
1 1 1 1 1 0 0 1.0000 0.0000 ENUM('1') NOT NULL
SELECT * FROM t1 UNION SELECT * FROM t1 PROCEDURE analyse();
ERROR HY000: Incorrect usage of PROCEDURE and subquery
#
# MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from create_select, select_paren_derived, select_derived2, query_specification
#
SELECT * FROM (SELECT * FROM t1 PROCEDURE ANALYSE());
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 'PROCEDURE ANALYSE())' at line 1
SELECT * FROM t1 NATURAL JOIN (SELECT * FROM t2 PROCEDURE ANALYSE());
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 'PROCEDURE ANALYSE())' at line 1
SELECT (SELECT 1 FROM t1 PROCEDURE ANALYSE()) FROM t2;
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 'PROCEDURE ANALYSE()) FROM t2' at line 1
SELECT ((SELECT 1 FROM t1 PROCEDURE ANALYSE())) FROM t2;
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 'PROCEDURE ANALYSE())) FROM t2' at line 1
......@@ -686,7 +686,7 @@ FOR UPDATE) a;
SELECT 1 FROM
(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
PROCEDURE ANALYSE() FOR UPDATE) a;
ERROR HY000: Incorrect usage of PROCEDURE and subquery
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 'PROCEDURE ANALYSE() FOR UPDATE) a' at line 3
SELECT 1 FROM t1
WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
FOR UPDATE);
......@@ -694,7 +694,7 @@ FOR UPDATE);
SELECT 1 FROM t1
WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
PROCEDURE ANALYSE() FOR UPDATE);
ERROR HY000: Incorrect usage of PROCEDURE and subquery
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 'PROCEDURE ANALYSE() FOR UPDATE)' at line 3
SELECT 1 FROM t1
UNION
SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
......
......@@ -79,7 +79,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
1
1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
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 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
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 'SELECT 1))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
......
......@@ -83,7 +83,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
1
1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
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 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
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 'SELECT 1))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
......
......@@ -86,7 +86,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
1
1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
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 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
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 'SELECT 1))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
......
......@@ -82,7 +82,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
1
1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
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 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
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 'SELECT 1))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
......
......@@ -85,7 +85,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
1
1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
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 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
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 'SELECT 1))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
......
......@@ -82,7 +82,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
1
1
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
ERROR HY000: Incorrect usage of PROCEDURE and subquery
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 'PROCEDURE ANALYSE(1))' at line 1
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
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 'SELECT 1))' at line 1
SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
......
......@@ -11,7 +11,7 @@ insert into t1 values (1,2,"","Y","2002-03-03"), (3,4,"","N","2002-03-04"), (5,6
select count(*) from t1 procedure analyse();
select * from t1 procedure analyse();
select * from t1 procedure analyse(2);
--error ER_WRONG_USAGE
--error ER_PARSE_ERROR
create table t2 select * from t1 procedure analyse();
drop table t1;
......@@ -127,7 +127,7 @@ CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1),(2);
--echo # should not crash
--error ER_WRONG_USAGE
--error ER_PARSE_ERROR
CREATE TABLE t2 SELECT 1 FROM t1, t1 t3 GROUP BY t3.a PROCEDURE ANALYSE();
DROP TABLE t1;
......@@ -157,3 +157,27 @@ SELECT * FROM t2 LIMIT 1 PROCEDURE ANALYSE();
DROP TABLE t1, t2;
--echo End of 5.1 tests
--echo #
--echo # Start of 10.2 tests
--echo #
(SELECT 1 FROM DUAL PROCEDURE ANALYSE());
((SELECT 1 FROM DUAL PROCEDURE ANALYSE()));
# TODO:
--error ER_WRONG_USAGE
SELECT * FROM t1 UNION SELECT * FROM t1 PROCEDURE analyse();
--echo #
--echo # MDEV-10030 sql_yacc.yy: Split table_expression and remove PROCEDURE from create_select, select_paren_derived, select_derived2, query_specification
--echo #
--error ER_PARSE_ERROR
SELECT * FROM (SELECT * FROM t1 PROCEDURE ANALYSE());
--ERROR ER_PARSE_ERROR
SELECT * FROM t1 NATURAL JOIN (SELECT * FROM t2 PROCEDURE ANALYSE());
--error ER_PARSE_ERROR
SELECT (SELECT 1 FROM t1 PROCEDURE ANALYSE()) FROM t2;
--error ER_PARSE_ERROR
SELECT ((SELECT 1 FROM t1 PROCEDURE ANALYSE())) FROM t2;
......@@ -806,7 +806,7 @@ SELECT 1 FROM
(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
FOR UPDATE) a;
--error ER_WRONG_USAGE
--error ER_PARSE_ERROR
SELECT 1 FROM
(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
PROCEDURE ANALYSE() FOR UPDATE) a;
......@@ -815,7 +815,7 @@ SELECT 1 FROM t1
WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
FOR UPDATE);
--error ER_WRONG_USAGE
--error ER_PARSE_ERROR
SELECT 1 FROM t1
WHERE EXISTS(SELECT 1 FROM DUAL WHERE 1 GROUP BY 1 HAVING 1 ORDER BY 1
PROCEDURE ANALYSE() FOR UPDATE);
......
......@@ -51,7 +51,7 @@ SELECT * FROM (SELECT 1 as id) b WHERE id IN (SELECT * FROM (SELECT 1 as id) c O
SELECT * FROM (SELECT 1) a WHERE 1 IN (SELECT 1,1);
SELECT 1 IN (SELECT 1);
SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
-- error ER_WRONG_USAGE
-- error ER_PARSE_ERROR
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
-- error ER_PARSE_ERROR
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
......
......@@ -988,6 +988,12 @@ JOIN::prepare(TABLE_LIST *tables_init,
}
if (thd->lex->derived_tables)
{
/*
Queries with derived tables and PROCEDURE are not allowed.
Many of such queries are disallowed grammatically, but there
are still some complex cases:
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE()
*/
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE",
thd->lex->derived_tables & DERIVED_VIEW ?
"view" : "subquery");
......@@ -995,6 +1001,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
}
if (thd->lex->sql_command != SQLCOM_SELECT)
{
// EXPLAIN SELECT * FROM t1 PROCEDURE ANALYSE()
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "non-SELECT");
goto err;
}
......
......@@ -1037,10 +1037,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%parse-param { THD *thd }
%lex-param { THD *thd }
/*
Currently there are 124 shift/reduce conflicts.
Currently there are 123 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
%expect 124
%expect 123
/*
Comments for TOKENS.
......@@ -5695,7 +5695,19 @@ create_select:
{
Select->parsing_place= NO_MATTER;
}
table_expression
/*
TODO:
The following sequence repeats a few times:
opt_table_expression
opt_order_clause
opt_limit_clause
opt_select_lock_type
Perhaps they can be grouped into a dedicated rule.
*/
opt_table_expression
opt_order_clause
opt_limit_clause
opt_select_lock_type
{
/*
The following work only with the local list, the global list
......@@ -8535,7 +8547,10 @@ select_paren_derived:
Lex->current_select->set_braces(true);
}
SELECT_SYM select_part2_derived
table_expression
opt_table_expression
opt_order_clause
opt_limit_clause
opt_select_lock_type
{
if (setup_select_in_parentheses(Lex))
MYSQL_YYABORT;
......@@ -8566,24 +8581,20 @@ select_part2:
| select_options_and_item_list into opt_select_lock_type
| select_options_and_item_list
opt_into
from_clause
opt_where_clause
opt_group_clause
opt_having_clause
opt_window_clause
table_expression
opt_order_clause
opt_limit_clause
opt_procedure_clause
opt_into
opt_select_lock_type
{
if ($2 && $11)
if ($2 && $7)
{
/* double "INTO" clause */
my_error(ER_WRONG_USAGE, MYF(0), "INTO", "INTO");
MYSQL_YYABORT;
}
if ($10 && ($2 || $11))
if ($6 && ($2 || $7))
{
/* "INTO" with "PROCEDURE ANALYSE" */
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "INTO");
......@@ -8606,25 +8617,25 @@ select_options_and_item_list:
}
;
/**
<table expression>, as in the SQL standard.
*/
table_expression:
opt_from_clause
from_clause
opt_where_clause
opt_group_clause
opt_having_clause
opt_window_clause
opt_order_clause
opt_limit_clause
opt_procedure_clause
opt_select_lock_type
;
from_clause:
FROM table_reference_list
opt_table_expression:
/* Empty */
| table_expression
;
opt_from_clause:
/* empty */
| from_clause
from_clause:
FROM table_reference_list
;
table_reference_list:
......@@ -11208,7 +11219,10 @@ select_derived2:
{
Select->parsing_place= NO_MATTER;
}
table_expression
opt_table_expression
opt_order_clause
opt_limit_clause
opt_select_lock_type
;
get_select_lex:
......@@ -11946,9 +11960,11 @@ opt_procedure_clause:
if (&lex->select_lex != lex->current_select)
{
// SELECT * FROM t1 UNION SELECT * FROM t2 PROCEDURE ANALYSE();
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
MYSQL_YYABORT;
}
lex->proc_list.elements=0;
lex->proc_list.first=0;
lex->proc_list.next= &lex->proc_list.first;
......@@ -16359,7 +16375,10 @@ union_option:
query_specification:
SELECT_SYM select_init2_derived
table_expression
opt_table_expression
opt_order_clause
opt_limit_clause
opt_select_lock_type
{
$$= Lex->current_select->master_unit()->first_select();
}
......
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