From c1885d22df4efa779805d480bdd26d203ee49de9 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 7 Jul 2017 17:00:07 +0400 Subject: [PATCH] MDEV-13273 Confusion between table alias and ROW type variable --- mysql-test/r/sp-row.result | 86 ++++++++++++++++- .../suite/compat/oracle/r/sp-row.result | 88 ++++++++++++++++- mysql-test/suite/compat/oracle/t/sp-row.test | 95 ++++++++++++++++++- mysql-test/t/sp-row.test | 92 +++++++++++++++++- sql/sql_lex.cc | 5 +- 5 files changed, 352 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/sp-row.result b/mysql-test/r/sp-row.result index f86233bc2b8..c3204fe043b 100644 --- a/mysql-test/r/sp-row.result +++ b/mysql-test/r/sp-row.result @@ -129,15 +129,17 @@ CALL p1(); ERROR 21000: Operand should contain 2 column(s) DROP PROCEDURE p1; # -# Bad usage of a scalar variable as a row +# Scalar variable vs table alias cause no ambiguity # CREATE PROCEDURE p1() BEGIN DECLARE a INT; -SELECT a.x FROM t1; +-- a.x is a table column here (not a row variable field) +SELECT a.x FROM a; +SELECT a.x FROM t1 a; END; $$ -ERROR HY000: 'a' is not a row variable +DROP PROCEDURE p1; # # Using the entire ROW variable in select list # @@ -2166,3 +2168,81 @@ rec1.a rec1.b 10 b10 DROP TABLE t1; DROP PROCEDURE p1; +# +# MDEV-13273 Confusion between table alias and ROW type variable +# +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +CREATE PROCEDURE p1() +BEGIN +DECLARE a INT; +DECLARE b INT; +-- a.c1 is a table column +SELECT a.c1 INTO b +FROM t1 a +WHERE a.c2 = 0; +SELECT b; +END; +$$ +CALL p1; +b +0 +DROP PROCEDURE p1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +CREATE PROCEDURE p1() +BEGIN +DECLARE a ROW (c1 INT, c2 INT) DEFAULT ROW(101,102); +DECLARE b INT; +-- a.c1 is a ROW variable field +SELECT a.c1 INTO b +FROM t1 a +WHERE a.c2 = 102; +SELECT b; +END; +$$ +CALL p1; +b +101 +DROP PROCEDURE p1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +CREATE PROCEDURE p1() +BEGIN +DECLARE a ROW TYPE OF t1 DEFAULT ROW (10,20); +DECLARE b INT; +-- a.c1 is a ROW variable field +SELECT a.c1 INTO b +FROM t1 a +WHERE a.c2 = 20; +SELECT b; +END; +$$ +CALL p1; +b +10 +DROP PROCEDURE p1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +CREATE PROCEDURE p1() +BEGIN +DECLARE cur1 CURSOR FOR SELECT * FROM t1; +BEGIN +DECLARE a ROW TYPE OF cur1 DEFAULT ROW (10,20); +DECLARE b INT; +-- a.c1 is a ROW variable field +SELECT a.c1 INTO b +FROM t1 a +WHERE a.c2 = 20; +SELECT b; +END; +END; +$$ +CALL p1; +b +10 +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/r/sp-row.result b/mysql-test/suite/compat/oracle/r/sp-row.result index b68800cb866..86b6b9a530b 100644 --- a/mysql-test/suite/compat/oracle/r/sp-row.result +++ b/mysql-test/suite/compat/oracle/r/sp-row.result @@ -143,16 +143,18 @@ CALL p1(); ERROR 21000: Operand should contain 2 column(s) DROP PROCEDURE p1; # -# Bad usage of a scalar variable as a row +# Scalar variable vs table alias cause no ambiguity # CREATE PROCEDURE p1() AS a INT; BEGIN -SELECT a.x FROM t1; +-- a.x is a table column here (not a row variable field) +SELECT a.x FROM a; +SELECT a.x FROM t1 a; END; $$ -ERROR HY000: 'a' is not a row variable +DROP PROCEDURE p1; # # Using the entire ROW variable in select list # @@ -2988,3 +2990,83 @@ rec.b b0 DROP TABLE t1; DROP PROCEDURE p1; +# +# MDEV-13273 Confusion between table alias and ROW type variable +# +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +CREATE PROCEDURE p1 +AS +a INT; +b INT; +BEGIN +-- a.c1 is a table column +SELECT a.c1 INTO b +FROM t1 a +WHERE a.c2 = 0; +SELECT b; +END; +$$ +CALL p1; +b +0 +DROP PROCEDURE p1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +CREATE PROCEDURE p1 +AS +a ROW (c1 INT, c2 INT) := ROW(101,102); +b INT; +BEGIN +-- a.c1 is a ROW variable field +SELECT a.c1 INTO b +FROM t1 a +WHERE a.c2 = 102; +SELECT b; +END; +$$ +CALL p1; +b +101 +DROP PROCEDURE p1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +CREATE PROCEDURE p1 +AS +a t1%ROWTYPE := ROW (10,20); +b INT; +BEGIN +-- a.c1 is a ROW variable field +SELECT a.c1 INTO b +FROM t1 a +WHERE a.c2 = 20; +SELECT b; +END; +$$ +CALL p1; +b +10 +DROP PROCEDURE p1; +DROP TABLE t1; +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +CREATE PROCEDURE p1 +AS +CURSOR cur1 IS SELECT * FROM t1; +a cur1%ROWTYPE := ROW (10,20); +b INT; +BEGIN +-- a.c1 is a ROW variable field +SELECT a.c1 INTO b +FROM t1 a +WHERE a.c2 = 20; +SELECT b; +END; +$$ +CALL p1; +b +10 +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/t/sp-row.test b/mysql-test/suite/compat/oracle/t/sp-row.test index 70d5a26223d..5d97bf02fa2 100644 --- a/mysql-test/suite/compat/oracle/t/sp-row.test +++ b/mysql-test/suite/compat/oracle/t/sp-row.test @@ -175,20 +175,21 @@ DROP PROCEDURE p1; --echo # ---echo # Bad usage of a scalar variable as a row +--echo # Scalar variable vs table alias cause no ambiguity --echo # DELIMITER $$; ---error ER_UNKNOWN_ERROR CREATE PROCEDURE p1() AS a INT; BEGIN - SELECT a.x FROM t1; + -- a.x is a table column here (not a row variable field) + SELECT a.x FROM a; + SELECT a.x FROM t1 a; END; $$ DELIMITER ;$$ - +DROP PROCEDURE p1; --echo # --echo # Using the entire ROW variable in select list @@ -2288,3 +2289,89 @@ DELIMITER ;$$ CALL p1(); DROP TABLE t1; DROP PROCEDURE p1; + + +--echo # +--echo # MDEV-13273 Confusion between table alias and ROW type variable +--echo # + +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + a INT; + b INT; +BEGIN + -- a.c1 is a table column + SELECT a.c1 INTO b + FROM t1 a + WHERE a.c2 = 0; + SELECT b; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + a ROW (c1 INT, c2 INT) := ROW(101,102); + b INT; +BEGIN + -- a.c1 is a ROW variable field + SELECT a.c1 INTO b + FROM t1 a + WHERE a.c2 = 102; + SELECT b; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + a t1%ROWTYPE := ROW (10,20); + b INT; +BEGIN + -- a.c1 is a ROW variable field + SELECT a.c1 INTO b + FROM t1 a + WHERE a.c2 = 20; + SELECT b; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + CURSOR cur1 IS SELECT * FROM t1; + a cur1%ROWTYPE := ROW (10,20); + b INT; +BEGIN + -- a.c1 is a ROW variable field + SELECT a.c1 INTO b + FROM t1 a + WHERE a.c2 = 20; + SELECT b; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/mysql-test/t/sp-row.test b/mysql-test/t/sp-row.test index e9e141b2533..6ed8b4495f4 100644 --- a/mysql-test/t/sp-row.test +++ b/mysql-test/t/sp-row.test @@ -161,18 +161,20 @@ DROP PROCEDURE p1; --echo # ---echo # Bad usage of a scalar variable as a row +--echo # Scalar variable vs table alias cause no ambiguity --echo # DELIMITER $$; ---error ER_UNKNOWN_ERROR CREATE PROCEDURE p1() BEGIN DECLARE a INT; - SELECT a.x FROM t1; + -- a.x is a table column here (not a row variable field) + SELECT a.x FROM a; + SELECT a.x FROM t1 a; END; $$ DELIMITER ;$$ +DROP PROCEDURE p1; --echo # @@ -1385,3 +1387,87 @@ DELIMITER ;$$ CALL p1(); DROP TABLE t1; DROP PROCEDURE p1; + + +--echo # +--echo # MDEV-13273 Confusion between table alias and ROW type variable +--echo # + +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE a INT; + DECLARE b INT; + -- a.c1 is a table column + SELECT a.c1 INTO b + FROM t1 a + WHERE a.c2 = 0; + SELECT b; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE a ROW (c1 INT, c2 INT) DEFAULT ROW(101,102); + DECLARE b INT; + -- a.c1 is a ROW variable field + SELECT a.c1 INTO b + FROM t1 a + WHERE a.c2 = 102; + SELECT b; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE a ROW TYPE OF t1 DEFAULT ROW (10,20); + DECLARE b INT; + -- a.c1 is a ROW variable field + SELECT a.c1 INTO b + FROM t1 a + WHERE a.c2 = 20; + SELECT b; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; + +CREATE TABLE t1 (c1 INT, c2 INT); +INSERT INTO t1 VALUES (0,0); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE cur1 CURSOR FOR SELECT * FROM t1; + BEGIN + DECLARE a ROW TYPE OF cur1 DEFAULT ROW (10,20); + DECLARE b INT; + -- a.c1 is a ROW variable field + SELECT a.c1 INTO b + FROM t1 a + WHERE a.c2 = 20; + SELECT b; + END; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 41df42d11f8..07534b7e7a6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -6452,7 +6452,10 @@ Item *LEX::create_item_ident(THD *thd, uint pos_in_q, uint length_in_q) { sp_variable *spv; - if (spcont && (spv= spcont->find_variable(a, false))) + if (spcont && (spv= spcont->find_variable(a, false)) && + (spv->field_def.is_row() || + spv->field_def.is_table_rowtype_ref() || + spv->field_def.is_cursor_rowtype_ref())) return create_item_spvar_row_field(thd, a, b, spv, pos_in_q, length_in_q); if ((thd->variables.sql_mode & MODE_ORACLE) && b->length == 7)