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); ...@@ -252,3 +252,101 @@ CREATE TABLE begin (begin INT);
DROP TABLE begin; DROP TABLE begin;
CREATE TABLE end (end INT); CREATE TABLE end (end INT);
DROP TABLE end; 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); ...@@ -272,3 +272,108 @@ CREATE TABLE begin (begin INT);
DROP TABLE begin; DROP TABLE begin;
CREATE TABLE end (end INT); CREATE TABLE end (end INT);
DROP TABLE end; 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 ...@@ -3097,8 +3097,16 @@ struct LEX: public Query_tables_list
class sp_label *tmp; class sp_label *tmp;
return sp_block_finalize(thd, spblock, &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, bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
const LEX_STRING end_label); 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, bool sp_declarations_join(Lex_spblock_st *res,
const Lex_spblock_st b1, const Lex_spblock_st b1,
const Lex_spblock_st b2) const const Lex_spblock_st b2) const
......
...@@ -1329,7 +1329,7 @@ END_OF_INPUT ...@@ -1329,7 +1329,7 @@ END_OF_INPUT
%type <num> sp_decl_idents sp_handler_type sp_hcond_list %type <num> sp_decl_idents sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value %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 <lex> sp_cursor_stmt
%type <spname> sp_name %type <spname> sp_name
%type <spvar> sp_param_name sp_param_name_and_type %type <spvar> sp_param_name sp_param_name_and_type
...@@ -2359,26 +2359,23 @@ sp_proc_stmts1: ...@@ -2359,26 +2359,23 @@ sp_proc_stmts1:
| sp_proc_stmts1 sp_proc_stmt ';' | sp_proc_stmts1 sp_proc_stmt ';'
; ;
sp_decls: opt_sp_decl_body_list:
/* Empty */ /* Empty */
{ {
$$.init(); $$.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)) if (Lex->sp_declarations_join(&$$, $1, $2))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
; ;
sp_decl:
DECLARE_SYM sp_decl_body { $$= $2; }
;
sp_decl_body: sp_decl_body:
sp_decl_idents sp_decl_idents
{ {
...@@ -2392,7 +2389,7 @@ sp_decl_body: ...@@ -2392,7 +2389,7 @@ sp_decl_body:
$$.vars= $1; $$.vars= $1;
$$.conds= $$.hndlrs= $$.curs= 0; $$.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)) if (Lex->spcont->declare_condition(thd, $1, $4))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -2411,7 +2408,7 @@ sp_decl_body: ...@@ -2411,7 +2408,7 @@ sp_decl_body:
$$.vars= $$.conds= $$.curs= 0; $$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= 1; $$.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)) if (Lex->sp_declare_cursor(thd, $1, $4))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -2823,7 +2820,7 @@ condition_information_item_name: ...@@ -2823,7 +2820,7 @@ condition_information_item_name:
; ;
sp_decl_idents: sp_decl_idents:
ident ident_directly_assignable
{ {
/* NOTE: field definition is filled in sp_decl section. */ /* NOTE: field definition is filled in sp_decl section. */
...@@ -3381,12 +3378,25 @@ sp_labeled_block: ...@@ -3381,12 +3378,25 @@ sp_labeled_block:
{ {
Lex->sp_block_init(thd, $1); Lex->sp_block_init(thd, $1);
} }
sp_decls
sp_proc_stmts sp_proc_stmts
END END
sp_opt_label 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; MYSQL_YYABORT;
} }
; ;
...@@ -3396,7 +3406,18 @@ sp_unlabeled_block: ...@@ -3396,7 +3406,18 @@ sp_unlabeled_block:
{ {
Lex->sp_block_init(thd); 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 sp_proc_stmts
END END
{ {
...@@ -3405,6 +3426,20 @@ sp_unlabeled_block: ...@@ -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: sp_unlabeled_block_not_atomic:
BEGIN_SYM not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */ BEGIN_SYM not ATOMIC_SYM /* TODO: BEGIN ATOMIC (not -> opt_not) */
{ {
...@@ -3412,11 +3447,10 @@ sp_unlabeled_block_not_atomic: ...@@ -3412,11 +3447,10 @@ sp_unlabeled_block_not_atomic:
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sp_block_init(thd); Lex->sp_block_init(thd);
} }
sp_decls
sp_proc_stmts sp_proc_stmts
END END
{ {
if (Lex->sp_block_finalize(thd, $5)) if (Lex->sp_block_finalize(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
; ;
...@@ -15982,7 +16016,7 @@ sf_tail: ...@@ -15982,7 +16016,7 @@ sf_tail:
lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); lex->sphead->set_body_start(thd, lip->get_cpp_tok_start());
} }
sp_tail_is /* $15 */ sp_tail_is /* $15 */
sp_proc_stmt_in_returns_clause /* $16 */ sp_body /* $16 */
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
...@@ -16031,7 +16065,7 @@ sp_tail: ...@@ -16031,7 +16065,7 @@ sp_tail:
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start()); Lex->sphead->set_body_start(thd, YYLIP->get_cpp_tok_start());
} }
sp_tail_is sp_tail_is
sp_proc_stmt sp_body
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
......
...@@ -649,4 +649,10 @@ struct Lex_spblock_st ...@@ -649,4 +649,10 @@ struct Lex_spblock_st
}; };
class Lex_spblock: public Lex_spblock_st
{
public:
Lex_spblock() { init(); }
};
#endif /* STRUCTS_INCLUDED */ #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