1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable

CREATE PROCEDURE did not detect unknown SP variables in assignments like this:

  SET var=a_long_var_name_with_a_typo;

The error happened only during the SP execution time, and only of the control
flow reaches the erroneous statement.

Fixing most expressions to detect unknown identifiers.
This includes simple subqueries without tables:

- Query specification: SELECT list, WHERE,
  HAVING (inside aggregate functions) clauses, e.g.
    SET var= (SELECT unknown_ident+1);
    SET var= (SELECT 1 WHERE unknown_identifier);
    SET var= (SELECT 1 HAVING SUM(unknown_identifier);

- Table value constructor: VALUES clause, e.g.:
    SET var= (VALUES(unknown_ident));

Note, in some more complex subquery cases unknown variables are still not detected
(this will be fixed separately):

- Derived tables:
  SET a=(SELECT unknown_ident FROM (SELECT 1 AS alias) t1);
  SET res=(SELECT * FROM t1 LEFT OUTER JOIN (SELECT unknown_ident) t2 USING (c1));

- CTE:
  SET a=(WITH cte1 (a) AS (SELECT unknown_ident) SELECT * FROM cte1);
  SET a=(WITH cte1 (a,b) AS (VALUES (unknown,2),(3,4)) SELECT * FROM cte1);
  SET a=(WITH cte1 (a,b) AS (VALUES (1,2),(3,4)) SELECT unknown_ident FROM cte1);

- SELECT .. GROUP BY unknown_identifier
- SELECT .. ORDER BY unknown_identifier
- HAVING with an unknown identifier outside of any aggregate functions:
  SELECT .. HAVING unknown_identifier;
This commit is contained in:
Alexander Barkov
2020-06-09 23:03:08 +04:00
parent 264a98eaa0
commit 6e2d967b1b
11 changed files with 1096 additions and 19 deletions

View File

@ -1310,3 +1310,406 @@ t1 CREATE TABLE "t1" (
"var" char(1) DEFAULT NULL
)
DROP TABLE t1;
#
# MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
#
#
# Simple cases (without subqueries) - the most typical problem:
# a typo in an SP variable name
#
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
IF (a < 0) THEN
SET res= a_long_variable_name_with_a_typo;
END IF;
END;
$$
ERROR 42000: Undeclared variable: a_long_variable_name_with_a_typo
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
IF (a < 0) THEN
SET res= 1 + a_long_variable_name_with_a_typo;
END IF;
END;
$$
ERROR 42000: Undeclared variable: a_long_variable_name_with_a_typo
#
# Complex cases with subqueries
#
#
# Maybe a table field identifier (there are some tables) - no error
#
CREATE PROCEDURE p1()
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(SELECT * FROM t1 LEFT OUTER JOIN t2 USING (c1));
END;
$$
DROP PROCEDURE p1;
CREATE PROCEDURE p1()
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(SELECT * FROM t1 LEFT OUTER JOIN t2 ON (c1=c2));
END;
$$
DROP PROCEDURE p1;
#
# One unknown identifier, no tables
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=unknown_ident;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=unknown_ident1.unknown_ident2;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident1
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=unknown_ident1.unknown_ident2.unknown_ident3;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident1
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT unknown_ident);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT unknown_ident FROM dual);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT (SELECT unknown_ident));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT (SELECT unknown_ident FROM dual));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT 1 WHERE unknown_ident);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT 1 WHERE unknown_ident=1);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT 1 LIMIT unknown_ident);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
#
# GROUP, HAVING, ORDER are not tested yet for unknown identifiers
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT 1 GROUP BY unknown_ident);
END;
$$
DROP PROCEDURE p1;
CREATE PROCEDURE p1()
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(SELECT 1 HAVING unknown_ident);
END;
$$
DROP PROCEDURE p1;
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT 1 ORDER BY unknown_ident);
END;
$$
DROP PROCEDURE p1;
#
# HAVING + aggregate_function(unknown_identifier) is a special case
#
CREATE PROCEDURE p1()
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(SELECT 1 HAVING SUM(unknown_ident));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
#
# Known indentifier + unknown identifier, no tables
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=a+unknown_ident;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=a+(SELECT unknown_ident);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=a+(SELECT unknown_ident FROM dual);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT (a+(SELECT unknown_ident)));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT (a+(SELECT unknown_ident FROM dual)));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
#
# Unknown indentifier + known identifier, no tables
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=unknown_ident+a;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT unknown_ident)+a;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT unknown_ident FROM dual)+a;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT (SELECT unknown_ident)+a);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT (SELECT unknown_ident FROM dual)+a);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
#
# Maybe a table field indentifier + unknown identifier
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT c1 FROM t1)+unknown_ident;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT c1 FROM t1)+(SELECT unknown_ident);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT c1 FROM t1)+(SELECT unknown_ident FROM dual);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT ((SELECT c1 FROM t1)+(SELECT unknown_ident)));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT ((SELECT c1 FROM t1)+(SELECT unknown_ident FROM dual)));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
#
# Unknown indentifier + maybe a table field identifier
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=unknown_ident+(SELECT c1 FROM t1);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT unknown_ident)+(SELECT c1 FROM t1);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT unknown_ident FROM dual)+(SELECT c1 FROM t1);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT (SELECT unknown_ident)+(SELECT c1 FROM t1));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
SET a=(SELECT (SELECT unknown_ident FROM dual)+(SELECT c1 FROM t1));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
#
# Maybe a table field identifier + maybe a field table identifier
#
CREATE PROCEDURE p1()
BEGIN
DECLARE a INT;
-- c2 does not have a table on its level
-- but it can be a field of a table on the uppder level, i.e. t1
SET a=(SELECT c1+(SELECT c2) FROM t1);
END;
$$
DROP PROCEDURE p1;
#
# TVC - unknown identifier
#
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(VALUES(unknown_ident));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(VALUES(1),(unknown_ident));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(VALUES((SELECT unknown_ident)));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(VALUES(1),((SELECT unknown_ident)));
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(VALUES(1) LIMIT unknown_ident);
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
#
# TVC - ORDER BY - not tested yet for unknown identifiers
#
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(VALUES(1) ORDER BY unknown_ident);
END;
$$
DROP PROCEDURE p1;
#
# TVC - maybe a table field identifier - no error
#
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(VALUES((SELECT c1 FROM t1)));
END;
$$
DROP PROCEDURE p1;
CREATE PROCEDURE p1(a INT)
BEGIN
DECLARE res INT DEFAULT 0;
SET res=(VALUES(1),((SELECT c1 FROM t1)));
END;
$$
DROP PROCEDURE p1;
#
# Functions DEFAULT(x) and VALUE(x)
#
CREATE PROCEDURE p1()
BEGIN
DECLARE res INT DEFAULT 0;
SET res=DEFAULT(unknown_ident);
SELECT res;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
CREATE PROCEDURE p1()
BEGIN
DECLARE res INT DEFAULT 0;
SET res=VALUE(unknown_ident);
SELECT res;
END;
$$
ERROR 42000: Undeclared variable: unknown_ident
#
# End of MDEV-14347 CREATE PROCEDURE returns no error when using an unknown variable
#