Commit a44e90ae authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10411 Providing compatibility for basic PL/SQL constructs

Part 7: variable declarations
parent e399949b
......@@ -252,3 +252,101 @@ CREATE TABLE begin (begin INT);
DROP TABLE begin;
CREATE TABLE end (end INT);
DROP TABLE end;
# Testing top-level declarations
CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10))
AS
p2 VARCHAR(10);
BEGIN
p2:='p1new';
p1:=p2;
END;
/
SET @p1='p1';
CALL p1(@p1);
SELECT @p1;
@p1
p1new
DROP PROCEDURE p1;
CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURNS VARCHAR(20)
AS
p2 VARCHAR(10);
BEGIN
p2:='new';
RETURN CONCAT(p1, p2);
END;
/
SET @p1='p1';
SELECT f1(@p1);
f1(@p1)
p1new
DROP FUNCTION f1;
# Testing non-top declarations
CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10))
AS
BEGIN
DECLARE
p2 VARCHAR(10);
BEGIN
p2:='p1new';
p1:=p2;
END;
DECLARE
t1 VARCHAR(10);
t2 VARCHAR(10);
BEGIN
END;
END;
/
SET @p1='p1';
CALL p1(@p1);
SELECT @p1;
@p1
p1new
DROP PROCEDURE p1;
CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURNS VARCHAR(20)
AS
BEGIN
DECLARE
p2 VARCHAR(10);
BEGIN
p2:='new';
RETURN CONCAT(p1, p2);
END;
DECLARE
t1 VARCHAR(10);
t2 VARCHAR(10);
BEGIN
END;
END;
/
SET @p1='p1';
SELECT f1(@p1);
f1(@p1)
p1new
DROP FUNCTION f1;
# Testing BEGIN NOT ATOMIC with no declarations
BEGIN NOT ATOMIC
SELECT 1 AS a;
END
/
a
1
# Testing BEGIN NOT ATOMIC with declarations
# DECLARE starts a new block and thus must be followed by BEGIN .. END
BEGIN NOT ATOMIC
DECLARE
i INT DEFAULT 5;
x INT DEFAULT 10;
BEGIN
<<label>>
WHILE i > 3 DO
i:= i - 1;
SELECT i;
END WHILE label;
END;
END
/
i
4
i
3
......@@ -272,3 +272,108 @@ CREATE TABLE begin (begin INT);
DROP TABLE begin;
CREATE TABLE end (end INT);
DROP TABLE end;
--echo # Testing top-level declarations
DELIMITER /;
CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10))
AS
p2 VARCHAR(10);
BEGIN
p2:='p1new';
p1:=p2;
END;
/
DELIMITER ;/
SET @p1='p1';
CALL p1(@p1);
SELECT @p1;
DROP PROCEDURE p1;
DELIMITER /;
CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURNS VARCHAR(20)
AS
p2 VARCHAR(10);
BEGIN
p2:='new';
RETURN CONCAT(p1, p2);
END;
/
DELIMITER ;/
SET @p1='p1';
SELECT f1(@p1);
DROP FUNCTION f1;
--echo # Testing non-top declarations
DELIMITER /;
CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10))
AS
BEGIN
DECLARE
p2 VARCHAR(10);
BEGIN
p2:='p1new';
p1:=p2;
END;
DECLARE
t1 VARCHAR(10);
t2 VARCHAR(10);
BEGIN
END;
END;
/
DELIMITER ;/
SET @p1='p1';
CALL p1(@p1);
SELECT @p1;
DROP PROCEDURE p1;
DELIMITER /;
CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURNS VARCHAR(20)
AS
BEGIN
DECLARE
p2 VARCHAR(10);
BEGIN
p2:='new';
RETURN CONCAT(p1, p2);
END;
DECLARE
t1 VARCHAR(10);
t2 VARCHAR(10);
BEGIN
END;
END;
/
DELIMITER ;/
SET @p1='p1';
SELECT f1(@p1);
DROP FUNCTION f1;
--echo # Testing BEGIN NOT ATOMIC with no declarations
DELIMITER /;
BEGIN NOT ATOMIC
SELECT 1 AS a;
END
/
DELIMITER ;/
--echo # Testing BEGIN NOT ATOMIC with declarations
--echo # DECLARE starts a new block and thus must be followed by BEGIN .. END
DELIMITER /;
BEGIN NOT ATOMIC
DECLARE
i INT DEFAULT 5;
x INT DEFAULT 10;
BEGIN
<<label>>
WHILE i > 3 DO
i:= i - 1;
SELECT i;
END WHILE label;
END;
END
/
DELIMITER ;/
......@@ -3097,8 +3097,16 @@ struct LEX: public Query_tables_list
class sp_label *tmp;
return sp_block_finalize(thd, spblock, &tmp);
}
bool sp_block_finalize(THD *thd)
{
return sp_block_finalize(thd, Lex_spblock());
}
bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
const LEX_STRING end_label);
bool sp_block_finalize(THD *thd, const LEX_STRING end_label)
{
return sp_block_finalize(thd, Lex_spblock(), end_label);
}
bool sp_declarations_join(Lex_spblock_st *res,
const Lex_spblock_st b1,
const Lex_spblock_st b2) const
......
......@@ -1329,7 +1329,7 @@ END_OF_INPUT
%type <num> sp_decl_idents sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decls sp_decl sp_decl_body
%type <spblock> sp_decl_body sp_decl_body_list opt_sp_decl_body_list
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <spvar> sp_param_name sp_param_name_and_type
......@@ -2359,26 +2359,23 @@ sp_proc_stmts1:
| sp_proc_stmts1 sp_proc_stmt ';'
;
sp_decls:
opt_sp_decl_body_list:
/* Empty */
{
$$.init();
}
| sp_decls sp_decl ';'
| sp_decl_body_list { $$= $1; }
;
sp_decl_body_list:
sp_decl_body ';' { $$= $1; }
| sp_decl_body_list sp_decl_body ';'
{
/* We check for declarations out of (standard) order this way
because letting the grammar rules reflect it caused tricky
shift/reduce conflicts with the wrong result. (And we get
better error handling this way.) */
if (Lex->sp_declarations_join(&$$, $1, $2))
MYSQL_YYABORT;
}
;
sp_decl:
DECLARE_SYM sp_decl_body { $$= $2; }
;
sp_decl_body:
sp_decl_idents
{
......@@ -2392,7 +2389,7 @@ sp_decl_body:
$$.vars= $1;
$$.conds= $$.hndlrs= $$.curs= 0;
}
| ident CONDITION_SYM FOR_SYM sp_cond
| ident_directly_assignable CONDITION_SYM FOR_SYM sp_cond
{
if (Lex->spcont->declare_condition(thd, $1, $4))
MYSQL_YYABORT;
......@@ -2411,7 +2408,7 @@ sp_decl_body:
$$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= 1;
}
| ident CURSOR_SYM FOR_SYM sp_cursor_stmt
| ident_directly_assignable CURSOR_SYM FOR_SYM sp_cursor_stmt
{
if (Lex->sp_declare_cursor(thd, $1, $4))
MYSQL_YYABORT;
......@@ -2823,7 +2820,7 @@ condition_information_item_name:
;
sp_decl_idents:
ident
ident_directly_assignable
{
/* NOTE: field definition is filled in sp_decl section. */
......@@ -3381,12 +3378,25 @@ sp_labeled_block:
{
Lex->sp_block_init(thd, $1);
}
sp_decls
sp_proc_stmts
END
sp_opt_label
{
if (Lex->sp_block_finalize(thd, $4, $7))
if (Lex->sp_block_finalize(thd, $6))
MYSQL_YYABORT;
}
| sp_block_label
DECLARE_SYM
{
Lex->sp_block_init(thd, $1);
}
sp_decl_body_list
BEGIN_SYM
sp_proc_stmts
END
sp_opt_label
{
if (Lex->sp_block_finalize(thd, $4, $8))
MYSQL_YYABORT;
}
;
......@@ -3396,7 +3406,18 @@ sp_unlabeled_block:
{
Lex->sp_block_init(thd);
}
sp_decls
sp_proc_stmts
END
{
if (Lex->sp_block_finalize(thd))
MYSQL_YYABORT;
}
| DECLARE_SYM
{
Lex->sp_block_init(thd);
}
sp_decl_body_list
BEGIN_SYM
sp_proc_stmts
END
{
......@@ -3405,6 +3426,20 @@ sp_unlabeled_block:
}
;
sp_body:
{
Lex->sp_block_init(thd);
}
opt_sp_decl_body_list
BEGIN_SYM
sp_proc_stmts
END
{
if (Lex->sp_block_finalize(thd, $2))
MYSQL_YYABORT;
}
;
sp_unlabeled_block_not_atomic:
BEGIN_SYM not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
{
......@@ -3412,11 +3447,10 @@ sp_unlabeled_block_not_atomic:
MYSQL_YYABORT;
Lex->sp_block_init(thd);
}
sp_decls
sp_proc_stmts
END
{
if (Lex->sp_block_finalize(thd, $5))
if (Lex->sp_block_finalize(thd))
MYSQL_YYABORT;
}
;
......@@ -15982,7 +16016,7 @@ sf_tail:
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
}
sp_tail_is /* $15 */
sp_proc_stmt_in_returns_clause /* $16 */
sp_body /* $16 */
{
LEX *lex= thd->lex;
sp_head *sp= lex->sphead;
......@@ -16031,7 +16065,7 @@ sp_tail:
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
}
sp_tail_is
sp_proc_stmt
sp_body
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
......
......@@ -649,4 +649,10 @@ struct Lex_spblock_st
};
class Lex_spblock: public Lex_spblock_st
{
public:
Lex_spblock() { init(); }
};
#endif /* STRUCTS_INCLUDED */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment