maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #11218
Re: Fwd: [Commits] b32031991e4: initial oracle parser fix
Hello Sanja, Igor,
This patch removes a lot of main_select_push() / pop_select() that
you had to add into *.yy files in the 10.3-MDEV-11953 branch.
The patch does the following:
- Disallows creation of Item_field in the select stack is empty.
An error is returned instead (ER_BAD_FIELD_ERROR).
The point is that Item_field requires a Name_resolution_context,
which is not available with the empty select stack.
This additionally fixed the problem reported in:
MDEV-14347 CREATE PROCEDURE returns no error when using an unknown
variable
- Disallows creation of Item_sum and Item_windowfunc the same way,
as they also need a Name_resolution_context.
It fixed the second part of MDEV-14347, about aggregate and window
functions.
It also fixed:
MDEV-15870 Using aggregate and window function in unexpected places
can crash the server
(repeatable since 10.2)
- Adds FOR_LOOP_BOUND into enum_parsing_place, to force creation of a
temporary
Item_field when inside a FOR loop:
FOR x IN ident
If the "ident" is later resolves to a cursor name,
then the loop is treated as "explicit cursor FOR loop", otherwise
it's a normal field name and therefore the same error (ER_BAD_FIELD_ERROR)
is returned.
- Adds a new method LEX::create_item_query_expression()
to reuse the same code in sql_yacc.yy and sql_yacc_ora.yy.
Adds a test for curr_sel, in case of NULL resets curr_sel
to &lex->builtin_select.
- Adds tests to cover IN and EXISTS subselects in various query parts.
This was very weakly covered. While working on this patch I had problems
with IN and EXISTS subselects, so I had to cover them.
- Adds a function relink_hack() to properly bind st_select_lex containing
an IN/EXISTS subselect to thd->lex->builtin_select. This is needed for
the cases when the statement does not do main_select_push().
I does not know this code well, so you can fine a better solution.
Please suggest.
I propose the following plan:
1. Move tests for IN/EXISTS from this patch just to 10.3
and rebase your branch.
2. Please review the remaining main_select_push()/pop_select().
Note, these rules must have push/pop for sure,
as they need Item_field as a part of their syntax:
insert:
update:
delete:
show:
handler:
But some of push/pop pairs should also be further removed:
- Some rules can probably assume (and assert) that the select stack
is not
empty, as the parent rule must have pushed an entry earlier:
partition_entry:
parse_vcol_expr:
single_multi:
- Non-TABLE related entries in:
create:
alter:
cannot use Item_field (e.g CREATE DATABASE or ALTER DATABASE),
so push/pop can be removed.
- I'm not sure about
load:
set:
I can study these separately (if we generally agree on the plan).
3. Move the part of the patch fixing MDEV-15870 and MDEV-14347 to 10.4,
so then you rebase on top of it.
Alternatively, just keep MDEV-15870 and MDEV-14347
as a part of 10.3-MDEV-11953. Please decide.
On 04/10/2018 03:37 PM, Oleksandr Byelkin wrote:
> Am 10.04.2018 um 10:58 schrieb Alexander Barkov:
>> Hello Sanja,
>>
>>
>> I reviewed your recent changes in "10.3-MDEV-11953"
>> (and the attached additional patch for sql_yacc_ora.yy)
>>
>> I have some proposals:
>>
>>
>>
>> 1. Can you please move huge pieces of the code from sql_yacc.yy to LEX
>> or other relevant classes?
>>
>> It makes the grammar much more readable (patches are aslo much more
>> readable).
>>
>> I'd move the relevant pieces of the code to LEX as a separate patch,
>> even before fixing the grammar.
> OK
>>
>> 2. You're adding too many main_select_push() and pop_select().
>> Please move them to upper level rules (it should be possible in many
>> cases).
> Impossible
>>
>> Add new helper rules when needed.
>> For example, this piece of code repeats many times:
>>
>> + {
>> + if (Lex->main_select_push())
>> + MYSQL_YYABORT;
>> + }
>> + expr
>> + {
>> + Lex->pop_select(); //main select
>> + $$= $3;
>>
>> It deserved a rule, say, expr_with_select_push_pop.
>> You can find a better name :)
>>
> OK
>> - Serg and I spent a lot of time working on this task:
>> MDEV-8909 union parser cleanup
>> (and its 13 dependency tasks, and 3 related tasks,
>> see the "Issue links" section in MDEV).
>>
>> We think that it should be the parser who disallows bad grammar, instead
>> of post-analysis with raising errors like
>> ER_CANT_USE_OPTION_HERE.
>> Please keep using the same approach.
> The task did not made parser recognizing brackets, and I have no ideas
> how to return parser errors when all SELECT parsed in the same way in
> difference from the previous parser which could recognize only one level
> of SELECTs.
>> Thanks!
>>
> [skip]
diff --git a/mysql-test/main/get_diagnostics.result b/mysql-test/main/get_diagnostics.result
index 732be7c..6944103 100644
--- a/mysql-test/main/get_diagnostics.result
+++ b/mysql-test/main/get_diagnostics.result
@@ -133,7 +133,7 @@ DROP PROCEDURE p1;
GET DIAGNOSTICS CONDITION;
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 '' at line 1
GET DIAGNOSTICS CONDITION a;
-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 '' at line 1
+ERROR 42S22: Unknown column 'a' in 'field list'
GET DIAGNOSTICS CONDITION 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 '' at line 1
GET DIAGNOSTICS CONDITION 1 @var;
@@ -212,9 +212,9 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
GET DIAGNOSTICS CONDITION (1) @var = CLASS_ORIGIN;
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 '(1) @var = CLASS_ORIGIN' at line 1
GET DIAGNOSTICS CONDITION p1() @var = CLASS_ORIGIN;
-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 '() @var = CLASS_ORIGIN' at line 1
+ERROR 42S22: Unknown column 'p1' in 'field list'
GET DIAGNOSTICS CONDITION ABS(2) @var = CLASS_ORIGIN;
-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 '(2) @var = CLASS_ORIGIN' at line 1
+ERROR 42S22: Unknown column 'ABS' in 'field list'
GET DIAGNOSTICS CONDITION 1.1 @var = CLASS_ORIGIN;
GET DIAGNOSTICS CONDITION "1" @var = CLASS_ORIGIN;
SELECT COUNT(max_questions) INTO @var FROM mysql.user;
@@ -226,10 +226,7 @@ Warnings:
Error 1758 Invalid condition number
Error 1758 Invalid condition number
GET DIAGNOSTICS CONDITION a @var = CLASS_ORIGIN;
-Warnings:
-Error 1758 Invalid condition number
-Error 1758 Invalid condition number
-Error 1054 Unknown column 'a' in 'field list'
+ERROR 42S22: Unknown column 'a' in 'field list'
SELECT COUNT(max_questions) INTO @var FROM mysql.user;
SET @cond = 1;
GET DIAGNOSTICS CONDITION @cond @var1 = CLASS_ORIGIN;
diff --git a/mysql-test/main/get_diagnostics.test b/mysql-test/main/get_diagnostics.test
index a30bad7..1553eb5 100644
--- a/mysql-test/main/get_diagnostics.test
+++ b/mysql-test/main/get_diagnostics.test
@@ -169,7 +169,7 @@ DROP PROCEDURE p1;
--error ER_PARSE_ERROR
GET DIAGNOSTICS CONDITION;
---error ER_PARSE_ERROR
+--error ER_BAD_FIELD_ERROR
GET DIAGNOSTICS CONDITION a;
--error ER_PARSE_ERROR
GET DIAGNOSTICS CONDITION 1;
@@ -271,9 +271,9 @@ GET DIAGNOSTICS CONDITION 1+1 @var = CLASS_ORIGIN;
GET DIAGNOSTICS CONDITION ? @var = CLASS_ORIGIN;
--error ER_PARSE_ERROR
GET DIAGNOSTICS CONDITION (1) @var = CLASS_ORIGIN;
---error ER_PARSE_ERROR
+--error ER_BAD_FIELD_ERROR
GET DIAGNOSTICS CONDITION p1() @var = CLASS_ORIGIN;
---error ER_PARSE_ERROR
+--error ER_BAD_FIELD_ERROR
GET DIAGNOSTICS CONDITION ABS(2) @var = CLASS_ORIGIN;
# Unfortunate side effects...
@@ -285,6 +285,7 @@ SELECT COUNT(max_questions) INTO @var FROM mysql.user;
GET DIAGNOSTICS CONDITION 9999 @var = CLASS_ORIGIN;
GET DIAGNOSTICS CONDITION NULL @var = CLASS_ORIGIN;
+--error ER_BAD_FIELD_ERROR
GET DIAGNOSTICS CONDITION a @var = CLASS_ORIGIN;
# Reset warnings
diff --git a/mysql-test/main/mysqldump.result b/mysql-test/main/mysqldump.result
index a1e206d..7034a7b 100644
--- a/mysql-test/main/mysqldump.result
+++ b/mysql-test/main/mysqldump.result
@@ -5153,7 +5153,7 @@ USE BUG52792;
SET NAMES utf8;
CREATE FUNCTION `straÃe` ( c1 CHAR(20))
RETURNS CHAR(50) DETERMINISTIC
-RETURN CONCAT(']]>, ', s, '!');
+RETURN CONCAT(']]>, ', c1, '!');
<?xml version="1.0"?>
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="BUG52792">
@@ -5162,7 +5162,7 @@ RETURN CONCAT(']]>, ', s, '!');
<![CDATA[
CREATE DEFINER=`root`@`localhost` FUNCTION `straÃe`( c1 CHAR(20)) RETURNS char(50) CHARSET latin1
DETERMINISTIC
-RETURN CONCAT(']]]]><![CDATA[>, ', s, '!')
+RETURN CONCAT(']]]]><![CDATA[>, ', c1, '!')
]]>
</routine>
</routines>
diff --git a/mysql-test/main/mysqldump.test b/mysql-test/main/mysqldump.test
index 6dde5aa..05aabcc 100644
--- a/mysql-test/main/mysqldump.test
+++ b/mysql-test/main/mysqldump.test
@@ -2351,7 +2351,7 @@ USE BUG52792;
SET NAMES utf8;
CREATE FUNCTION `straÃe` ( c1 CHAR(20))
RETURNS CHAR(50) DETERMINISTIC
-RETURN CONCAT(']]>, ', s, '!');
+RETURN CONCAT(']]>, ', c1, '!');
--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 -R -X BUG52792
diff --git a/mysql-test/main/signal.result b/mysql-test/main/signal.result
index 905842b..a37e25e 100644
--- a/mysql-test/main/signal.result
+++ b/mysql-test/main/signal.result
@@ -2285,17 +2285,13 @@ begin
DECLARE foo CONDITION FOR SQLSTATE '12345';
SIGNAL foo SET MYSQL_ERRNO = `65`; /* illegal */
end $$
-call test_signal $$
ERROR 42S22: Unknown column '65' in 'field list'
-drop procedure test_signal $$
create procedure test_signal()
begin
DECLARE foo CONDITION FOR SQLSTATE '12345';
SIGNAL foo SET MYSQL_ERRNO = `A`; /* illegal */
end $$
-call test_signal $$
ERROR 42S22: Unknown column 'A' in 'field list'
-drop procedure test_signal $$
create procedure test_signal()
begin
DECLARE foo CONDITION FOR SQLSTATE '12345';
@@ -2346,9 +2342,7 @@ DECLARE foo CONDITION FOR SQLSTATE '12345';
SIGNAL foo SET MYSQL_ERRNO = 1000,
MESSAGE_TEXT = `Hello`;
end $$
-call test_signal $$
ERROR 42S22: Unknown column 'Hello' in 'field list'
-drop procedure test_signal $$
create procedure test_signal()
begin
DECLARE foo CONDITION FOR SQLSTATE '12345';
diff --git a/mysql-test/main/signal.test b/mysql-test/main/signal.test
index cdb5796..54c6107 100644
--- a/mysql-test/main/signal.test
+++ b/mysql-test/main/signal.test
@@ -2546,25 +2546,21 @@ end $$
call test_signal $$
drop procedure test_signal $$
+-- error ER_BAD_FIELD_ERROR
create procedure test_signal()
begin
DECLARE foo CONDITION FOR SQLSTATE '12345';
SIGNAL foo SET MYSQL_ERRNO = `65`; /* illegal */
end $$
--- error ER_BAD_FIELD_ERROR
-call test_signal $$
-drop procedure test_signal $$
+-- error ER_BAD_FIELD_ERROR
create procedure test_signal()
begin
DECLARE foo CONDITION FOR SQLSTATE '12345';
SIGNAL foo SET MYSQL_ERRNO = `A`; /* illegal */
end $$
--- error ER_BAD_FIELD_ERROR
-call test_signal $$
-drop procedure test_signal $$
create procedure test_signal()
begin
@@ -2620,6 +2616,7 @@ end $$
call test_signal $$
drop procedure test_signal $$
+-- error ER_BAD_FIELD_ERROR
create procedure test_signal()
begin
DECLARE foo CONDITION FOR SQLSTATE '12345';
@@ -2627,10 +2624,6 @@ begin
MESSAGE_TEXT = `Hello`;
end $$
--- error ER_BAD_FIELD_ERROR
-call test_signal $$
-drop procedure test_signal $$
-
create procedure test_signal()
begin
DECLARE foo CONDITION FOR SQLSTATE '12345';
diff --git a/mysql-test/main/sp-error.result b/mysql-test/main/sp-error.result
index de4c4cf..cf74e6c 100644
--- a/mysql-test/main/sp-error.result
+++ b/mysql-test/main/sp-error.result
@@ -439,6 +439,9 @@ create procedure nodb.bug3339() begin end|
ERROR 42000: Unknown database 'nodb'
create procedure bug2653_1(a int, out b int)
set b = aa|
+call bug2653_1(1, @b)|
+ERROR 42S22: Unknown column 'aa' in 'field list'
+drop procedure bug2653_1|
create procedure bug2653_2(a int, out b int)
begin
if aa < 0 then
@@ -447,12 +450,7 @@ else
set b = a;
end if;
end|
-call bug2653_1(1, @b)|
-ERROR 42S22: Unknown column 'aa' in 'field list'
-call bug2653_2(2, @b)|
ERROR 42S22: Unknown column 'aa' in 'field list'
-drop procedure bug2653_1|
-drop procedure bug2653_2|
create procedure bug4344() drop procedure bug4344|
ERROR HY000: Can't drop or alter a PROCEDURE from within another stored routine
create procedure bug4344() drop function bug4344|
@@ -1067,6 +1065,7 @@ IF bug13037_foo THEN
SELECT 1;
END IF;
END|
+ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
CREATE PROCEDURE bug13037_p2()
BEGIN
SET @bug13037_foo = bug13037_bar;
@@ -1076,19 +1075,14 @@ BEGIN
SELECT bug13037_foo;
END|
-CALL bug13037_p1();
-ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
CALL bug13037_p2();
ERROR 42S22: Unknown column 'bug13037_bar' in 'field list'
CALL bug13037_p3();
ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
-CALL bug13037_p1();
-ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
CALL bug13037_p2();
ERROR 42S22: Unknown column 'bug13037_bar' in 'field list'
CALL bug13037_p3();
ERROR 42S22: Unknown column 'bug13037_foo' in 'field list'
-DROP PROCEDURE bug13037_p1;
DROP PROCEDURE bug13037_p2;
DROP PROCEDURE bug13037_p3;
create database mysqltest1;
diff --git a/mysql-test/main/sp-error.test b/mysql-test/main/sp-error.test
index 88d9809..e2adea8 100644
--- a/mysql-test/main/sp-error.test
+++ b/mysql-test/main/sp-error.test
@@ -608,6 +608,12 @@ create procedure nodb.bug3339() begin end|
create procedure bug2653_1(a int, out b int)
set b = aa|
+--error ER_BAD_FIELD_ERROR
+call bug2653_1(1, @b)|
+
+drop procedure bug2653_1|
+
+--error ER_BAD_FIELD_ERROR
create procedure bug2653_2(a int, out b int)
begin
if aa < 0 then
@@ -617,13 +623,6 @@ begin
end if;
end|
---error 1054
-call bug2653_1(1, @b)|
---error 1054
-call bug2653_2(2, @b)|
-
-drop procedure bug2653_1|
-drop procedure bug2653_2|
#
# BUG#4344
@@ -1507,6 +1506,7 @@ DROP PROCEDURE IF EXISTS bug13037_p3;
delimiter |;
+--error ER_BAD_FIELD_ERROR
CREATE PROCEDURE bug13037_p1()
BEGIN
IF bug13037_foo THEN
@@ -1529,20 +1529,15 @@ delimiter ;|
--echo
--error 1054
-CALL bug13037_p1();
---error 1054
CALL bug13037_p2();
--error 1054
CALL bug13037_p3();
--error 1054
-CALL bug13037_p1();
---error 1054
CALL bug13037_p2();
--error 1054
CALL bug13037_p3();
-DROP PROCEDURE bug13037_p1;
DROP PROCEDURE bug13037_p2;
DROP PROCEDURE bug13037_p3;
diff --git a/mysql-test/main/sp-expr.result b/mysql-test/main/sp-expr.result
new file mode 100644
index 0000000..3b4efb2e
--- /dev/null
+++ b/mysql-test/main/sp-expr.result
@@ -0,0 +1,574 @@
+#
+# Start of 10.4 tests
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+BEGIN NOT ATOMIC
+CASE ((1) IN (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+CASE (EXISTS (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+IF ((1) IN (SELECT a FROM t1)) THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+IF (EXISTS (SELECT a FROM t1)) THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+WHILE ((1234) IN (SELECT * FROM t1)) DO
+SELECT 1;
+END WHILE;
+END;
+$$
+BEGIN NOT ATOMIC
+WHILE (EXISTS (SELECT * FROM t1 WHERE a=1234)) DO
+SELECT 1;
+END WHILE;
+END;
+$$
+BEGIN NOT ATOMIC
+REPEAT
+SELECT 1;
+UNTIL (1 IN (SELECT * FROM t1))
+END REPEAT;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+REPEAT
+SELECT 1;
+UNTIL EXISTS (SELECT * FROM t1 WHERE a=1)
+END REPEAT;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+FOR i IN 0..(1 IN (SELECT * FROM t1))
+DO
+SELECT i;
+END FOR;
+END;
+$$
+i
+0
+i
+1
+BEGIN NOT ATOMIC
+FOR i IN 0..EXISTS (SELECT * FROM t1 WHERE a=1)
+DO
+SELECT i;
+END FOR;
+END;
+$$
+i
+0
+i
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+BEGIN NOT ATOMIC
+DECLARE a INT DEFAULT ((10) IN (SELECT * FROM t1));
+SELECT a;
+END;
+$$
+a
+1
+BEGIN NOT ATOMIC
+DECLARE a INT DEFAULT EXISTS (SELECT * FROM t1);
+SELECT a;
+END;
+$$
+a
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+RETURN ((1) IN (SELECT * FROM t1));
+END;
+$$
+CREATE FUNCTION f2() RETURNS INT
+BEGIN
+RETURN EXISTS (SELECT * FROM t1 WHERE a=1);
+END;
+$$
+SELECT f1();
+f1()
+1
+SELECT f2();
+f2()
+1
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(1 IN (SELECT * FROM t1));
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+va
+2
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(EXISTS (SELECT * FROM t1));
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+va
+2
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+CREATE PROCEDURE p1()
+BEGIN
+CASE unknown_identifier WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+CASE unknown_identifier.a WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+CASE unknown_identifier.a.b WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+CASE unknown_identifier.a.b.c WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+IF unknown_identifier THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+IF unknown_identifier.a THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+IF unknown_identifier.a.b THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+IF unknown_identifier.a.b.c THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+WHILE unknown_identifier DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+WHILE unknown_identifier.a DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+WHILE unknown_identifier.a.b DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+WHILE unknown_identifier.a.b.c DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a.b;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a.b.c;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN 0..unknown_identifier
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN 0..unknown_identifier.field1
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier.field1
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN 0..unknown_identifier.field1.field2
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: field1.field2
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN unknown_identifier..10
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN unknown_identifier.field1..10
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier.field1
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN unknown_identifier.field1.field2..10
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: field1.field2
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT DEFAULT unknown_identifier;
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT DEFAULT unknown_identifier.a;
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT DEFAULT unknown_identifier.a.b;
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(unknown_identifier);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'ORDER clause'
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(unknown_identifier.a);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'ORDER clause'
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(unknown_identifier.a.b);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'ORDER clause'
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(unknown_identifier.a.b.c);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'ORDER clause'
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+# (testing aggregate functions)
+CREATE PROCEDURE p1()
+BEGIN
+CASE SUM(1) WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1()
+BEGIN
+IF SUM(1) THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1()
+BEGIN
+WHILE SUM(1) DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1()
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL SUM(1);
+END REPEAT;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN 0..SUM(1)
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN SUM(1)..10
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT DEFAULT SUM(1);
+SELECT a;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE FUNCTION f1() RETURNS INT RETURN SUM(1);
+ERROR HY000: Invalid use of group function
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(SUM(1));
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR HY000: Invalid use of group function
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+# (testing window functions)
+CREATE PROCEDURE p1()
+BEGIN
+CASE ROW_NUMBER() OVER() WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1()
+BEGIN
+IF ROW_NUMBER() OVER() THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1()
+BEGIN
+WHILE ROW_NUMBER() OVER() DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1()
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL ROW_NUMBER() OVER();
+END REPEAT;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN 0..ROW_NUMBER() OVER()
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1()
+BEGIN
+FOR i IN ROW_NUMBER() OVER()..10
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT DEFAULT ROW_NUMBER() OVER();
+SELECT a;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE FUNCTION f1() RETURNS INT RETURN ROW_NUMBER() OVER();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(ROW_NUMBER() OVER());
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+DROP TABLE t1;
diff --git a/mysql-test/main/sp-expr.test b/mysql-test/main/sp-expr.test
new file mode 100644
index 0000000..6c61e7a
--- /dev/null
+++ b/mysql-test/main/sp-expr.test
@@ -0,0 +1,804 @@
+# Testing expressions of different kinds in various parts of SP syntax
+
+--echo #
+--echo # Start of 10.4 tests
+--echo #
+
+#
+# Subselects in SP control structures
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DELIMITER $$;
+
+BEGIN NOT ATOMIC
+ CASE ((1) IN (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+BEGIN NOT ATOMIC
+ CASE (EXISTS (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+BEGIN NOT ATOMIC
+ IF ((1) IN (SELECT a FROM t1)) THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+BEGIN NOT ATOMIC
+ IF (EXISTS (SELECT a FROM t1)) THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+BEGIN NOT ATOMIC
+ WHILE ((1234) IN (SELECT * FROM t1)) DO
+ SELECT 1;
+ END WHILE;
+END;
+$$
+BEGIN NOT ATOMIC
+ WHILE (EXISTS (SELECT * FROM t1 WHERE a=1234)) DO
+ SELECT 1;
+ END WHILE;
+END;
+$$
+
+BEGIN NOT ATOMIC
+ REPEAT
+ SELECT 1;
+ UNTIL (1 IN (SELECT * FROM t1))
+ END REPEAT;
+END;
+$$
+BEGIN NOT ATOMIC
+ REPEAT
+ SELECT 1;
+ UNTIL EXISTS (SELECT * FROM t1 WHERE a=1)
+ END REPEAT;
+END;
+$$
+
+BEGIN NOT ATOMIC
+ FOR i IN 0..(1 IN (SELECT * FROM t1))
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+BEGIN NOT ATOMIC
+ FOR i IN 0..EXISTS (SELECT * FROM t1 WHERE a=1)
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+#
+# Subselects as SP variable default values
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+BEGIN NOT ATOMIC
+ DECLARE a INT DEFAULT ((10) IN (SELECT * FROM t1));
+ SELECT a;
+END;
+$$
+BEGIN NOT ATOMIC
+ DECLARE a INT DEFAULT EXISTS (SELECT * FROM t1);
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+#
+# Subselects SP function return values
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DELIMITER $$;
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+ RETURN ((1) IN (SELECT * FROM t1));
+END;
+$$
+CREATE FUNCTION f2() RETURNS INT
+BEGIN
+ RETURN EXISTS (SELECT * FROM t1 WHERE a=1);
+END;
+$$
+DELIMITER ;$$
+SELECT f1();
+SELECT f2();
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
+
+
+#
+# Subselects in CURSOR parameters
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DELIMITER $$;
+BEGIN NOT ATOMIC
+ DECLARE va INT;
+ DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+ OPEN cur(1 IN (SELECT * FROM t1));
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+BEGIN NOT ATOMIC
+ DECLARE va INT;
+ DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+ OPEN cur(EXISTS (SELECT * FROM t1));
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+--echo #
+
+#
+# Unknown identifiers in CASE SP control
+#
+
+DELIMITER $$;
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ CASE unknown_identifier WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ CASE unknown_identifier.a WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ CASE unknown_identifier.a.b WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ CASE unknown_identifier.a.b.c WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+
+#
+# Unknown identifier in IF
+#
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ IF unknown_identifier THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ IF unknown_identifier.a THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ IF unknown_identifier.a.b THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ IF unknown_identifier.a.b.c THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+
+#
+# Unknown identifier in WHILE
+#
+
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ WHILE unknown_identifier DO
+ SELECT 1;
+ END WHILE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ WHILE unknown_identifier.a DO
+ SELECT 1;
+ END WHILE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ WHILE unknown_identifier.a.b DO
+ SELECT 1;
+ END WHILE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ WHILE unknown_identifier.a.b.c DO
+ SELECT 1;
+ END WHILE;
+END;
+$$
+
+
+
+#
+# Unknown identifier in REPEAT
+#
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL unknown_identifier;
+ END REPEAT;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL unknown_identifier.a;
+ END REPEAT;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL unknown_identifier.a.b;
+ END REPEAT;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL unknown_identifier.a.b.c;
+ END REPEAT;
+END;
+$$
+
+
+#
+# Unknown identifier in FOR
+#
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN 0..unknown_identifier
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN 0..unknown_identifier.field1
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN 0..unknown_identifier.field1.field2
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN unknown_identifier..10
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN unknown_identifier.field1..10
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN unknown_identifier.field1.field2..10
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+DELIMITER ;$$
+
+
+#
+# Unknown identifiers as SP variable default values
+#
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT DEFAULT unknown_identifier;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT DEFAULT unknown_identifier.a;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT DEFAULT unknown_identifier.a.b;
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+#
+# Unknown identifiers as SP function return values
+#
+
+--error ER_BAD_FIELD_ERROR
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier;
+
+--error ER_BAD_FIELD_ERROR
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a;
+
+--error ER_BAD_FIELD_ERROR
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a.b;
+
+--error ER_BAD_FIELD_ERROR
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a.b.c;
+
+
+#
+# Unknown identifiers in CURSOR parameters
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DELIMITER $$;
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE va INT;
+ DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+ OPEN cur(unknown_identifier);
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE va INT;
+ DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+ OPEN cur(unknown_identifier.a);
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE va INT;
+ DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+ OPEN cur(unknown_identifier.a.b);
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE va INT;
+ DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+ OPEN cur(unknown_identifier.a.b.c);
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+--echo #
+
+--echo # (testing aggregate functions)
+
+#
+# Aggregate functions in CASE SP control
+#
+
+DELIMITER $$;
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1()
+BEGIN
+ CASE SUM(1) WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+
+#
+# Aggregate function in IF
+#
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1()
+BEGIN
+ IF SUM(1) THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+
+#
+# Aggregate function in WHILE
+#
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1()
+BEGIN
+ WHILE SUM(1) DO
+ SELECT 1;
+ END WHILE;
+END;
+$$
+
+
+#
+# Aggregate function in REPEAT
+#
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1()
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL SUM(1);
+ END REPEAT;
+END;
+$$
+
+
+#
+# Aggregate function in FOR
+#
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN 0..SUM(1)
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN SUM(1)..10
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+
+DELIMITER ;$$
+
+
+#
+# Aggregate functions as SP variable default values
+#
+
+DELIMITER $$;
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT DEFAULT SUM(1);
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+
+#
+# Aggregate functions as SP function return values
+#
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE FUNCTION f1() RETURNS INT RETURN SUM(1);
+
+
+#
+# Aggregate functions in CURSOR parameters
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DELIMITER $$;
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE va INT;
+ DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+ OPEN cur(SUM(1));
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+--echo #
+
+--echo # (testing window functions)
+
+#
+# Aggregate functions in CASE SP control
+#
+
+DELIMITER $$;
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1()
+BEGIN
+ CASE ROW_NUMBER() OVER() WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+
+#
+# Aggregate function in IF
+#
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1()
+BEGIN
+ IF ROW_NUMBER() OVER() THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+
+#
+# Aggregate function in WHILE
+#
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1()
+BEGIN
+ WHILE ROW_NUMBER() OVER() DO
+ SELECT 1;
+ END WHILE;
+END;
+$$
+
+
+#
+# Aggregate function in REPEAT
+#
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1()
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL ROW_NUMBER() OVER();
+ END REPEAT;
+END;
+$$
+
+
+#
+# Aggregate function in FOR
+#
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN 0..ROW_NUMBER() OVER()
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1()
+BEGIN
+ FOR i IN ROW_NUMBER() OVER()..10
+ DO
+ SELECT i;
+ END FOR;
+END;
+$$
+
+
+DELIMITER ;$$
+
+
+#
+# Aggregate functions as SP variable default values
+#
+
+DELIMITER $$;
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT DEFAULT ROW_NUMBER() OVER();
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+
+#
+# Aggregate functions as SP function return values
+#
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE FUNCTION f1() RETURNS INT RETURN ROW_NUMBER() OVER();
+
+
+#
+# Aggregate functions in CURSOR parameters
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DELIMITER $$;
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE va INT;
+ DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+ OPEN cur(ROW_NUMBER() OVER());
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+
+DELIMITER ;$$
+DROP TABLE t1;
diff --git a/mysql-test/main/sp.result b/mysql-test/main/sp.result
index a79d90d..572015d 100644
--- a/mysql-test/main/sp.result
+++ b/mysql-test/main/sp.result
@@ -4179,6 +4179,7 @@ select v, isnull(v);
end if;
end;
end|
+ERROR 42S22: Unknown column 'undefined_var' in 'field list'
create procedure bug14643_2()
begin
declare continue handler for sqlexception select 'boo' as 'Handler';
@@ -4190,18 +4191,7 @@ select 2;
end case;
select undefined_var;
end|
-call bug14643_1()|
-Handler
-boo
-v isnull(v)
-NULL 1
-call bug14643_2()|
-Handler
-boo
-Handler
-boo
-drop procedure bug14643_1|
-drop procedure bug14643_2|
+ERROR 42S22: Unknown column 'undefined_var' in 'field list'
drop procedure if exists bug14304|
drop table if exists t3, t4|
create table t3(a int primary key auto_increment)|
@@ -4231,9 +4221,7 @@ create procedure bug14376()
begin
declare x int default x;
end|
-call bug14376()|
ERROR 42S22: Unknown column 'x' in 'field list'
-drop procedure bug14376|
create procedure bug14376()
begin
declare x int default 42;
@@ -4476,6 +4464,7 @@ select 'no' as 'v';
end if;
select 'done' as 'End';
end|
+ERROR 42S22: Unknown column 'v' in 'field list'
create procedure bug14498_2()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -4484,6 +4473,7 @@ select 'yes' as 'v';
end while;
select 'done' as 'End';
end|
+ERROR 42S22: Unknown column 'v' in 'field list'
create procedure bug14498_3()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -4492,6 +4482,7 @@ select 'maybe' as 'v';
until v end repeat;
select 'done' as 'End';
end|
+ERROR 42S22: Unknown column 'v' in 'field list'
create procedure bug14498_4()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -4505,6 +4496,7 @@ select '?' as 'v';
end case;
select 'done' as 'End';
end|
+ERROR 42S22: Unknown column 'v' in 'field list'
create procedure bug14498_5()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -4518,38 +4510,7 @@ select '?' as 'v';
end case;
select 'done' as 'End';
end|
-call bug14498_1()|
-Handler
-error
-End
-done
-call bug14498_2()|
-Handler
-error
-End
-done
-call bug14498_3()|
-v
-maybe
-Handler
-error
-End
-done
-call bug14498_4()|
-Handler
-error
-End
-done
-call bug14498_5()|
-Handler
-error
-End
-done
-drop procedure bug14498_1|
-drop procedure bug14498_2|
-drop procedure bug14498_3|
-drop procedure bug14498_4|
-drop procedure bug14498_5|
+ERROR 42S22: Unknown column 'v' in 'field list'
drop table if exists t3|
drop procedure if exists bug15231_1|
drop procedure if exists bug15231_2|
@@ -8316,14 +8277,12 @@ DECLARE name VARCHAR(10);
SET name="hello";
call p1(name2);
END|
+ERROR 42S22: Unknown column 'name2' in 'field list'
call p2();
a
hello
-call p3();
-ERROR 42S22: Unknown column 'name2' in 'field list'
drop procedure p1;
drop procedure p2;
-drop procedure p3;
#
# MDEV-15328: MariaDB 10.2.13 Crashes upon CALL PROCEDURE PARAM
# LAST_INSERT_ID ()
diff --git a/mysql-test/main/sp.test b/mysql-test/main/sp.test
index 56dea01..3d0a6b8 100644
--- a/mysql-test/main/sp.test
+++ b/mysql-test/main/sp.test
@@ -5040,6 +5040,7 @@ drop procedure if exists bug14643_1|
drop procedure if exists bug14643_2|
--enable_warnings
+--error ER_BAD_FIELD_ERROR
create procedure bug14643_1()
begin
declare continue handler for sqlexception select 'boo' as 'Handler';
@@ -5055,6 +5056,7 @@ begin
end;
end|
+--error ER_BAD_FIELD_ERROR
create procedure bug14643_2()
begin
declare continue handler for sqlexception select 'boo' as 'Handler';
@@ -5069,11 +5071,6 @@ begin
select undefined_var;
end|
-call bug14643_1()|
-call bug14643_2()|
-
-drop procedure bug14643_1|
-drop procedure bug14643_2|
#
# BUG#14304: auto_increment field incorrect set in SP
@@ -5114,15 +5111,12 @@ drop table t3, t4|
drop procedure if exists bug14376|
--enable_warnings
+--error ER_BAD_FIELD_ERROR
create procedure bug14376()
begin
declare x int default x;
end|
-# Not the error we want, but that's what we got for now...
---error ER_BAD_FIELD_ERROR
-call bug14376()|
-drop procedure bug14376|
create procedure bug14376()
begin
@@ -5344,6 +5338,7 @@ drop procedure if exists bug14498_4|
drop procedure if exists bug14498_5|
--enable_warnings
+--error ER_BAD_FIELD_ERROR
create procedure bug14498_1()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -5356,6 +5351,7 @@ begin
select 'done' as 'End';
end|
+--error ER_BAD_FIELD_ERROR
create procedure bug14498_2()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -5366,6 +5362,7 @@ begin
select 'done' as 'End';
end|
+--error ER_BAD_FIELD_ERROR
create procedure bug14498_3()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -5376,6 +5373,7 @@ begin
select 'done' as 'End';
end|
+--error ER_BAD_FIELD_ERROR
create procedure bug14498_4()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -5391,6 +5389,7 @@ begin
select 'done' as 'End';
end|
+--error ER_BAD_FIELD_ERROR
create procedure bug14498_5()
begin
declare continue handler for sqlexception select 'error' as 'Handler';
@@ -5406,17 +5405,6 @@ begin
select 'done' as 'End';
end|
-call bug14498_1()|
-call bug14498_2()|
-call bug14498_3()|
-call bug14498_4()|
-call bug14498_5()|
-
-drop procedure bug14498_1|
-drop procedure bug14498_2|
-drop procedure bug14498_3|
-drop procedure bug14498_4|
-drop procedure bug14498_5|
#
# BUG#15231: Stored procedure bug with not found condition handler
@@ -9828,6 +9816,8 @@ BEGIN
SET name="hello";
call p1(name);
END|
+
+--error ER_BAD_FIELD_ERROR
CREATE OR REPLACE PROCEDURE p3 ()
BEGIN
DECLARE name VARCHAR(10);
@@ -9838,11 +9828,8 @@ END|
DELIMITER ;|
call p2();
---error ER_BAD_FIELD_ERROR
-call p3();
drop procedure p1;
drop procedure p2;
-drop procedure p3;
--echo #
--echo # MDEV-15328: MariaDB 10.2.13 Crashes upon CALL PROCEDURE PARAM
diff --git a/mysql-test/main/statement-expr.result b/mysql-test/main/statement-expr.result
new file mode 100644
index 0000000..2e7e3ab
--- /dev/null
+++ b/mysql-test/main/statement-expr.result
@@ -0,0 +1,217 @@
+CREATE TABLE t1 (id INT, id1 INT);
+INSERT INTO t1 VALUES (1,7);
+INSERT INTO t1 VALUES (1,8);
+SELECT ROW(1,7) IN (SELECT id, id1 FROM t1 WHERE id1= 8);
+ROW(1,7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)
+0
+EXECUTE IMMEDIATE 'SELECT ROW(1, 7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)';
+ROW(1, 7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)
+0
+DROP TABLE t1;
+EXECUTE IMMEDIATE 'SELECT ?' USING (1 IN (SELECT * FROM t1));
+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 * FROM t1))' at line 1
+EXECUTE IMMEDIATE 'SELECT ?' USING (SELECT * FROM t1);
+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 * FROM t1)' at line 1
+CREATE TABLE t1 (id INT);
+INSERT INTO t1 VALUES (10);
+CREATE PROCEDURE p1(a INT) BEGIN END;
+CALL p1((1) IN (SELECT * FROM t1));
+CALL p1(EXISTS (SELECT * FROM t1));
+DROP PROCEDURE p1;
+DROP TABLE t1;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=(1 IN (SELECT * FROM t1));
+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 '(1 IN (SELECT * FROM t1))' at line 1
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=EXISTS (SELECT * FROM t1);
+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 'EXISTS (SELECT * FROM t1)' at line 1
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=(1 IN (SELECT * FROM t1));
+SIGNAL SQLSTATE '01000';
+END;
+$$
+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 '(1 IN (SELECT * FROM t1));
+SIGNAL SQLSTATE '01000';
+END' at line 3
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=EXISTS (SELECT * FROM t1);
+SIGNAL SQLSTATE '01000';
+END;
+$$
+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 'EXISTS (SELECT * FROM t1);
+SIGNAL SQLSTATE '01000';
+END' at line 3
+PREPARE stmt FROM (1 IN (SELECT * FROM t1));
+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 * FROM t1))' at line 1
+PREPARE stmt FROM EXISTS (SELECT * FROM t1);
+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 * FROM t1)' at line 1
+EXECUTE IMMEDIATE (1 IN (SELECT * FROM t1));
+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 * FROM t1))' at line 1
+EXECUTE IMMEDIATE EXISTS (SELECT * FROM t1);
+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 * FROM t1)' at line 1
+GET DIAGNOSTICS CONDITION (1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO;
+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 '(1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO' at line 1
+GET DIAGNOSTICS CONDITION EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO;
+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 'EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO' at line 1
+PURGE BINARY LOGS BEFORE (1 IN (SELECT * FROM t1));
+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 * FROM t1))' at line 1
+PURGE BINARY LOGS BEFORE EXISTS (SELECT * FROM t1);
+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 * FROM t1)' at line 1
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DO 1 IN (SELECT * FROM t1);
+DO EXISTS (SELECT * FROM t1);
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1(a INT) BEGIN END;
+CALL p1(unknown_identifier);
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CALL p1(unknown_identifier.a);
+ERROR 42S22: Unknown column 'a' in 'field list'
+CALL p1(unknown_identifier.a.b);
+ERROR 42S22: Unknown column 'b' in 'field list'
+CALL p1(unknown_identifier.a.b.c);
+ERROR 42S22: Unknown column 'b' in 'field list'
+DROP PROCEDURE p1;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=unknown_identifier;
+SIGNAL SQLSTATE '01000';
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a;
+SIGNAL SQLSTATE '01000';
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a.b;
+SIGNAL SQLSTATE '01000';
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a.b.c;
+SIGNAL SQLSTATE '01000';
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+PREPARE stmt FROM unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+PREPARE stmt FROM unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+PREPARE stmt FROM unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+PREPARE stmt FROM unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+EXECUTE IMMEDIATE unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+EXECUTE IMMEDIATE unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+EXECUTE IMMEDIATE unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+EXECUTE IMMEDIATE unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+GET DIAGNOSTICS CONDITION unknown_identifier @errno=MYSQL_ERRNO;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+GET DIAGNOSTICS CONDITION unknown_identifier.a @errno=MYSQL_ERRNO;
+ERROR 42S22: Unknown column 'a' in 'field list'
+GET DIAGNOSTICS CONDITION unknown_identifier.a.b @errno=MYSQL_ERRNO;
+ERROR 42S22: Unknown column 'b' in 'field list'
+GET DIAGNOSTICS CONDITION unknown_identifier.a.b.c @errno=MYSQL_ERRNO;
+ERROR 42S22: Unknown column 'b' in 'field list'
+PURGE BINARY LOGS BEFORE unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+PURGE BINARY LOGS BEFORE unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+PURGE BINARY LOGS BEFORE unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+PURGE BINARY LOGS BEFORE unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1()
+BEGIN
+DO unknown_identifier;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+#
+# MDEV-15870 Using aggregate and window function in unexpected places can crash the server
+#
+# (aggreate functions)
+EXECUTE IMMEDIATE 'SELECT ?' USING SUM(1);
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1(a INT) BEGIN END;
+CALL p1(SUM(1));
+ERROR HY000: Invalid use of group function
+DROP PROCEDURE p1;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=SUM(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 'SUM(1)' at line 1
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=SUM(1);
+SIGNAL SQLSTATE '01000';
+END;
+$$
+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 'SUM(1);
+SIGNAL SQLSTATE '01000';
+END' at line 3
+PREPARE stmt FROM SUM(1);
+ERROR HY000: Invalid use of group function
+EXECUTE IMMEDIATE SUM(1);
+ERROR HY000: Invalid use of group function
+GET DIAGNOSTICS CONDITION SUM(1) @errno=MYSQL_ERRNO;
+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 'SUM(1) @errno=MYSQL_ERRNO' at line 1
+PURGE BINARY LOGS BEFORE SUM(1);
+ERROR HY000: Invalid use of group function
+#
+# MDEV-15870 Using aggregate and window function in unexpected places can crash the server
+#
+# (window functions)
+EXECUTE IMMEDIATE 'SELECT ?' USING ROW_NUMBER() OVER ();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1(a INT) BEGIN END;
+CALL p1(ROW_NUMBER() OVER ());
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+DROP PROCEDURE p1;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=ROW_NUMBER() OVER ();
+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 'ROW_NUMBER() OVER ()' at line 1
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=ROW_NUMBER() OVER ();
+SIGNAL SQLSTATE '01000';
+END;
+$$
+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 'ROW_NUMBER() OVER ();
+SIGNAL SQLSTATE '01000';
+END' at line 3
+PREPARE stmt FROM ROW_NUMBER() OVER ();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+EXECUTE IMMEDIATE ROW_NUMBER() OVER ();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+GET DIAGNOSTICS CONDITION ROW_NUMBER() OVER () @errno=MYSQL_ERRNO;
+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 'ROW_NUMBER() OVER () @errno=MYSQL_ERRNO' at line 1
+PURGE BINARY LOGS BEFORE ROW_NUMBER() OVER ();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
diff --git a/mysql-test/main/statement-expr.test b/mysql-test/main/statement-expr.test
new file mode 100644
index 0000000..7b96a7d
--- /dev/null
+++ b/mysql-test/main/statement-expr.test
@@ -0,0 +1,291 @@
+# Testing expressions of different kinds in various non-SELECT statements
+
+
+#
+# Subselects in non-SELECT statements
+#
+
+CREATE TABLE t1 (id INT, id1 INT);
+INSERT INTO t1 VALUES (1,7);
+INSERT INTO t1 VALUES (1,8);
+SELECT ROW(1,7) IN (SELECT id, id1 FROM t1 WHERE id1= 8);
+EXECUTE IMMEDIATE 'SELECT ROW(1, 7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)';
+DROP TABLE t1;
+
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING (1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING (SELECT * FROM t1);
+
+
+CREATE TABLE t1 (id INT);
+INSERT INTO t1 VALUES (10);
+CREATE PROCEDURE p1(a INT) BEGIN END;
+CALL p1((1) IN (SELECT * FROM t1));
+CALL p1(EXISTS (SELECT * FROM t1));
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=(1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=EXISTS (SELECT * FROM t1);
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=(1 IN (SELECT * FROM t1));
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=EXISTS (SELECT * FROM t1);
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+DELIMITER ;$$
+
+
+--error ER_PARSE_ERROR
+PREPARE stmt FROM (1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+PREPARE stmt FROM EXISTS (SELECT * FROM t1);
+
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE (1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE EXISTS (SELECT * FROM t1);
+
+--error ER_PARSE_ERROR
+GET DIAGNOSTICS CONDITION (1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO;
+--error ER_PARSE_ERROR
+GET DIAGNOSTICS CONDITION EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO;
+
+--error ER_PARSE_ERROR
+PURGE BINARY LOGS BEFORE (1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+PURGE BINARY LOGS BEFORE EXISTS (SELECT * FROM t1);
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DO 1 IN (SELECT * FROM t1);
+DO EXISTS (SELECT * FROM t1);
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+--echo #
+
+#TODO: warp into CREATE
+
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a.b.c;
+
+
+CREATE PROCEDURE p1(a INT) BEGIN END;
+--error ER_BAD_FIELD_ERROR
+CALL p1(unknown_identifier);
+--error ER_BAD_FIELD_ERROR
+CALL p1(unknown_identifier.a);
+--error ER_BAD_FIELD_ERROR
+CALL p1(unknown_identifier.a.b);
+--error ER_BAD_FIELD_ERROR
+CALL p1(unknown_identifier.a.b.c);
+DROP PROCEDURE p1;
+
+
+--error ER_BAD_FIELD_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a.b.c;
+
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=unknown_identifier;
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+--error ER_BAD_FIELD_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a;
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+--error ER_BAD_FIELD_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a.b;
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+--error ER_BAD_FIELD_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a.b.c;
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+DELIMITER ;$$
+
+
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM unknown_identifier.a.b.c;
+
+
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE unknown_identifier.a.b.c;
+
+
+--error ER_BAD_FIELD_ERROR
+GET DIAGNOSTICS CONDITION unknown_identifier @errno=MYSQL_ERRNO;
+--error ER_BAD_FIELD_ERROR
+GET DIAGNOSTICS CONDITION unknown_identifier.a @errno=MYSQL_ERRNO;
+--error ER_BAD_FIELD_ERROR
+GET DIAGNOSTICS CONDITION unknown_identifier.a.b @errno=MYSQL_ERRNO;
+--error ER_BAD_FIELD_ERROR
+GET DIAGNOSTICS CONDITION unknown_identifier.a.b.c @errno=MYSQL_ERRNO;
+
+
+--error ER_BAD_FIELD_ERROR
+PURGE BINARY LOGS BEFORE unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+PURGE BINARY LOGS BEFORE unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+PURGE BINARY LOGS BEFORE unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+PURGE BINARY LOGS BEFORE unknown_identifier.a.b.c;
+
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DO unknown_identifier;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # MDEV-15870 Using aggregate and window function in unexpected places can crash the server
+--echo #
+
+--echo # (aggreate functions)
+
+--error ER_INVALID_GROUP_FUNC_USE
+EXECUTE IMMEDIATE 'SELECT ?' USING SUM(1);
+
+
+CREATE PROCEDURE p1(a INT) BEGIN END;
+--error ER_INVALID_GROUP_FUNC_USE
+CALL p1(SUM(1));
+DROP PROCEDURE p1;
+
+
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=SUM(1);
+
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=SUM(1);
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+DELIMITER ;$$
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+PREPARE stmt FROM SUM(1);
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+EXECUTE IMMEDIATE SUM(1);
+
+
+--error ER_PARSE_ERROR
+GET DIAGNOSTICS CONDITION SUM(1) @errno=MYSQL_ERRNO;
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+PURGE BINARY LOGS BEFORE SUM(1);
+
+
+
+--echo #
+--echo # MDEV-15870 Using aggregate and window function in unexpected places can crash the server
+--echo #
+
+--echo # (window functions)
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+EXECUTE IMMEDIATE 'SELECT ?' USING ROW_NUMBER() OVER ();
+
+
+CREATE PROCEDURE p1(a INT) BEGIN END;
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CALL p1(ROW_NUMBER() OVER ());
+DROP PROCEDURE p1;
+
+
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=ROW_NUMBER() OVER ();
+
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=ROW_NUMBER() OVER ();
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+DELIMITER ;$$
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+PREPARE stmt FROM ROW_NUMBER() OVER ();
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+EXECUTE IMMEDIATE ROW_NUMBER() OVER ();
+
+
+--error ER_PARSE_ERROR
+GET DIAGNOSTICS CONDITION ROW_NUMBER() OVER () @errno=MYSQL_ERRNO;
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+PURGE BINARY LOGS BEFORE ROW_NUMBER() OVER ();
diff --git a/mysql-test/suite/compat/oracle/r/sp-expr.result b/mysql-test/suite/compat/oracle/r/sp-expr.result
new file mode 100644
index 0000000..e9383d5
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-expr.result
@@ -0,0 +1,585 @@
+SET sql_mode=ORACLE;
+#
+# Start of 10.4 tests
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+BEGIN
+CASE ((1) IN (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+1
+1
+BEGIN
+CASE (EXISTS (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+1
+1
+BEGIN
+IF ((1) IN (SELECT a FROM t1)) THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+1
+1
+BEGIN
+IF (EXISTS (SELECT a FROM t1)) THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+1
+1
+BEGIN
+WHILE ((1234) IN (SELECT * FROM t1)) LOOP
+SELECT 1;
+END LOOP;
+END;
+$$
+BEGIN
+WHILE (EXISTS (SELECT * FROM t1 WHERE a=1234)) LOOP
+SELECT 1;
+END LOOP;
+END;
+$$
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL (1 IN (SELECT * FROM t1))
+END REPEAT;
+END;
+$$
+1
+1
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL EXISTS (SELECT * FROM t1 WHERE a=1)
+END REPEAT;
+END;
+$$
+1
+1
+BEGIN
+FOR i IN 0..(1 IN (SELECT * FROM t1))
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+i
+0
+i
+1
+BEGIN
+FOR i IN 0..EXISTS (SELECT * FROM t1 WHERE a=1)
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+i
+0
+i
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+DECLARE
+a INT DEFAULT ((10) IN (SELECT * FROM t1));
+BEGIN
+SELECT a;
+END;
+$$
+a
+1
+DECLARE
+a INT DEFAULT EXISTS (SELECT * FROM t1);
+BEGIN
+SELECT a;
+END;
+$$
+a
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE FUNCTION f1() RETURN INT AS
+BEGIN
+RETURN ((1) IN (SELECT * FROM t1));
+END;
+$$
+CREATE FUNCTION f2() RETURN INT AS
+BEGIN
+RETURN EXISTS (SELECT * FROM t1 WHERE a=1);
+END;
+$$
+SELECT f1();
+f1()
+1
+SELECT f2();
+f2()
+1
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DECLARE
+va INT;
+CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+OPEN cur(1 IN (SELECT * FROM t1));
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+va
+2
+DECLARE
+va INT;
+CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+OPEN cur(EXISTS (SELECT * FROM t1));
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+va
+2
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+CREATE PROCEDURE p1() AS
+BEGIN
+CASE unknown_identifier WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+CASE unknown_identifier.a WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+CASE unknown_identifier.a.b WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+CASE unknown_identifier.a.b.c WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+IF unknown_identifier THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+IF unknown_identifier.a THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+IF unknown_identifier.a.b THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+IF unknown_identifier.a.b.c THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+WHILE unknown_identifier LOOP
+SELECT 1;
+END LOOP;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+WHILE unknown_identifier.a LOOP
+SELECT 1;
+END LOOP;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+WHILE unknown_identifier.a.b LOOP
+SELECT 1;
+END LOOP;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+WHILE unknown_identifier.a.b.c LOOP
+SELECT 1;
+END LOOP;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a.b;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a.b.c;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN 0..unknown_identifier
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN 0..unknown_identifier.field1
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier.field1
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN 0..unknown_identifier.field1.field2
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR 42000: Undeclared variable: field1.field2
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN unknown_identifier..10
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN unknown_identifier.field1..10
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier.field1
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN unknown_identifier.field1.field2..10
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR 42000: Undeclared variable: field1.field2
+CREATE PROCEDURE p1() AS
+a INT DEFAULT unknown_identifier;
+BEGIN
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE PROCEDURE p1() AS
+a INT DEFAULT unknown_identifier.a;
+BEGIN
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE PROCEDURE p1() AS
+a INT DEFAULT unknown_identifier.a.b;
+BEGIN
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN unknown_identifier; END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN unknown_identifier.a; END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN unknown_identifier.a.b; END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN unknown_identifier.a.b.c; END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE PROCEDURE p1() AS
+va INT;
+CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+OPEN cur(unknown_identifier);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'ORDER clause'
+CREATE PROCEDURE p1() AS
+va INT;
+CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+OPEN cur(unknown_identifier.a);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'ORDER clause'
+CREATE PROCEDURE p1() AS
+va INT;
+CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+OPEN cur(unknown_identifier.a.b);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'ORDER clause'
+CREATE PROCEDURE p1() AS
+va INT;
+CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+OPEN cur(unknown_identifier.a.b.c);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'ORDER clause'
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+# (testing aggregate functions)
+CREATE PROCEDURE p1() AS
+BEGIN
+CASE SUM(1) WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1() AS
+BEGIN
+IF SUM(1) THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1() AS
+BEGIN
+WHILE SUM(1) LOOP
+SELECT 1;
+END LOOP;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1() AS
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL SUM(1);
+END REPEAT;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN 0..SUM(1)
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN SUM(1)..10
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1() AS
+a INT DEFAULT SUM(1);
+BEGIN
+SELECT a;
+END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN SUM(1); END;
+$$
+ERROR HY000: Invalid use of group function
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE PROCEDURE p1() AS
+va INT;
+CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+OPEN cur(SUM(1));
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR HY000: Invalid use of group function
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+# (testing window functions)
+CREATE PROCEDURE p1() AS
+BEGIN
+CASE ROW_NUMBER() OVER() WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1() AS
+BEGIN
+IF ROW_NUMBER() OVER() THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1() AS
+BEGIN
+WHILE ROW_NUMBER() OVER() LOOP
+SELECT 1;
+END LOOP;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1() AS
+BEGIN
+REPEAT
+SELECT 1;
+UNTIL ROW_NUMBER() OVER();
+END REPEAT;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN 0..ROW_NUMBER() OVER()
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1() AS
+BEGIN
+FOR i IN ROW_NUMBER() OVER()..10
+LOOP
+SELECT i;
+END LOOP;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1() AS
+a INT DEFAULT ROW_NUMBER() OVER();
+BEGIN
+SELECT a;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN ROW_NUMBER() OVER(); END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+CREATE PROCEDURE p1() AS
+va INT;
+CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+OPEN cur(ROW_NUMBER() OVER());
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/r/sp.result b/mysql-test/suite/compat/oracle/r/sp.result
index 7f04282..2049f23 100644
--- a/mysql-test/suite/compat/oracle/r/sp.result
+++ b/mysql-test/suite/compat/oracle/r/sp.result
@@ -1019,9 +1019,7 @@ LOOP
EXIT WHEN unknown_ident IS NULL;
END LOOP;
END$$
-CALL p1;
ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
-DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
BEGIN
@@ -1030,9 +1028,7 @@ LOOP
EXIT label WHEN unknown_ident IS NULL;
END LOOP;
END$$
-CALL p1;
ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
-DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
BEGIN
@@ -1040,9 +1036,7 @@ LOOP
CONTINUE WHEN unknown_ident IS NULL;
END LOOP;
END$$
-CALL p1;
ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
-DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
BEGIN
@@ -1051,9 +1045,7 @@ LOOP
CONTINUE label WHEN unknown_ident IS NULL;
END LOOP;
END$$
-CALL p1;
ERROR 42S22: Unknown column 'unknown_ident' in 'field list'
-DROP PROCEDURE p1;
#
# MDEV-10583 sql_mode=ORACLE: SQL%ROWCOUNT
#
diff --git a/mysql-test/suite/compat/oracle/r/statement-expr.result b/mysql-test/suite/compat/oracle/r/statement-expr.result
new file mode 100644
index 0000000..3f37a22
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/statement-expr.result
@@ -0,0 +1,222 @@
+SET sql_mode=ORACLE;
+CREATE TABLE t1 (id INT, id1 INT);
+INSERT INTO t1 VALUES (1,7);
+INSERT INTO t1 VALUES (1,8);
+SELECT ROW(1,7) IN (SELECT id, id1 FROM t1 WHERE id1= 8);
+ROW(1,7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)
+0
+EXECUTE IMMEDIATE 'SELECT ROW(1, 7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)';
+ROW(1, 7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)
+0
+DROP TABLE t1;
+EXECUTE IMMEDIATE 'SELECT ?' USING (1 IN (SELECT * FROM t1));
+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 * FROM t1))' at line 1
+EXECUTE IMMEDIATE 'SELECT ?' USING (SELECT * FROM t1);
+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 * FROM t1)' at line 1
+CREATE TABLE t1 (id INT);
+INSERT INTO t1 VALUES (10);
+CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
+$$
+CALL p1((1) IN (SELECT * FROM t1));
+CALL p1(EXISTS (SELECT * FROM t1));
+DROP PROCEDURE p1;
+DROP TABLE t1;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=(1 IN (SELECT * FROM t1));
+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 '(1 IN (SELECT * FROM t1))' at line 1
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=EXISTS (SELECT * FROM t1);
+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 'EXISTS (SELECT * FROM t1)' at line 1
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=(1 IN (SELECT * FROM t1));
+SIGNAL SQLSTATE '01000';
+END;
+$$
+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 '(1 IN (SELECT * FROM t1));
+SIGNAL SQLSTATE '01000';
+END' at line 3
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=EXISTS (SELECT * FROM t1);
+SIGNAL SQLSTATE '01000';
+END;
+$$
+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 'EXISTS (SELECT * FROM t1);
+SIGNAL SQLSTATE '01000';
+END' at line 3
+PREPARE stmt FROM (1 IN (SELECT * FROM t1));
+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 * FROM t1))' at line 1
+PREPARE stmt FROM EXISTS (SELECT * FROM t1);
+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 * FROM t1)' at line 1
+EXECUTE IMMEDIATE (1 IN (SELECT * FROM t1));
+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 * FROM t1))' at line 1
+EXECUTE IMMEDIATE EXISTS (SELECT * FROM t1);
+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 * FROM t1)' at line 1
+GET DIAGNOSTICS CONDITION (1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO;
+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 '(1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO' at line 1
+GET DIAGNOSTICS CONDITION EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO;
+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 'EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO' at line 1
+PURGE BINARY LOGS BEFORE (1 IN (SELECT * FROM t1));
+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 * FROM t1))' at line 1
+PURGE BINARY LOGS BEFORE EXISTS (SELECT * FROM t1);
+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 * FROM t1)' at line 1
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DO 1 IN (SELECT * FROM t1);
+DO EXISTS (SELECT * FROM t1);
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
+$$
+CALL p1(unknown_identifier);
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CALL p1(unknown_identifier.a);
+ERROR 42S22: Unknown column 'a' in 'field list'
+CALL p1(unknown_identifier.a.b);
+ERROR 42S22: Unknown column 'b' in 'field list'
+CALL p1(unknown_identifier.a.b.c);
+ERROR 42S22: Unknown column 'b' in 'field list'
+DROP PROCEDURE p1;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=unknown_identifier;
+SIGNAL SQLSTATE '01000';
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a;
+SIGNAL SQLSTATE '01000';
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a.b;
+SIGNAL SQLSTATE '01000';
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a.b.c;
+SIGNAL SQLSTATE '01000';
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+PREPARE stmt FROM unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+PREPARE stmt FROM unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+PREPARE stmt FROM unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+PREPARE stmt FROM unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+EXECUTE IMMEDIATE unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+EXECUTE IMMEDIATE unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+EXECUTE IMMEDIATE unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+EXECUTE IMMEDIATE unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+GET DIAGNOSTICS CONDITION unknown_identifier @errno=MYSQL_ERRNO;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+GET DIAGNOSTICS CONDITION unknown_identifier.a @errno=MYSQL_ERRNO;
+ERROR 42S22: Unknown column 'a' in 'field list'
+GET DIAGNOSTICS CONDITION unknown_identifier.a.b @errno=MYSQL_ERRNO;
+ERROR 42S22: Unknown column 'b' in 'field list'
+GET DIAGNOSTICS CONDITION unknown_identifier.a.b.c @errno=MYSQL_ERRNO;
+ERROR 42S22: Unknown column 'b' in 'field list'
+PURGE BINARY LOGS BEFORE unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+PURGE BINARY LOGS BEFORE unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+PURGE BINARY LOGS BEFORE unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+PURGE BINARY LOGS BEFORE unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+#
+# MDEV-15870 Using aggregate and window function in unexpected places can crash the server
+#
+# (aggreate functions)
+EXECUTE IMMEDIATE 'SELECT ?' USING SUM(1);
+ERROR HY000: Invalid use of group function
+CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
+$$
+CALL p1(SUM(1));
+ERROR HY000: Invalid use of group function
+DROP PROCEDURE p1;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=SUM(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 'SUM(1)' at line 1
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=SUM(1);
+SIGNAL SQLSTATE '01000';
+END;
+$$
+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 'SUM(1);
+SIGNAL SQLSTATE '01000';
+END' at line 3
+PREPARE stmt FROM SUM(1);
+ERROR HY000: Invalid use of group function
+EXECUTE IMMEDIATE SUM(1);
+ERROR HY000: Invalid use of group function
+GET DIAGNOSTICS CONDITION SUM(1) @errno=MYSQL_ERRNO;
+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 'SUM(1) @errno=MYSQL_ERRNO' at line 1
+PURGE BINARY LOGS BEFORE SUM(1);
+ERROR HY000: Invalid use of group function
+#
+# MDEV-15870 Using aggregate and window function in unexpected places can crash the server
+#
+# (window functions)
+EXECUTE IMMEDIATE 'SELECT ?' USING ROW_NUMBER() OVER ();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
+$$
+CALL p1(ROW_NUMBER() OVER ());
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+DROP PROCEDURE p1;
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=ROW_NUMBER() OVER ();
+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 'ROW_NUMBER() OVER ()' at line 1
+BEGIN NOT ATOMIC
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+RESIGNAL SET MYSQL_ERRNO=ROW_NUMBER() OVER ();
+SIGNAL SQLSTATE '01000';
+END;
+$$
+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 'ROW_NUMBER() OVER ();
+SIGNAL SQLSTATE '01000';
+END' at line 3
+PREPARE stmt FROM ROW_NUMBER() OVER ();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+EXECUTE IMMEDIATE ROW_NUMBER() OVER ();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+GET DIAGNOSTICS CONDITION ROW_NUMBER() OVER () @errno=MYSQL_ERRNO;
+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 'ROW_NUMBER() OVER () @errno=MYSQL_ERRNO' at line 1
+PURGE BINARY LOGS BEFORE ROW_NUMBER() OVER ();
+ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause
+CREATE PROCEDURE p1() AS
+BEGIN
+DO unknown_identifier;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
diff --git a/mysql-test/suite/compat/oracle/t/sp-expr.result b/mysql-test/suite/compat/oracle/t/sp-expr.result
new file mode 100644
index 0000000..38a3d4c
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-expr.result
@@ -0,0 +1,389 @@
+#
+# Start of 10.4 tests
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+BEGIN NOT ATOMIC
+CASE ((1) IN (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+CASE (EXISTS (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+IF ((1) IN (SELECT a FROM t1)) THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+IF (EXISTS (SELECT a FROM t1)) THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+WHILE ((1234) IN (SELECT * FROM t1)) DO
+SELECT 1;
+END WHILE;
+END;
+$$
+BEGIN NOT ATOMIC
+WHILE (EXISTS (SELECT * FROM t1 WHERE a=1234)) DO
+SELECT 1;
+END WHILE;
+END;
+$$
+BEGIN NOT ATOMIC
+REPEAT
+SELECT 1;
+UNTIL (1 IN (SELECT * FROM t1))
+END REPEAT;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+REPEAT
+SELECT 1;
+UNTIL EXISTS (SELECT * FROM t1 WHERE a=1)
+END REPEAT;
+END;
+$$
+1
+1
+BEGIN NOT ATOMIC
+FOR i IN 0..(1 IN (SELECT * FROM t1))
+DO
+SELECT i;
+END FOR;
+END;
+$$
+i
+0
+i
+1
+BEGIN NOT ATOMIC
+FOR i IN 0..EXISTS (SELECT * FROM t1 WHERE a=1)
+DO
+SELECT i;
+END FOR;
+END;
+$$
+i
+0
+i
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+BEGIN NOT ATOMIC
+DECLARE a INT DEFAULT ((10) IN (SELECT * FROM t1));
+SELECT a;
+END;
+$$
+a
+1
+BEGIN NOT ATOMIC
+DECLARE a INT DEFAULT EXISTS (SELECT * FROM t1);
+SELECT a;
+END;
+$$
+a
+1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+RETURN ((1) IN (SELECT * FROM t1));
+END;
+$$
+CREATE FUNCTION f2() RETURNS INT
+BEGIN
+RETURN EXISTS (SELECT * FROM t1 WHERE a=1);
+END;
+$$
+SELECT f1();
+f1()
+1
+SELECT f2();
+f2()
+1
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(1 IN (SELECT * FROM t1));
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+va
+2
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(EXISTS (SELECT * FROM t1));
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+va
+2
+DROP TABLE t1;
+#
+# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+#
+BEGIN NOT ATOMIC
+CASE unknown_identifier WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+BEGIN NOT ATOMIC
+CASE unknown_identifier.a WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+BEGIN NOT ATOMIC
+CASE unknown_identifier.a.b WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+CASE unknown_identifier.a.b.c WHEN 1 THEN SELECT 1;
+ELSE SELECT NULL;
+END CASE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+IF unknown_identifier THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+BEGIN NOT ATOMIC
+IF unknown_identifier.a THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+BEGIN NOT ATOMIC
+IF unknown_identifier.a.b THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+IF unknown_identifier.a.b.c THEN SELECT 1;
+ELSE SELECT NULL;
+END IF;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+WHILE unknown_identifier DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+BEGIN NOT ATOMIC
+WHILE unknown_identifier.a DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+BEGIN NOT ATOMIC
+WHILE unknown_identifier.a.b DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+WHILE unknown_identifier.a.b.c DO
+SELECT 1;
+END WHILE;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+BEGIN NOT ATOMIC
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+BEGIN NOT ATOMIC
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a.b;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+REPEAT
+SELECT 1;
+UNTIL unknown_identifier.a.b.c;
+END REPEAT;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+BEGIN NOT ATOMIC
+FOR i IN 0..unknown_identifier
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier
+BEGIN NOT ATOMIC
+FOR i IN 0..unknown_identifier.field1
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier.field1
+BEGIN NOT ATOMIC
+FOR i IN 0..unknown_identifier.field1.field2
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: field1.field2
+BEGIN NOT ATOMIC
+FOR i IN unknown_identifier..10
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier
+BEGIN NOT ATOMIC
+FOR i IN unknown_identifier.field1..10
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: unknown_identifier.field1
+BEGIN NOT ATOMIC
+FOR i IN unknown_identifier.field1.field2..10
+DO
+SELECT i;
+END FOR;
+END;
+$$
+ERROR 42000: Undeclared variable: field1.field2
+BEGIN NOT ATOMIC
+DECLARE a INT DEFAULT unknown_identifier;
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE a INT DEFAULT unknown_identifier.a;
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'field list'
+BEGIN NOT ATOMIC
+DECLARE a INT DEFAULT unknown_identifier.a.b;
+SELECT a;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier;
+ERROR 42S22: Unknown column 'unknown_identifier' in 'field list'
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a;
+ERROR 42S22: Unknown column 'a' in 'field list'
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a.b;
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE FUNCTION f1() RETURNS INT RETURN unknown_identifier.a.b.c;
+ERROR 42S22: Unknown column 'b' in 'field list'
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(unknown_identifier);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'unknown_identifier' in 'ORDER clause'
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(unknown_identifier.a);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'a' in 'ORDER clause'
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(unknown_identifier.a.b);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'ORDER clause'
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR(amin INT) FOR SELECT a FROM t1 WHERE a>amin ORDER BY a;
+OPEN cur(unknown_identifier.a.b.c);
+FETCH cur INTO va;
+SELECT va;
+CLOSE cur;
+END;
+$$
+ERROR 42S22: Unknown column 'b' in 'ORDER clause'
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-expr.test b/mysql-test/suite/compat/oracle/t/sp-expr.test
new file mode 100644
index 0000000..2e589f7
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-expr.test
@@ -0,0 +1,820 @@
+# Testing expressions of different kinds in various parts of SP syntax
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # Start of 10.4 tests
+--echo #
+
+#
+# Subselects in SP control structures
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DELIMITER $$;
+
+BEGIN
+ CASE ((1) IN (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+BEGIN
+ CASE (EXISTS (SELECT a FROM t1)) WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+BEGIN
+ IF ((1) IN (SELECT a FROM t1)) THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+BEGIN
+ IF (EXISTS (SELECT a FROM t1)) THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+BEGIN
+ WHILE ((1234) IN (SELECT * FROM t1)) LOOP
+ SELECT 1;
+ END LOOP;
+END;
+$$
+BEGIN
+ WHILE (EXISTS (SELECT * FROM t1 WHERE a=1234)) LOOP
+ SELECT 1;
+ END LOOP;
+END;
+$$
+
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL (1 IN (SELECT * FROM t1))
+ END REPEAT;
+END;
+$$
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL EXISTS (SELECT * FROM t1 WHERE a=1)
+ END REPEAT;
+END;
+$$
+
+BEGIN
+ FOR i IN 0..(1 IN (SELECT * FROM t1))
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+BEGIN
+ FOR i IN 0..EXISTS (SELECT * FROM t1 WHERE a=1)
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+#
+# Subselects as SP variable default values
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+DECLARE
+ a INT DEFAULT ((10) IN (SELECT * FROM t1));
+BEGIN
+ SELECT a;
+END;
+$$
+DECLARE
+ a INT DEFAULT EXISTS (SELECT * FROM t1);
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+#
+# Subselects SP function return values
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN INT AS
+BEGIN
+ RETURN ((1) IN (SELECT * FROM t1));
+END;
+$$
+CREATE FUNCTION f2() RETURN INT AS
+BEGIN
+ RETURN EXISTS (SELECT * FROM t1 WHERE a=1);
+END;
+$$
+DELIMITER ;$$
+SELECT f1();
+SELECT f2();
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP TABLE t1;
+
+
+#
+# Subselects in CURSOR parameters
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DELIMITER $$;
+DECLARE
+ va INT;
+ CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+ OPEN cur(1 IN (SELECT * FROM t1));
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+DECLARE
+ va INT;
+ CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+ OPEN cur(EXISTS (SELECT * FROM t1));
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+--echo #
+
+#
+# Unknown identifiers in CASE SP control
+#
+
+DELIMITER $$;
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ CASE unknown_identifier WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ CASE unknown_identifier.a WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ CASE unknown_identifier.a.b WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ CASE unknown_identifier.a.b.c WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+
+#
+# Unknown identifiers in IF
+#
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ IF unknown_identifier THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ IF unknown_identifier.a THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ IF unknown_identifier.a.b THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ IF unknown_identifier.a.b.c THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+
+#
+# Unknown identifiers in WHILE
+#
+
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ WHILE unknown_identifier LOOP
+ SELECT 1;
+ END LOOP;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ WHILE unknown_identifier.a LOOP
+ SELECT 1;
+ END LOOP;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ WHILE unknown_identifier.a.b LOOP
+ SELECT 1;
+ END LOOP;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ WHILE unknown_identifier.a.b.c LOOP
+ SELECT 1;
+ END LOOP;
+END;
+$$
+
+
+
+#
+# Unknown identifiers in REPEAT
+#
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL unknown_identifier;
+ END REPEAT;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL unknown_identifier.a;
+ END REPEAT;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL unknown_identifier.a.b;
+ END REPEAT;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL unknown_identifier.a.b.c;
+ END REPEAT;
+END;
+$$
+
+
+#
+# Unknown identifiers in FOR
+#
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN 0..unknown_identifier
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN 0..unknown_identifier.field1
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN 0..unknown_identifier.field1.field2
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN unknown_identifier..10
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN unknown_identifier.field1..10
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+--error ER_SP_UNDECLARED_VAR
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN unknown_identifier.field1.field2..10
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+DELIMITER ;$$
+
+
+#
+# Unknown identifiers as SP variable default values
+#
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+ a INT DEFAULT unknown_identifier;
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+ a INT DEFAULT unknown_identifier.a;
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+ a INT DEFAULT unknown_identifier.a.b;
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+#
+# Unknown identifiers as SP function return values
+#
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN unknown_identifier; END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN unknown_identifier.a; END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN unknown_identifier.a.b; END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN unknown_identifier.a.b.c; END;
+$$
+DELIMITER ;$$
+
+
+#
+# Unknown identifiers in CURSOR parameters
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DELIMITER $$;
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+ va INT;
+ CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+ OPEN cur(unknown_identifier);
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+ va INT;
+ CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+ OPEN cur(unknown_identifier.a);
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+ va INT;
+ CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+ OPEN cur(unknown_identifier.a.b);
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+ va INT;
+ CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+ OPEN cur(unknown_identifier.a.b.c);
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+--echo #
+--echo # (testing aggregate functions)
+
+#
+# Aggregate functions in CASE SP control
+#
+
+DELIMITER $$;
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1() AS
+BEGIN
+ CASE SUM(1) WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+
+#
+# Aggregate functions in IF
+#
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1() AS
+BEGIN
+ IF SUM(1) THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+
+#
+# Aggregate functions in WHILE
+#
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1() AS
+BEGIN
+ WHILE SUM(1) LOOP
+ SELECT 1;
+ END LOOP;
+END;
+$$
+
+
+
+#
+# Aggregate functions in REPEAT
+#
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1() AS
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL SUM(1);
+ END REPEAT;
+END;
+$$
+
+#
+# Aggregate functions in FOR
+#
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN 0..SUM(1)
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN SUM(1)..10
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+DELIMITER ;$$
+
+
+#
+# Aggregate functions as SP variable default values
+#
+
+DELIMITER $$;
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1() AS
+ a INT DEFAULT SUM(1);
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+#
+# Aggregate functions as SP function return values
+#
+
+DELIMITER $$;
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN SUM(1); END;
+$$
+DELIMITER ;$$
+
+
+#
+# Aggregate functions in CURSOR parameters
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DELIMITER $$;
+
+--error ER_INVALID_GROUP_FUNC_USE
+CREATE PROCEDURE p1() AS
+ va INT;
+ CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+ OPEN cur(SUM(1));
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+DELIMITER ;$$
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+--echo #
+--echo # (testing window functions)
+
+#
+# Window functions in CASE SP control
+#
+
+DELIMITER $$;
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1() AS
+BEGIN
+ CASE ROW_NUMBER() OVER() WHEN 1 THEN SELECT 1;
+ ELSE SELECT NULL;
+ END CASE;
+END;
+$$
+
+
+#
+# Window functions in IF
+#
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1() AS
+BEGIN
+ IF ROW_NUMBER() OVER() THEN SELECT 1;
+ ELSE SELECT NULL;
+ END IF;
+END;
+$$
+
+
+#
+# Window functions in WHILE
+#
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1() AS
+BEGIN
+ WHILE ROW_NUMBER() OVER() LOOP
+ SELECT 1;
+ END LOOP;
+END;
+$$
+
+
+
+#
+# Window functions in REPEAT
+#
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1() AS
+BEGIN
+ REPEAT
+ SELECT 1;
+ UNTIL ROW_NUMBER() OVER();
+ END REPEAT;
+END;
+$$
+
+#
+# Window functions in FOR
+#
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN 0..ROW_NUMBER() OVER()
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1() AS
+BEGIN
+ FOR i IN ROW_NUMBER() OVER()..10
+ LOOP
+ SELECT i;
+ END LOOP;
+END;
+$$
+
+DELIMITER ;$$
+
+
+#
+# Window functions as SP variable default values
+#
+
+DELIMITER $$;
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1() AS
+ a INT DEFAULT ROW_NUMBER() OVER();
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+
+
+#
+# Window functions as SP function return values
+#
+
+DELIMITER $$;
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE FUNCTION f1() RETURN INT AS BEGIN RETURN ROW_NUMBER() OVER(); END;
+$$
+DELIMITER ;$$
+
+
+#
+# Window functions in CURSOR parameters
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DELIMITER $$;
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CREATE PROCEDURE p1() AS
+ va INT;
+ CURSOR cur(amin INT) IS SELECT a FROM t1 WHERE a>amin ORDER BY a;
+BEGIN
+ OPEN cur(ROW_NUMBER() OVER());
+ FETCH cur INTO va;
+ SELECT va;
+ CLOSE cur;
+END;
+$$
+
+DELIMITER ;$$
+DROP TABLE t1;
diff --git a/mysql-test/suite/compat/oracle/t/sp.test b/mysql-test/suite/compat/oracle/t/sp.test
index b88271a..de2a4a5 100644
--- a/mysql-test/suite/compat/oracle/t/sp.test
+++ b/mysql-test/suite/compat/oracle/t/sp.test
@@ -1092,6 +1092,7 @@ DROP FUNCTION f1;
--echo #
DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
CREATE PROCEDURE p1
AS
BEGIN
@@ -1100,12 +1101,10 @@ BEGIN
END LOOP;
END$$
DELIMITER ;$$
---error ER_BAD_FIELD_ERROR
-CALL p1;
-DROP PROCEDURE p1;
DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
CREATE PROCEDURE p1
AS
BEGIN
@@ -1115,12 +1114,10 @@ BEGIN
END LOOP;
END$$
DELIMITER ;$$
---error ER_BAD_FIELD_ERROR
-CALL p1;
-DROP PROCEDURE p1;
DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
CREATE PROCEDURE p1
AS
BEGIN
@@ -1129,12 +1126,10 @@ BEGIN
END LOOP;
END$$
DELIMITER ;$$
---error ER_BAD_FIELD_ERROR
-CALL p1;
-DROP PROCEDURE p1;
DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
CREATE PROCEDURE p1
AS
BEGIN
@@ -1144,9 +1139,6 @@ BEGIN
END LOOP;
END$$
DELIMITER ;$$
---error ER_BAD_FIELD_ERROR
-CALL p1;
-DROP PROCEDURE p1;
--echo #
--echo # MDEV-10583 sql_mode=ORACLE: SQL%ROWCOUNT
diff --git a/mysql-test/suite/compat/oracle/t/statement-expr.test b/mysql-test/suite/compat/oracle/t/statement-expr.test
new file mode 100644
index 0000000..3970caf
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/statement-expr.test
@@ -0,0 +1,304 @@
+# Testing expressions of different kinds in various non-SELECT statements
+
+SET sql_mode=ORACLE;
+
+#
+# Subselects in non-SELECT statements
+#
+
+CREATE TABLE t1 (id INT, id1 INT);
+INSERT INTO t1 VALUES (1,7);
+INSERT INTO t1 VALUES (1,8);
+SELECT ROW(1,7) IN (SELECT id, id1 FROM t1 WHERE id1= 8);
+EXECUTE IMMEDIATE 'SELECT ROW(1, 7) IN (SELECT id, id1 FROM t1 WHERE id1= 8)';
+DROP TABLE t1;
+
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING (1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING (SELECT * FROM t1);
+
+
+CREATE TABLE t1 (id INT);
+INSERT INTO t1 VALUES (10);
+DELIMITER $$;
+CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
+$$
+DELIMITER ;$$
+CALL p1((1) IN (SELECT * FROM t1));
+CALL p1(EXISTS (SELECT * FROM t1));
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=(1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=EXISTS (SELECT * FROM t1);
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=(1 IN (SELECT * FROM t1));
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=EXISTS (SELECT * FROM t1);
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+DELIMITER ;$$
+
+
+--error ER_PARSE_ERROR
+PREPARE stmt FROM (1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+PREPARE stmt FROM EXISTS (SELECT * FROM t1);
+
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE (1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+EXECUTE IMMEDIATE EXISTS (SELECT * FROM t1);
+
+--error ER_PARSE_ERROR
+GET DIAGNOSTICS CONDITION (1 IN (SELECT * FROM t1)) @errno=MYSQL_ERRNO;
+--error ER_PARSE_ERROR
+GET DIAGNOSTICS CONDITION EXISTS (SELECT * FROM t1) @errno=MYSQL_ERRNO;
+
+--error ER_PARSE_ERROR
+PURGE BINARY LOGS BEFORE (1 IN (SELECT * FROM t1));
+--error ER_PARSE_ERROR
+PURGE BINARY LOGS BEFORE EXISTS (SELECT * FROM t1);
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+DO 1 IN (SELECT * FROM t1);
+DO EXISTS (SELECT * FROM t1);
+DROP TABLE t1;
+
+
+--echo #
+--echo # MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
+--echo #
+
+# TODO: wrap into CREATE
+
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE 'SELECT ?' USING unknown_identifier.a.b.c;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
+$$
+DELIMITER ;$$
+--error ER_BAD_FIELD_ERROR
+CALL p1(unknown_identifier);
+--error ER_BAD_FIELD_ERROR
+CALL p1(unknown_identifier.a);
+--error ER_BAD_FIELD_ERROR
+CALL p1(unknown_identifier.a.b);
+--error ER_BAD_FIELD_ERROR
+CALL p1(unknown_identifier.a.b.c);
+DROP PROCEDURE p1;
+
+
+--error ER_BAD_FIELD_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=unknown_identifier.a.b.c;
+
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=unknown_identifier;
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+--error ER_BAD_FIELD_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a;
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+--error ER_BAD_FIELD_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a.b;
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+--error ER_BAD_FIELD_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=unknown_identifier.a.b.c;
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+DELIMITER ;$$
+
+
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+PREPARE stmt FROM unknown_identifier.a.b.c;
+
+
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+EXECUTE IMMEDIATE unknown_identifier.a.b.c;
+
+
+--error ER_BAD_FIELD_ERROR
+GET DIAGNOSTICS CONDITION unknown_identifier @errno=MYSQL_ERRNO;
+--error ER_BAD_FIELD_ERROR
+GET DIAGNOSTICS CONDITION unknown_identifier.a @errno=MYSQL_ERRNO;
+--error ER_BAD_FIELD_ERROR
+GET DIAGNOSTICS CONDITION unknown_identifier.a.b @errno=MYSQL_ERRNO;
+--error ER_BAD_FIELD_ERROR
+GET DIAGNOSTICS CONDITION unknown_identifier.a.b.c @errno=MYSQL_ERRNO;
+
+
+--error ER_BAD_FIELD_ERROR
+PURGE BINARY LOGS BEFORE unknown_identifier;
+--error ER_BAD_FIELD_ERROR
+PURGE BINARY LOGS BEFORE unknown_identifier.a;
+--error ER_BAD_FIELD_ERROR
+PURGE BINARY LOGS BEFORE unknown_identifier.a.b;
+--error ER_BAD_FIELD_ERROR
+PURGE BINARY LOGS BEFORE unknown_identifier.a.b.c;
+
+
+--echo #
+--echo # MDEV-15870 Using aggregate and window function in unexpected places can crash the server
+--echo #
+
+--echo # (aggreate functions)
+
+--error ER_INVALID_GROUP_FUNC_USE
+EXECUTE IMMEDIATE 'SELECT ?' USING SUM(1);
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
+$$
+DELIMITER ;$$
+--error ER_INVALID_GROUP_FUNC_USE
+CALL p1(SUM(1));
+DROP PROCEDURE p1;
+
+
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=SUM(1);
+
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=SUM(1);
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+DELIMITER ;$$
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+PREPARE stmt FROM SUM(1);
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+EXECUTE IMMEDIATE SUM(1);
+
+
+--error ER_PARSE_ERROR
+GET DIAGNOSTICS CONDITION SUM(1) @errno=MYSQL_ERRNO;
+
+
+--error ER_INVALID_GROUP_FUNC_USE
+PURGE BINARY LOGS BEFORE SUM(1);
+
+
+
+--echo #
+--echo # MDEV-15870 Using aggregate and window function in unexpected places can crash the server
+--echo #
+
+--echo # (window functions)
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+EXECUTE IMMEDIATE 'SELECT ?' USING ROW_NUMBER() OVER ();
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END;
+$$
+DELIMITER ;$$
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+CALL p1(ROW_NUMBER() OVER ());
+DROP PROCEDURE p1;
+
+
+--error ER_PARSE_ERROR
+SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO=ROW_NUMBER() OVER ();
+
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+BEGIN NOT ATOMIC
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ RESIGNAL SET MYSQL_ERRNO=ROW_NUMBER() OVER ();
+ SIGNAL SQLSTATE '01000';
+END;
+$$
+DELIMITER ;$$
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+PREPARE stmt FROM ROW_NUMBER() OVER ();
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+EXECUTE IMMEDIATE ROW_NUMBER() OVER ();
+
+
+--error ER_PARSE_ERROR
+GET DIAGNOSTICS CONDITION ROW_NUMBER() OVER () @errno=MYSQL_ERRNO;
+
+
+--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION
+PURGE BINARY LOGS BEFORE ROW_NUMBER() OVER ();
+
+
+DELIMITER $$;
+--error ER_BAD_FIELD_ERROR
+CREATE PROCEDURE p1() AS
+BEGIN
+ DO unknown_identifier;
+END;
+$$
+DELIMITER ;$$
diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result
index e5e009a..0fe7082 100644
--- a/mysql-test/suite/funcs_1/r/storedproc.result
+++ b/mysql-test/suite/funcs_1/r/storedproc.result
@@ -15723,6 +15723,7 @@ Testcase 4.3.7:
DROP PROCEDURE IF EXISTS sp7;
CREATE PROCEDURE sp7()
BEGIN
+DECLARE count INT DEFAULT 100;
label1: loop
set @dummystring = 'temp value';
if count > 10 then leave label1;
@@ -15732,7 +15733,7 @@ END label1 loop;
END//
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 'iterate;
END label1 loop;
-END' at line 7
+END' at line 8
DROP PROCEDURE IF EXISTS sp7;
CREATE PROCEDURE sp7()
BEGIN
diff --git a/mysql-test/suite/funcs_1/t/storedproc.test b/mysql-test/suite/funcs_1/t/storedproc.test
index 98385d4..3178641 100644
--- a/mysql-test/suite/funcs_1/t/storedproc.test
+++ b/mysql-test/suite/funcs_1/t/storedproc.test
@@ -18861,6 +18861,7 @@ delimiter //;
--error ER_PARSE_ERROR
CREATE PROCEDURE sp7()
BEGIN
+ DECLARE count INT DEFAULT 100;
label1: loop
set @dummystring = 'temp value';
if count > 10 then leave label1;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 901dfa0..b3fbdfd 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -3487,12 +3487,11 @@ Create_sp_func::create_with_db(THD *thd, LEX_CSTRING *db, LEX_CSTRING *name,
sph->add_used_routine(lex, thd, qname);
if (pkgname.m_name.length)
sp_handler_package_body.add_used_routine(lex, thd, &pkgname);
+ Name_resolution_context *ctx= lex->current_context_or_default();
if (arg_count > 0)
- func= new (thd->mem_root) Item_func_sp(thd, lex->current_context(),
- qname, sph, *item_list);
+ func= new (thd->mem_root) Item_func_sp(thd, ctx, qname, sph, *item_list);
else
- func= new (thd->mem_root) Item_func_sp(thd, lex->current_context(),
- qname, sph);
+ func= new (thd->mem_root) Item_func_sp(thd, ctx, qname, sph);
lex->safe_to_cache_query= 0;
return func;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 5a447ce..9ca44c6 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -115,7 +115,8 @@ void Item_subselect::init(st_select_lex *select_lex,
do not take into account expression inside aggregate functions because
they can access original table fields
*/
- parsing_place= (outer_select->in_sum_expr ?
+ // QQ: shouldn't we use relink_hack() instead ?
+ parsing_place= (!outer_select || outer_select->in_sum_expr ?
NO_MATTER :
outer_select->parsing_place);
if (unit->is_unit_op() && unit->first_select()->next_select())
@@ -239,6 +240,9 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
{
SELECT_LEX *upper= unit->outer_select();
+ // QQ: shouldn't we use relink_hack() instead?
+ if (!upper)
+ upper= &thd_param->lex->builtin_select;
if (upper->parsing_place == IN_HAVING)
upper->subquery_in_having= 1;
/* The subquery is an expression cache candidate */
@@ -1395,12 +1399,46 @@ bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
}
+/*
+ "IN" and "EXISTS" subselect can appear in two statement types:
+
+ 1. Statements that can have table columns, such as SELECT, DELETE, UPDATE
+ 2. Statements that cannot have table columns, e.g:
+ RETURN ((1) IN (SELECT * FROM t1))
+ IF ((1) IN (SELECT * FROM t1))
+
+ Statements of the first type call master_select_push() in the beginning.
+ In such case everything is properly linked.
+
+ Statements of the second type do not call mastr_select_push().
+ Here we catch the second case and relink thd->lex->builtin_select and
+ select_lex to properly point to each other.
+
+ QQ: Shouldn't subselects of other type also call relink_hack()?
+ QQ: Can we do it at constructor time instead?
+*/
+static void relink_hack(THD *thd, st_select_lex *select_lex)
+{
+ if (!thd->lex->select_stack_top) // Statements of the second type
+ {
+ if (!select_lex->get_master()->get_master())
+ ((st_select_lex *) select_lex->get_master())->
+ set_master(&thd->lex->builtin_select);
+ if (!thd->lex->builtin_select.get_slave())
+ thd->lex->builtin_select.set_slave(select_lex->get_master());
+ }
+}
+
+
Item_exists_subselect::Item_exists_subselect(THD *thd,
st_select_lex *select_lex):
Item_subselect(thd), upper_not(NULL), abort_on_null(0),
emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0)
{
DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
+
+ relink_hack(thd, select_lex);
+
init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
max_columns= UINT_MAX;
null_value= FALSE; //can't be NULL
@@ -1443,6 +1481,9 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
{
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy));
+
+ relink_hack(thd, select_lex);
+
left_expr_orig= left_expr= left_exp;
/* prepare to possible disassembling the item in convert_subq_to_sj() */
if (left_exp->type() == Item::ROW_ITEM)
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 2ec7e3c..a880050 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -72,6 +72,7 @@ size_t Item_sum::ram_limitation(THD *thd)
bool Item_sum::init_sum_func_check(THD *thd)
{
SELECT_LEX *curr_sel= thd->lex->current_select;
+ DBUG_ASSERT(curr_sel);
if (!curr_sel->name_visibility_map)
{
for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select())
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index a723980..ef6524c 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -518,6 +518,7 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs,
if (optimizer_flag(thd, OPTIMIZER_SWITCH_MATERIALIZATION) && // 0
!child_select->is_part_of_union() && // 1
parent_unit->first_select()->leaf_tables.elements && // 2
+ child_select->outer_select() &&
child_select->outer_select()->leaf_tables.elements && // 2A
subquery_types_allow_materialization(in_subs) &&
(in_subs->is_top_level_item() || //3
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 0d39a4d..15fc876 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -6006,9 +6006,17 @@ bool LEX::sp_for_loop_implicit_cursor_statement(THD *thd,
bounds->m_index->sp_lex_in_use= true;
sphead->reset_lex(thd, bounds->m_index);
DBUG_ASSERT(thd->lex != this);
- if (!(item= new (thd->mem_root) Item_field(thd,
- thd->lex->current_context(),
- NullS, NullS, &name)))
+ /*
+ We pass NULL as Name_resolution_context here.
+ It's OK, fix_fields() will not be called for this Item_field created.
+ Item_field is only needed for LEX::sp_for_loop_cursor_declarations()
+ and is used to transfer the loop index variable name, "rec" in this example:
+ FOR rec IN (SELECT * FROM t1)
+ DO
+ SELECT rec.a, rec.b;
+ END FOR;
+ */
+ if (!(item= new (thd->mem_root) Item_field(thd, NULL, NullS, NullS, &name)))
return true;
bounds->m_index->set_item_and_free_list(item, NULL);
if (thd->lex->sphead->restore_lex(thd))
@@ -6112,6 +6120,19 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
const LEX_CSTRING *index,
const Lex_for_loop_bounds_st &bounds)
{
+ Item *item;
+ if ((item= bounds.m_index->get_item())->type() == Item::FIELD_ITEM)
+ {
+ // We're here is the lower bound is unknown identifier
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name());
+ return true;
+ }
+ if ((item= bounds.m_upper_bound->get_item())->type() == Item::FIELD_ITEM)
+ {
+ // We're here is the upper bound is unknown identifier
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), item->full_name());
+ return true;
+ }
if (!(loop->m_index=
bounds.m_index->sp_add_for_loop_variable(thd, index,
bounds.m_index->get_item())))
@@ -6989,6 +7010,38 @@ bool LEX::add_resignal_statement(THD *thd, const sp_condition_value *v)
}
+/*
+ Make an Item when an identifier is found in the FOR loop bounds:
+ FOR rec IN cursor
+ FOR var IN var1 .. xxx
+ FOR var IN row1.field1 .. xxx
+ When we parse the first expression after the "IN" keyword,
+ we don't know yet if it's a cursor name, or a scalar SP variable name,
+ or a field of a ROW SP variable. Here we create Item_field to remember
+ the fully qualified name. Later sp_for_loop_cursor_declarations()
+ detects how to treat this name properly.
+*/
+Item *LEX::create_item_for_loop_bound(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ const LEX_CSTRING *c)
+{
+ /*
+ Pass NULL as the name resolution context.
+ This is OK, fix_fields() won't be called for this Item_field.
+ */
+ return new (thd->mem_root) Item_field(thd, NULL, a->str, b->str, c);
+}
+
+
+bool LEX::check_expr_allows_fields_or_error(THD *thd, const char *name) const
+{
+ if (select_stack_top > 0)
+ return false; // OK, fields are allowed
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), name, thd->where);
+ return true; // Error, fields are not allowed
+}
+
Item *LEX::create_item_ident_nospvar(THD *thd,
const LEX_CSTRING *a,
const LEX_CSTRING *b)
@@ -7011,12 +7064,11 @@ Item *LEX::create_item_ident_nospvar(THD *thd,
my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), a->str, thd->where);
return NULL;
}
- if ((current_select->parsing_place != IN_HAVING) ||
- (current_select->get_in_sum_expr() > 0))
- return new (thd->mem_root) Item_field(thd, current_context(),
- NullS, a->str, b);
- return new (thd->mem_root) Item_ref(thd, current_context(),
- NullS, a->str, b);
+
+ if (current_select->parsing_place == FOR_LOOP_BOUND)
+ return create_item_for_loop_bound(thd, &null_clex_str, a, b);
+
+ return create_item_ident_field(thd, NullS, a->str, b);
}
@@ -7217,12 +7269,11 @@ Item *LEX::create_item_ident(THD *thd,
my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), b->str, thd->where);
return NULL;
}
- if (current_select->parsing_place != IN_HAVING ||
- current_select->get_in_sum_expr() > 0)
- return new (thd->mem_root) Item_field(thd, current_context(),
- schema, b->str, c);
- return new (thd->mem_root) Item_ref(thd, current_context(),
- schema, b->str, c);
+
+ if (current_select->parsing_place == FOR_LOOP_BOUND)
+ return create_item_for_loop_bound(thd, &null_clex_str, b, c);
+
+ return create_item_ident_field(thd, schema, b->str, c);
}
@@ -7298,15 +7349,19 @@ bool LEX::set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val)
}
-Item *LEX::create_item_ident_nosp(THD *thd, LEX_CSTRING *name)
+Item *LEX::create_item_ident_field(THD *thd, const char *db,
+ const char *table, const LEX_CSTRING *name)
{
+ if (check_expr_allows_fields_or_error(thd, name->str))
+ return NULL;
+
if (current_select->parsing_place != IN_HAVING ||
current_select->get_in_sum_expr() > 0)
return new (thd->mem_root) Item_field(thd, current_context(),
- NullS, NullS, name);
+ db, table, name);
return new (thd->mem_root) Item_ref(thd, current_context(),
- NullS, NullS, name);
+ db, table, name);
}
@@ -7352,6 +7407,11 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
if (!my_strcasecmp(system_charset_info, name->str, "SQLERRM"))
return new (thd->mem_root) Item_func_sqlerrm(thd);
}
+
+ if (current_select->parsing_place == FOR_LOOP_BOUND)
+ return create_item_for_loop_bound(thd, &null_clex_str, &null_clex_str,
+ name);
+
return create_item_ident_nosp(thd, name);
}
@@ -8538,3 +8598,29 @@ bool LEX::insert_select_hack(SELECT_LEX *sel)
DBUG_RETURN(FALSE);
}
+
+
+/*
+ Create an Item_singlerow_subselect for a query expression.
+*/
+Item *LEX::create_item_query_expression(THD *thd,
+ const char *tok_start,
+ st_select_lex_unit *unit)
+{
+ if (!expr_allows_subselect || sql_command == SQLCOM_PURGE)
+ {
+ thd->parse_error(ER_SYNTAX_ERROR, tok_start);
+ return NULL;
+ }
+
+ // Add the subtree of subquery to the current SELECT_LEX
+ SELECT_LEX *curr_sel= select_stack_head();
+ DBUG_ASSERT(current_select == curr_sel);
+ if (!curr_sel)
+ curr_sel= &builtin_select;
+ curr_sel->register_unit(unit, &curr_sel->context);
+ curr_sel->add_statistics(unit);
+
+ return new (thd->mem_root)
+ Item_singlerow_subselect(thd, unit->first_select());
+}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 4049ac8..ff348a8 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -606,6 +606,7 @@ class st_select_lex_node {
}
inline st_select_lex_node* get_master() { return master; }
+ inline st_select_lex_node* get_slave() { return slave; }
void include_down(st_select_lex_node *upper);
void add_slave(st_select_lex_node *slave_arg);
void include_neighbour(st_select_lex_node *before);
@@ -1115,6 +1116,10 @@ class st_select_lex: public st_select_lex_node
{
master= (st_select_lex_node *)master_unit;
}
+ void set_master(st_select_lex *master_arg)
+ {
+ master= master_arg;
+ }
st_select_lex_unit* first_inner_unit()
{
return (st_select_lex_unit*) slave;
@@ -2850,6 +2855,12 @@ struct LEX: public Query_tables_list
bool sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop);
bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop);
+ /*
+ Check if Item_field and Item_ref are allowed in the current statement.
+ @retval false OK (fields are allowed)
+ @retval true ERROR (fields are not allowed). Error is raised.
+ */
+ bool check_expr_allows_fields_or_error(THD *thd, const char *name) const;
public:
void parse_error(uint err_number= ER_SYNTAX_ERROR);
inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;}
@@ -3321,12 +3332,25 @@ struct LEX: public Query_tables_list
DBUG_RETURN(select_lex);
}
+ SELECT_LEX *current_select_or_default()
+ {
+ return current_select ? current_select : &builtin_select;
+ }
+
bool copy_db_to(LEX_CSTRING *to);
Name_resolution_context *current_context()
{
return context_stack.head();
}
+ Name_resolution_context *current_context_or_default()
+ {
+ Name_resolution_context *ctx= current_context();
+ if (!ctx)
+ return &builtin_select.context;
+ return ctx;
+ }
+
/*
Restore the LEX and THD in case of a parse error.
*/
@@ -3493,7 +3517,12 @@ struct LEX: public Query_tables_list
Item_splocal *create_item_for_sp_var(LEX_CSTRING *name, sp_variable *spvar,
const char *start, const char *end);
- Item *create_item_ident_nosp(THD *thd, LEX_CSTRING *name);
+ Item *create_item_ident_field(THD *thd, const char *db, const char *table,
+ const LEX_CSTRING *name);
+ Item *create_item_ident_nosp(THD *thd, LEX_CSTRING *name)
+ {
+ return create_item_ident_field(thd, NullS, NullS, name);
+ }
Item *create_item_ident_sp(THD *thd, LEX_CSTRING *name,
const char *start, const char *end);
Item *create_item_ident(THD *thd, LEX_CSTRING *name,
@@ -3623,6 +3652,10 @@ struct LEX: public Query_tables_list
const char *start,
const char *end);
+ Item *create_item_query_expression(THD *thd,
+ const char *tok_start,
+ st_select_lex_unit *unit);
+
Item *make_item_func_replace(THD *thd, Item *org, Item *find, Item *replace);
Item *make_item_func_substr(THD *thd, Item *a, Item *b, Item *c);
Item *make_item_func_substr(THD *thd, Item *a, Item *b);
@@ -3800,6 +3833,17 @@ struct LEX: public Query_tables_list
sp_for_loop_cursor_finalize(thd, loop) :
sp_for_loop_intrange_finalize(thd, loop);
}
+
+ /*
+ Make an Item when an identifier is found in the FOR loop bounds:
+ FOR rec IN cursor
+ FOR rec IN var1 .. var2
+ FOR rec IN row1.field1 .. xxx
+ */
+ Item *create_item_for_loop_bound(THD *thd,
+ const LEX_CSTRING *a,
+ const LEX_CSTRING *b,
+ const LEX_CSTRING *c);
/* End of FOR LOOP methods */
bool add_signal_statement(THD *thd, const class sp_condition_value *value);
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 4de8b8c..9c876c0 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -361,6 +361,7 @@ enum enum_parsing_place
IN_PART_FUNC,
BEFORE_OPT_LIST,
AFTER_LIST,
+ FOR_LOOP_BOUND,
PARSING_PLACE_SIZE /* always should be the last */
};
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d4122fe..d6758a5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2222,12 +2222,7 @@ deallocate_or_drop:
;
prepare:
- PREPARE_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- ident FROM prepare_src
+ PREPARE_SYM ident FROM prepare_src
{
LEX *lex= thd->lex;
if (lex->table_or_sp_used())
@@ -2236,8 +2231,7 @@ prepare:
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
lex->sql_command= SQLCOM_PREPARE;
- lex->prepared_stmt_name= $3;
- Lex->pop_select(); //main select
+ lex->prepared_stmt_name= $2;
}
;
@@ -2256,21 +2250,13 @@ execute:
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_EXECUTE;
lex->prepared_stmt_name= $2;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
execute_using
{
- Lex->pop_select(); //main select
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
- | EXECUTE_SYM IMMEDIATE_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- prepare_src
+ | EXECUTE_SYM IMMEDIATE_SYM prepare_src
{
if (Lex->table_or_sp_used())
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
@@ -2279,7 +2265,6 @@ execute:
}
execute_using
{
- Lex->pop_select(); //main select
if (Lex->check_main_unit_semantics())
MYSQL_YYABORT;
}
@@ -2812,7 +2797,6 @@ create:
if (Lex->main_select_push())
MYSQL_YYABORT;
Lex->create_info.set($1);
-
}
sf_tail_aggregate
{
@@ -3306,13 +3290,8 @@ call:
{
if (Lex->call_statement_start(thd, $2))
MYSQL_YYABORT;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- opt_sp_cparam_list
- {
- Lex->pop_select(); //main select
}
+ opt_sp_cparam_list {}
;
/* CALL parameters */
@@ -3729,16 +3708,10 @@ sp_hcond:
;
signal_stmt:
- SIGNAL_SYM
- {
- if (Lex->main_select_push())
- YYABORT;
- }
- signal_value opt_set_signal_information
+ SIGNAL_SYM signal_value opt_set_signal_information
{
- if (Lex->add_signal_statement(thd, $3))
+ if (Lex->add_signal_statement(thd, $2))
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -3864,14 +3837,9 @@ resignal_stmt:
;
get_diagnostics:
- GET_SYM which_area DIAGNOSTICS_SYM
+ GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information
{
- if (Lex->main_select_push())
- YYABORT;
- }
- diagnostics_information
- {
- Diagnostics_information *info= $5;
+ Diagnostics_information *info= $4;
info->set_which_da($2);
@@ -3880,7 +3848,6 @@ get_diagnostics:
if (Lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -4048,16 +4015,7 @@ sp_decl_idents:
sp_opt_default:
/* Empty */ { $$ = NULL; }
- | DEFAULT
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- expr
- {
- Lex->pop_select(); //main select
- $$ = $3;
- }
+ | DEFAULT expr { $$ = $2; }
;
/*
@@ -4159,15 +4117,10 @@ sp_proc_stmt_statement:
sp_proc_stmt_return:
RETURN_SYM
- {
- Lex->sphead->reset_lex(thd);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
+ { Lex->sphead->reset_lex(thd); }
expr
{
LEX *lex= Lex;
- lex->pop_select(); //main select
sp_head *sp= lex->sphead;
if (sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
$3, lex) ||
@@ -4205,8 +4158,6 @@ assignment_source_expr:
{
DBUG_ASSERT(thd->free_list == NULL);
Lex->sphead->reset_lex(thd, $1);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
expr
{
@@ -4215,7 +4166,6 @@ assignment_source_expr:
$$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, thd->free_list);
thd->free_list= NULL;
- Lex->pop_select(); //main select
if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
@@ -4225,6 +4175,7 @@ for_loop_bound_expr:
assignment_source_lex
{
Lex->sphead->reset_lex(thd, $1);
+ Lex->current_select->parsing_place= FOR_LOOP_BOUND;
}
expr
{
@@ -4234,6 +4185,7 @@ for_loop_bound_expr:
$$->set_item_and_free_list($3, NULL);
if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT;
+ Lex->current_select->parsing_place= NO_MATTER;
}
;
@@ -4348,14 +4300,9 @@ sp_fetch_list:
;
sp_if:
- {
- Lex->sphead->reset_lex(thd);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
+ { Lex->sphead->reset_lex(thd); }
expr THEN_SYM
{
- Lex->pop_select(); //main select
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
@@ -4467,18 +4414,12 @@ case_stmt_specification:
;
case_stmt_body:
- {
- Lex->sphead->reset_lex(thd); /* For expr $2 */
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
+ { Lex->sphead->reset_lex(thd); /* For expr $2 */ }
expr
{
if (Lex->case_stmt_action_expr($2))
MYSQL_YYABORT;
- Lex->pop_select(); //main select
if (Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
@@ -4502,9 +4443,6 @@ simple_when_clause:
WHEN_SYM
{
Lex->sphead->reset_lex(thd); /* For expr $3 */
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
expr
{
@@ -4513,8 +4451,6 @@ simple_when_clause:
LEX *lex= Lex;
if (lex->case_stmt_action_when($3, true))
MYSQL_YYABORT;
-
- lex->pop_select(); //main select
/* For expr $3 */
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
@@ -4531,17 +4467,12 @@ searched_when_clause:
WHEN_SYM
{
Lex->sphead->reset_lex(thd); /* For expr $3 */
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
expr
{
LEX *lex= Lex;
if (lex->case_stmt_action_when($3, false))
MYSQL_YYABORT;
-
- lex->pop_select(); //main select
/* For expr $3 */
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
@@ -4690,7 +4621,6 @@ while_body:
LEX *lex= Lex;
if (lex->sp_while_loop_expression(thd, $1))
MYSQL_YYABORT;
- Lex->pop_select(); //main select pushed before while_body use
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
@@ -4703,12 +4633,7 @@ while_body:
repeat_body:
sp_proc_stmts1 UNTIL_SYM
- {
- Lex->sphead->reset_lex(thd);
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
+ { Lex->sphead->reset_lex(thd); }
expr END REPEAT_SYM
{
LEX *lex= Lex;
@@ -4719,8 +4644,6 @@ repeat_body:
if (i == NULL ||
lex->sphead->add_instr(i))
MYSQL_YYABORT;
-
- lex->pop_select(); //main select
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
/* We can shortcut the cont_backpatch here */
@@ -4749,12 +4672,8 @@ sp_labeled_control:
if (Lex->sp_push_loop_label(thd, &$1))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
while_body pop_sp_loop_label
-
{ }
| sp_label FOR_SYM
{
@@ -4806,13 +4725,9 @@ sp_unlabeled_control:
if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
while_body
{
- // while body pop main select
Lex->sp_pop_loop_empty_label(thd);
}
| FOR_SYM
@@ -6898,22 +6813,7 @@ parenthesized_expr:
remember_tok_start
query_expression
{
- if (!Lex->expr_allows_subselect ||
- Lex->sql_command == (int)SQLCOM_PURGE)
- {
- thd->parse_error(ER_SYNTAX_ERROR, $1);
- MYSQL_YYABORT;
- }
-
- // Add the subtree of subquery to the current SELECT_LEX
- SELECT_LEX *curr_sel= Lex->select_stack_head();
- DBUG_ASSERT(Lex->current_select == curr_sel);
- curr_sel->register_unit($2, &curr_sel->context);
- curr_sel->add_statistics($2);
-
- $$= new (thd->mem_root)
- Item_singlerow_subselect(thd, $2->first_select());
- if ($$ == NULL)
+ if (!($$= Lex->create_item_query_expression(thd, $1, $2)))
MYSQL_YYABORT;
}
| expr
@@ -8756,13 +8656,9 @@ checksum:
lex->sql_command = SQLCOM_CHECKSUM;
/* Will be overridden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_list opt_checksum_type
- {
- Lex->pop_select(); //main select
- }
+ {}
;
opt_checksum_type:
@@ -8788,8 +8684,6 @@ repair:
lex->alter_info.reset();
/* Will be overridden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
repair_table_or_view
{
@@ -8798,7 +8692,6 @@ repair:
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -8827,8 +8720,6 @@ analyze:
ANALYZE_SYM opt_no_write_to_binlog table_or_tables
{
LEX *lex=Lex;
- if (lex->main_select_push())
- YYABORT;
lex->sql_command = SQLCOM_ANALYZE;
lex->no_write_to_binlog= $2;
lex->check_opt.init();
@@ -8843,7 +8734,6 @@ analyze:
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -8960,8 +8850,6 @@ check: CHECK_SYM
lex->alter_info.reset();
/* Will be overridden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
check_view_or_table
{
@@ -8972,7 +8860,6 @@ check: CHECK_SYM
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -9010,8 +8897,6 @@ optimize:
lex->alter_info.reset();
/* Will be overridden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_list opt_lock_wait_timeout
{
@@ -9020,7 +8905,6 @@ optimize:
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -9034,13 +8918,9 @@ rename:
RENAME table_or_tables
{
Lex->sql_command= SQLCOM_RENAME_TABLE;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_to_table_list
- {
- Lex->pop_select(); //main select
- }
+ {}
| RENAME USER_SYM clear_privileges rename_list
{
Lex->sql_command = SQLCOM_RENAME_USER;
@@ -9134,13 +9014,9 @@ preload:
LEX *lex=Lex;
lex->sql_command=SQLCOM_PRELOAD_KEYS;
lex->alter_info.reset();
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
preload_list_or_parts
- {
- Lex->pop_select(); //main select
- }
+ {}
;
preload_list_or_parts:
@@ -9526,6 +9402,7 @@ query_expression:
}
;
+
subselect:
remember_tok_start
query_expression
@@ -10332,7 +10209,21 @@ column_default_non_parenthesized_expr:
| param_marker { $$= $1; }
| variable
| sum_expr
+ {
+ if (!Lex->select_stack_top)
+ {
+ my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
| window_func_expr
+ {
+ if (!Lex->select_stack_top)
+ {
+ my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
| inverse_distribution_function
| ROW_SYM '(' expr ',' expr_list ')'
{
@@ -11456,7 +11347,7 @@ sum_expr:
SELECT_LEX *sel= Select;
sel->in_sum_expr--;
$$= new (thd->mem_root)
- Item_func_group_concat(thd, Lex->current_context(),
+ Item_func_group_concat(thd, Lex->current_context_or_default(),
$3, $5,
sel->gorder_list, $7, $8,
sel->select_limit,
@@ -13160,15 +13051,10 @@ do:
LEX *lex=Lex;
lex->sql_command = SQLCOM_DO;
mysql_init_select(lex);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
expr_list
{
Lex->insert_list= $3;
- Lex->pop_select(); //main select
- if (Lex->check_main_unit_semantics())
- MYSQL_YYABORT;
}
;
@@ -13310,7 +13196,8 @@ table_list:
table_name:
table_ident
{
- if (!Select->add_table_to_list(thd, $1, NULL,
+ if (!thd->lex->current_select_or_default()->
+ add_table_to_list(thd, $1, NULL,
TL_OPTION_UPDATING,
YYPS->m_lock_type,
YYPS->m_mdl_type))
@@ -13726,6 +13613,7 @@ delete_part2:
| HISTORY_SYM delete_single_table opt_delete_system_time
{
Lex->last_table()->vers_conditions= Lex->vers_conditions;
+ Lex->pop_select();
}
;
@@ -13852,8 +13740,6 @@ truncate:
{
LEX* lex= Lex;
lex->sql_command= SQLCOM_TRUNCATE;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
lex->alter_info.reset();
lex->builtin_select.options= 0;
lex->builtin_select.sql_cache= SELECT_LEX::SQL_CACHE_UNSPECIFIED;
@@ -13868,7 +13754,6 @@ truncate:
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -14680,13 +14565,9 @@ purge:
LEX *lex=Lex;
lex->type=0;
lex->sql_command = SQLCOM_PURGE;
- if (lex->main_select_push())
- MYSQL_YYABORT;
}
purge_options
- {
- Lex->pop_select(); //main select
- }
+ {}
;
purge_options:
@@ -14715,8 +14596,6 @@ kill:
KILL_SYM
{
LEX *lex=Lex;
- if (lex->main_select_push())
- YYABORT;
lex->value_list.empty();
lex->users_list.empty();
lex->sql_command= SQLCOM_KILL;
@@ -14725,7 +14604,6 @@ kill:
kill_type kill_option kill_expr
{
Lex->kill_signal= (killed_state) ($3 | $4);
- Lex->pop_select(); //main select
}
;
@@ -16545,13 +16423,9 @@ lock:
if (lex->sphead)
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
lex->sql_command= SQLCOM_LOCK_TABLES;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_lock_list opt_lock_wait_timeout
- {
- Lex->pop_select(); //main select
- }
+ {}
;
opt_lock_wait_timeout:
@@ -16616,13 +16490,9 @@ unlock:
if (lex->sphead)
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
lex->sql_command= SQLCOM_UNLOCK_TABLES;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_or_tables
- {
- Lex->pop_select(); //main select
- }
+ {}
;
/*
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 55d837b..1b80f78 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -1640,22 +1640,14 @@ deallocate_or_drop:
;
prepare:
- PREPARE_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- ident FROM prepare_src
+ PREPARE_SYM ident FROM prepare_src
{
LEX *lex= thd->lex;
if (lex->table_or_sp_used())
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
"PREPARE..FROM"));
- if (Lex->check_main_unit_semantics())
- MYSQL_YYABORT;
lex->sql_command= SQLCOM_PREPARE;
- lex->prepared_stmt_name= $3;
- Lex->pop_select(); //main select
+ lex->prepared_stmt_name= $2;
}
;
@@ -1674,21 +1666,10 @@ execute:
LEX *lex= thd->lex;
lex->sql_command= SQLCOM_EXECUTE;
lex->prepared_stmt_name= $2;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
execute_using
- {
- Lex->pop_select(); //main select
- if (Lex->check_main_unit_semantics())
- MYSQL_YYABORT;
- }
- | EXECUTE_SYM IMMEDIATE_SYM
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- prepare_src
+ {}
+ | EXECUTE_SYM IMMEDIATE_SYM prepare_src
{
if (Lex->table_or_sp_used())
my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0),
@@ -1696,11 +1677,7 @@ execute:
Lex->sql_command= SQLCOM_EXECUTE_IMMEDIATE;
}
execute_using
- {
- Lex->pop_select(); //main select
- if (Lex->check_main_unit_semantics())
- MYSQL_YYABORT;
- }
+ {}
;
execute_using:
@@ -2952,13 +2929,8 @@ call:
{
if (Lex->call_statement_start(thd, $2))
MYSQL_YYABORT;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- opt_sp_cparam_list
- {
- Lex->pop_select(); //main select
}
+ opt_sp_cparam_list {}
;
/* CALL parameters */
@@ -3488,16 +3460,10 @@ raise_stmt:
;
signal_stmt:
- SIGNAL_SYM
+ SIGNAL_SYM signal_value opt_set_signal_information
{
- if (Lex->main_select_push())
- YYABORT;
- }
- signal_value opt_set_signal_information
- {
- if (Lex->add_signal_statement(thd, $3))
+ if (Lex->add_signal_statement(thd, $2))
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -3623,14 +3589,9 @@ resignal_stmt:
;
get_diagnostics:
- GET_SYM which_area DIAGNOSTICS_SYM
+ GET_SYM which_area DIAGNOSTICS_SYM diagnostics_information
{
- if (Lex->main_select_push())
- YYABORT;
- }
- diagnostics_information
- {
- Diagnostics_information *info= $5;
+ Diagnostics_information *info= $4;
info->set_which_da($2);
@@ -3639,7 +3600,6 @@ get_diagnostics:
if (Lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -3820,26 +3780,8 @@ sp_decl_idents:
sp_opt_default:
/* Empty */ { $$ = NULL; }
- | DEFAULT
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- expr
- {
- Lex->pop_select(); //main select
- $$ = $3;
- }
- | SET_VAR
- {
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
- expr
- {
- Lex->pop_select(); //main select
- $$ = $3;
- }
+ | DEFAULT expr { $$ = $2; }
+ | SET_VAR expr { $$ = $2; }
;
sp_proc_stmt:
@@ -3956,15 +3898,10 @@ sp_proc_stmt_statement:
sp_proc_stmt_return:
RETURN_SYM
- {
- Lex->sphead->reset_lex(thd);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
+ { Lex->sphead->reset_lex(thd); }
expr
{
LEX *lex= Lex;
- lex->pop_select(); //main select
sp_head *sp= lex->sphead;
if (sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
$3, lex) ||
@@ -4079,8 +4016,6 @@ assignment_source_expr:
{
DBUG_ASSERT(thd->free_list == NULL);
Lex->sphead->reset_lex(thd, $1);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
expr
{
@@ -4089,7 +4024,6 @@ assignment_source_expr:
$$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, thd->free_list);
thd->free_list= NULL;
- Lex->pop_select(); //main select
if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
@@ -4099,6 +4033,7 @@ for_loop_bound_expr:
assignment_source_lex
{
Lex->sphead->reset_lex(thd, $1);
+ Lex->current_select->parsing_place= FOR_LOOP_BOUND;
}
expr
{
@@ -4108,6 +4043,7 @@ for_loop_bound_expr:
$$->set_item_and_free_list($3, NULL);
if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT;
+ Lex->current_select->parsing_place= NO_MATTER;
}
;
@@ -4210,14 +4146,9 @@ sp_fetch_list:
;
sp_if:
- {
- Lex->sphead->reset_lex(thd);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
+ { Lex->sphead->reset_lex(thd); }
expr THEN_SYM
{
- Lex->pop_select(); //main select
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
@@ -4329,18 +4260,12 @@ case_stmt_specification:
;
case_stmt_body:
- {
- Lex->sphead->reset_lex(thd); /* For expr $2 */
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
+ { Lex->sphead->reset_lex(thd); /* For expr $2 */ }
expr
{
if (Lex->case_stmt_action_expr($2))
MYSQL_YYABORT;
- Lex->pop_select(); //main select
if (Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
@@ -4364,9 +4289,6 @@ simple_when_clause:
WHEN_SYM
{
Lex->sphead->reset_lex(thd); /* For expr $3 */
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
expr
{
@@ -4375,8 +4297,6 @@ simple_when_clause:
LEX *lex= Lex;
if (lex->case_stmt_action_when($3, true))
MYSQL_YYABORT;
-
- lex->pop_select(); //main select
/* For expr $3 */
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
@@ -4393,17 +4313,12 @@ searched_when_clause:
WHEN_SYM
{
Lex->sphead->reset_lex(thd); /* For expr $3 */
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
expr
{
LEX *lex= Lex;
if (lex->case_stmt_action_when($3, false))
MYSQL_YYABORT;
-
- lex->pop_select(); //main select
/* For expr $3 */
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
@@ -4643,7 +4558,6 @@ while_body:
LEX *lex= Lex;
if (lex->sp_while_loop_expression(thd, $1))
MYSQL_YYABORT;
- Lex->pop_select(); //main select pushed before while_body use
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
@@ -4656,12 +4570,7 @@ while_body:
repeat_body:
sp_proc_stmts1 UNTIL_SYM
- {
- Lex->sphead->reset_lex(thd);
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
- }
+ { Lex->sphead->reset_lex(thd); }
expr END REPEAT_SYM
{
LEX *lex= Lex;
@@ -4672,8 +4581,6 @@ repeat_body:
if (i == NULL ||
lex->sphead->add_instr(i))
MYSQL_YYABORT;
-
- lex->pop_select(); //main select
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
/* We can shortcut the cont_backpatch here */
@@ -4702,12 +4609,8 @@ sp_labeled_control:
if (Lex->sp_push_loop_label(thd, &$1))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
while_body pop_sp_loop_label
-
{ }
| labels_declaration_oracle FOR_SYM
{
@@ -4759,13 +4662,9 @@ sp_unlabeled_control:
if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
-
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
while_body
{
- // while body pop main select
Lex->sp_pop_loop_empty_label(thd);
}
| FOR_SYM
@@ -6667,22 +6566,7 @@ parenthesized_expr:
remember_tok_start
query_expression
{
- if (!Lex->expr_allows_subselect ||
- Lex->sql_command == (int)SQLCOM_PURGE)
- {
- thd->parse_error(ER_SYNTAX_ERROR, $1);
- MYSQL_YYABORT;
- }
-
- // Add the subtree of subquery to the current SELECT_LEX
- SELECT_LEX *curr_sel= Lex->select_stack_head();
- DBUG_ASSERT(Lex->current_select == curr_sel);
- curr_sel->register_unit($2, &curr_sel->context);
- curr_sel->add_statistics($2);
-
- $$= new (thd->mem_root)
- Item_singlerow_subselect(thd, $2->first_select());
- if ($$ == NULL)
+ if (!($$= Lex->create_item_query_expression(thd, $1, $2)))
MYSQL_YYABORT;
}
| expr
@@ -8579,13 +8463,9 @@ checksum:
lex->sql_command = SQLCOM_CHECKSUM;
/* Will be overridden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_list opt_checksum_type
- {
- Lex->pop_select(); //main select
- }
+ {}
;
opt_checksum_type:
@@ -8611,8 +8491,6 @@ repair:
lex->alter_info.reset();
/* Will be overridden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
repair_table_or_view
{
@@ -8621,7 +8499,6 @@ repair:
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -8650,8 +8527,6 @@ analyze:
ANALYZE_SYM opt_no_write_to_binlog table_or_tables
{
LEX *lex=Lex;
- if (lex->main_select_push())
- YYABORT;
lex->sql_command = SQLCOM_ANALYZE;
lex->no_write_to_binlog= $2;
lex->check_opt.init();
@@ -8666,7 +8541,6 @@ analyze:
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_analyze_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -8783,8 +8657,6 @@ check: CHECK_SYM
lex->alter_info.reset();
/* Will be overridden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
check_view_or_table
{
@@ -8795,7 +8667,6 @@ check: CHECK_SYM
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -8833,8 +8704,6 @@ optimize:
lex->alter_info.reset();
/* Will be overridden during execution. */
YYPS->m_lock_type= TL_UNLOCK;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_list opt_lock_wait_timeout
{
@@ -8843,7 +8712,6 @@ optimize:
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_optimize_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
;
@@ -8857,13 +8725,9 @@ rename:
RENAME table_or_tables
{
Lex->sql_command= SQLCOM_RENAME_TABLE;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_to_table_list
- {
- Lex->pop_select(); //main select
- }
+ {}
| RENAME USER_SYM clear_privileges rename_list
{
Lex->sql_command = SQLCOM_RENAME_USER;
@@ -8957,13 +8821,9 @@ preload:
LEX *lex=Lex;
lex->sql_command=SQLCOM_PRELOAD_KEYS;
lex->alter_info.reset();
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
preload_list_or_parts
- {
- Lex->pop_select(); //main select
- }
+ {}
;
preload_list_or_parts:
@@ -10140,7 +10000,21 @@ column_default_non_parenthesized_expr:
| param_marker { $$= $1; }
| variable
| sum_expr
+ {
+ if (!Lex->select_stack_top)
+ {
+ my_error(ER_INVALID_GROUP_FUNC_USE, MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
| window_func_expr
+ {
+ if (!Lex->select_stack_top)
+ {
+ my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
+ MYSQL_YYABORT;
+ }
+ }
| inverse_distribution_function
| ROW_SYM '(' expr ',' expr_list ')'
{
@@ -11263,7 +11137,7 @@ sum_expr:
SELECT_LEX *sel= Select;
sel->in_sum_expr--;
$$= new (thd->mem_root)
- Item_func_group_concat(thd, Lex->current_context(),
+ Item_func_group_concat(thd, Lex->current_context_or_default(),
$3, $5,
sel->gorder_list, $7, $8,
sel->select_limit,
@@ -12976,15 +12850,10 @@ do:
LEX *lex=Lex;
lex->sql_command = SQLCOM_DO;
mysql_init_select(lex);
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
expr_list
{
Lex->insert_list= $3;
- Lex->pop_select(); //main select
- if (Lex->check_main_unit_semantics())
- MYSQL_YYABORT;
}
;
@@ -13666,7 +13535,6 @@ truncate:
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_truncate_table();
if (lex->m_sql_cmd == NULL)
MYSQL_YYABORT;
- Lex->pop_select(); //main select
}
opt_truncate_table_storage_clause { }
;
@@ -14459,13 +14327,9 @@ purge:
LEX *lex=Lex;
lex->type=0;
lex->sql_command = SQLCOM_PURGE;
- if (lex->main_select_push())
- MYSQL_YYABORT;
}
purge_options
- {
- Lex->pop_select(); //main select
- }
+ {}
;
purge_options:
@@ -14483,8 +14347,6 @@ purge_option:
lex->value_list.empty();
lex->value_list.push_front($2, thd->mem_root);
lex->sql_command= SQLCOM_PURGE_BEFORE;
- if (Lex->check_main_unit_semantics())
- MYSQL_YYABORT;
}
;
@@ -14494,8 +14356,6 @@ kill:
KILL_SYM
{
LEX *lex=Lex;
- if (lex->main_select_push())
- YYABORT;
lex->value_list.empty();
lex->users_list.empty();
lex->sql_command= SQLCOM_KILL;
@@ -14504,7 +14364,6 @@ kill:
kill_type kill_option kill_expr
{
Lex->kill_signal= (killed_state) ($3 | $4);
- Lex->pop_select(); //main select
}
;
@@ -16457,13 +16316,9 @@ lock:
if (lex->sphead)
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
lex->sql_command= SQLCOM_LOCK_TABLES;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_lock_list opt_lock_wait_timeout
- {
- Lex->pop_select(); //main select
- }
+ {}
;
opt_lock_wait_timeout:
@@ -16528,13 +16383,9 @@ unlock:
if (lex->sphead)
my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
lex->sql_command= SQLCOM_UNLOCK_TABLES;
- if (Lex->main_select_push())
- MYSQL_YYABORT;
}
table_or_tables
- {
- Lex->pop_select(); //main select
- }
+ {}
;
/*
Follow ups
References