Commit 765d9d64 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10411 Providing compatibility for basic PL/SQL constructs

Moving similar code from sql_yacc.yy and sql_yacc_ora.yy to methods:
  LEX::maybe_start_compound_statement()
  LEX::sp_push_loop_label()
  LEX::sp_push_loop_empty_label()
  LEX::sp_pop_loop_label()
  LEX::sp_pop_loop_empty_label()

The EXIT statement will also reuse this code.
parent f37a943f
...@@ -5506,6 +5506,66 @@ bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name) ...@@ -5506,6 +5506,66 @@ bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name)
} }
bool LEX::maybe_start_compound_statement(THD *thd)
{
if (!sphead)
{
if (!make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
return true;
sp_chistics.suid= SP_IS_NOT_SUID;
sphead->set_body_start(thd, thd->m_parser_state->m_lip.get_cpp_ptr());
}
return false;
}
bool LEX::sp_push_loop_label(THD *thd, const LEX_STRING label_name)
{
sp_label *lab= spcont->find_label(label_name);
if (lab)
{
my_error(ER_SP_LABEL_REDEFINE, MYF(0), label_name.str);
return true;
}
lab= spcont->push_label(thd, label_name, sphead->instructions());
lab->type= sp_label::ITERATION;
return false;
}
bool LEX::sp_push_loop_empty_label(THD *thd)
{
if (maybe_start_compound_statement(thd))
return true;
/* Unlabeled controls get an empty label. */
spcont->push_label(thd, empty_lex_str, sphead->instructions());
return false;
}
bool LEX::sp_pop_loop_label(THD *thd, const LEX_STRING label_name)
{
sp_label *lab= spcont->pop_label();
sphead->backpatch(lab);
if (label_name.str &&
my_strcasecmp(system_charset_info, label_name.str,
lab->name.str) != 0)
{
my_error(ER_SP_LABEL_MISMATCH, MYF(0), label_name.str);
return true;
}
return false;
}
void LEX::sp_pop_loop_empty_label(THD *thd)
{
sp_label *lab= spcont->pop_label();
sphead->backpatch(lab);
DBUG_ASSERT(lab->name.length == 0);
}
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
uint binlog_unsafe_map[256]; uint binlog_unsafe_map[256];
......
...@@ -3155,6 +3155,12 @@ struct LEX: public Query_tables_list ...@@ -3155,6 +3155,12 @@ struct LEX: public Query_tables_list
bool sp_leave_statement(THD *thd, const LEX_STRING label_name); bool sp_leave_statement(THD *thd, const LEX_STRING label_name);
bool sp_iterate_statement(THD *thd, const LEX_STRING label_name); bool sp_iterate_statement(THD *thd, const LEX_STRING label_name);
bool maybe_start_compound_statement(THD *thd);
bool sp_push_loop_label(THD *thd, LEX_STRING label_name);
bool sp_push_loop_empty_label(THD *thd);
bool sp_pop_loop_label(THD *thd, const LEX_STRING label_name);
void sp_pop_loop_empty_label(THD *thd);
// Check if "KEY IF NOT EXISTS name" used outside of ALTER context // Check if "KEY IF NOT EXISTS name" used outside of ALTER context
bool check_add_key(DDL_options_st ddl) bool check_add_key(DDL_options_st ddl)
{ {
......
...@@ -172,48 +172,6 @@ void turn_parser_debug_on() ...@@ -172,48 +172,6 @@ void turn_parser_debug_on()
#endif #endif
static bool maybe_start_compound_statement(THD *thd)
{
if (!thd->lex->sphead)
{
if (!thd->lex->make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
return 1;
Lex->sp_chistics.suid= SP_IS_NOT_SUID;
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_ptr());
}
return 0;
}
static bool push_sp_label(THD *thd, LEX_STRING label)
{
sp_pcontext *ctx= thd->lex->spcont;
sp_label *lab= ctx->find_label(label);
if (lab)
{
my_error(ER_SP_LABEL_REDEFINE, MYF(0), label.str);
return 1;
}
else
{
lab= thd->lex->spcont->push_label(thd, label,
thd->lex->sphead->instructions());
lab->type= sp_label::ITERATION;
}
return 0;
}
static bool push_sp_empty_label(THD *thd)
{
if (maybe_start_compound_statement(thd))
return 1;
/* Unlabeled controls get an empty label. */
thd->lex->spcont->push_label(thd, empty_lex_str,
thd->lex->sphead->instructions());
return 0;
}
/** /**
Helper action for a case expression statement (the expr in 'CASE expr'). Helper action for a case expression statement (the expr in 'CASE expr').
This helper is used for 'searched' cases only. This helper is used for 'searched' cases only.
...@@ -3512,7 +3470,7 @@ sp_proc_stmt_compound_ok: ...@@ -3512,7 +3470,7 @@ sp_proc_stmt_compound_ok:
sp_proc_stmt_if: sp_proc_stmt_if:
IF_SYM IF_SYM
{ {
if (maybe_start_compound_statement(thd)) if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->new_cont_backpatch(NULL); Lex->sphead->new_cont_backpatch(NULL);
} }
...@@ -3753,7 +3711,7 @@ sp_elseifs: ...@@ -3753,7 +3711,7 @@ sp_elseifs:
case_stmt_specification: case_stmt_specification:
CASE_SYM CASE_SYM
{ {
if (maybe_start_compound_statement(thd)) if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
/** /**
...@@ -3954,7 +3912,7 @@ sp_unlabeled_block: ...@@ -3954,7 +3912,7 @@ sp_unlabeled_block:
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) */
{ {
if (maybe_start_compound_statement(thd)) if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sp_block_init(thd); Lex->sp_block_init(thd);
} }
...@@ -4032,79 +3990,68 @@ repeat_body: ...@@ -4032,79 +3990,68 @@ repeat_body:
} }
; ;
pop_sp_label: pop_sp_loop_label:
sp_opt_label sp_opt_label
{ {
sp_label *lab; if (Lex->sp_pop_loop_label(thd, $1))
Lex->sphead->backpatch(lab= Lex->spcont->pop_label()); MYSQL_YYABORT;
if ($1.str)
{
if (my_strcasecmp(system_charset_info, $1.str,
lab->name.str) != 0)
my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $1.str));
}
}
;
pop_sp_empty_label:
{
sp_label *lab;
Lex->sphead->backpatch(lab= Lex->spcont->pop_label());
DBUG_ASSERT(lab->name.length == 0);
} }
; ;
sp_labeled_control: sp_labeled_control:
label_ident ':' LOOP_SYM label_ident ':' LOOP_SYM
{ {
if (push_sp_label(thd, $1)) if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
loop_body pop_sp_label loop_body pop_sp_loop_label
{ } { }
| label_ident ':' WHILE_SYM | label_ident ':' WHILE_SYM
{ {
if (push_sp_label(thd, $1)) if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->reset_lex(thd); Lex->sphead->reset_lex(thd);
} }
while_body pop_sp_label while_body pop_sp_loop_label
{ } { }
| label_ident ':' REPEAT_SYM | label_ident ':' REPEAT_SYM
{ {
if (push_sp_label(thd, $1)) if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
repeat_body pop_sp_label repeat_body pop_sp_loop_label
{ } { }
; ;
sp_unlabeled_control: sp_unlabeled_control:
LOOP_SYM LOOP_SYM
{ {
if (push_sp_empty_label(thd)) if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
loop_body loop_body
pop_sp_empty_label {
{ } Lex->sp_pop_loop_empty_label(thd);
}
| WHILE_SYM | WHILE_SYM
{ {
if (push_sp_empty_label(thd)) if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->reset_lex(thd); Lex->sphead->reset_lex(thd);
} }
while_body while_body
pop_sp_empty_label {
{ } Lex->sp_pop_loop_empty_label(thd);
}
| REPEAT_SYM | REPEAT_SYM
{ {
if (push_sp_empty_label(thd)) if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
repeat_body repeat_body
pop_sp_empty_label {
{ } Lex->sp_pop_loop_empty_label(thd);
}
; ;
trg_action_time: trg_action_time:
......
...@@ -151,49 +151,6 @@ void ORAerror(THD *thd, const char *s) ...@@ -151,49 +151,6 @@ void ORAerror(THD *thd, const char *s)
static bool maybe_start_compound_statement(THD *thd)
{
if (!thd->lex->sphead)
{
if (!thd->lex->make_sp_head(thd, NULL, TYPE_ENUM_PROCEDURE))
return 1;
Lex->sp_chistics.suid= SP_IS_NOT_SUID;
Lex->sphead->set_body_start(thd, YYLIP->get_cpp_ptr());
}
return 0;
}
static bool push_sp_label(THD *thd, LEX_STRING label)
{
sp_pcontext *ctx= thd->lex->spcont;
sp_label *lab= ctx->find_label(label);
if (lab)
{
my_error(ER_SP_LABEL_REDEFINE, MYF(0), label.str);
return 1;
}
else
{
lab= thd->lex->spcont->push_label(thd, label,
thd->lex->sphead->instructions());
lab->type= sp_label::ITERATION;
}
return 0;
}
static bool push_sp_empty_label(THD *thd)
{
if (maybe_start_compound_statement(thd))
return 1;
/* Unlabeled controls get an empty label. */
thd->lex->spcont->push_label(thd, empty_lex_str,
thd->lex->sphead->instructions());
return 0;
}
#define bincmp_collation(X,Y) \ #define bincmp_collation(X,Y) \
do \ do \
{ \ { \
...@@ -2919,7 +2876,7 @@ sp_proc_stmt_compound_ok: ...@@ -2919,7 +2876,7 @@ sp_proc_stmt_compound_ok:
sp_proc_stmt_if: sp_proc_stmt_if:
IF_SYM IF_SYM
{ {
if (maybe_start_compound_statement(thd)) if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->new_cont_backpatch(NULL); Lex->sphead->new_cont_backpatch(NULL);
} }
...@@ -3160,7 +3117,7 @@ sp_elseifs: ...@@ -3160,7 +3117,7 @@ sp_elseifs:
case_stmt_specification: case_stmt_specification:
CASE_SYM CASE_SYM
{ {
if (maybe_start_compound_statement(thd)) if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
/** /**
...@@ -3438,7 +3395,7 @@ sp_block_statements_and_exceptions: ...@@ -3438,7 +3395,7 @@ sp_block_statements_and_exceptions:
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) */
{ {
if (maybe_start_compound_statement(thd)) if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sp_block_init(thd); Lex->sp_block_init(thd);
} }
...@@ -3540,79 +3497,68 @@ repeat_body: ...@@ -3540,79 +3497,68 @@ repeat_body:
} }
; ;
pop_sp_label: pop_sp_loop_label:
sp_opt_label sp_opt_label
{ {
sp_label *lab; if (Lex->sp_pop_loop_label(thd, $1))
Lex->sphead->backpatch(lab= Lex->spcont->pop_label()); MYSQL_YYABORT;
if ($1.str)
{
if (my_strcasecmp(system_charset_info, $1.str,
lab->name.str) != 0)
my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $1.str));
}
}
;
pop_sp_empty_label:
{
sp_label *lab;
Lex->sphead->backpatch(lab= Lex->spcont->pop_label());
DBUG_ASSERT(lab->name.length == 0);
} }
; ;
sp_labeled_control: sp_labeled_control:
label_declaration_oracle LOOP_SYM label_declaration_oracle LOOP_SYM
{ {
if (push_sp_label(thd, $1)) if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
loop_body pop_sp_label loop_body pop_sp_loop_label
{ } { }
| label_declaration_oracle WHILE_SYM | label_declaration_oracle WHILE_SYM
{ {
if (push_sp_label(thd, $1)) if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->reset_lex(thd); Lex->sphead->reset_lex(thd);
} }
while_body pop_sp_label while_body pop_sp_loop_label
{ } { }
| label_declaration_oracle REPEAT_SYM | label_declaration_oracle REPEAT_SYM
{ {
if (push_sp_label(thd, $1)) if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
repeat_body pop_sp_label repeat_body pop_sp_loop_label
{ } { }
; ;
sp_unlabeled_control: sp_unlabeled_control:
LOOP_SYM LOOP_SYM
{ {
if (push_sp_empty_label(thd)) if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
loop_body loop_body
pop_sp_empty_label {
{ } Lex->sp_pop_loop_empty_label(thd);
}
| WHILE_SYM | WHILE_SYM
{ {
if (push_sp_empty_label(thd)) if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->reset_lex(thd); Lex->sphead->reset_lex(thd);
} }
while_body while_body
pop_sp_empty_label {
{ } Lex->sp_pop_loop_empty_label(thd);
}
| REPEAT_SYM | REPEAT_SYM
{ {
if (push_sp_empty_label(thd)) if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
repeat_body repeat_body
pop_sp_empty_label {
{ } Lex->sp_pop_loop_empty_label(thd);
}
; ;
trg_action_time: trg_action_time:
......
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