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)
}
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
uint binlog_unsafe_map[256];
......
......@@ -3155,6 +3155,12 @@ struct LEX: public Query_tables_list
bool sp_leave_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
bool check_add_key(DDL_options_st ddl)
{
......
......@@ -172,48 +172,6 @@ void turn_parser_debug_on()
#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').
This helper is used for 'searched' cases only.
......@@ -3512,7 +3470,7 @@ sp_proc_stmt_compound_ok:
sp_proc_stmt_if:
IF_SYM
{
if (maybe_start_compound_statement(thd))
if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT;
Lex->sphead->new_cont_backpatch(NULL);
}
......@@ -3753,7 +3711,7 @@ sp_elseifs:
case_stmt_specification:
CASE_SYM
{
if (maybe_start_compound_statement(thd))
if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT;
/**
......@@ -3954,7 +3912,7 @@ sp_unlabeled_block:
sp_unlabeled_block_not_atomic:
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;
Lex->sp_block_init(thd);
}
......@@ -4032,79 +3990,68 @@ repeat_body:
}
;
pop_sp_label:
pop_sp_loop_label:
sp_opt_label
{
sp_label *lab;
Lex->sphead->backpatch(lab= Lex->spcont->pop_label());
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);
if (Lex->sp_pop_loop_label(thd, $1))
MYSQL_YYABORT;
}
;
sp_labeled_control:
label_ident ':' LOOP_SYM
{
if (push_sp_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
}
loop_body pop_sp_label
loop_body pop_sp_loop_label
{ }
| label_ident ':' WHILE_SYM
{
if (push_sp_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
}
while_body pop_sp_label
while_body pop_sp_loop_label
{ }
| label_ident ':' REPEAT_SYM
{
if (push_sp_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
}
repeat_body pop_sp_label
repeat_body pop_sp_loop_label
{ }
;
sp_unlabeled_control:
LOOP_SYM
{
if (push_sp_empty_label(thd))
if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
}
loop_body
pop_sp_empty_label
{ }
{
Lex->sp_pop_loop_empty_label(thd);
}
| WHILE_SYM
{
if (push_sp_empty_label(thd))
if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
}
while_body
pop_sp_empty_label
{ }
{
Lex->sp_pop_loop_empty_label(thd);
}
| REPEAT_SYM
{
if (push_sp_empty_label(thd))
if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
}
repeat_body
pop_sp_empty_label
{ }
{
Lex->sp_pop_loop_empty_label(thd);
}
;
trg_action_time:
......
......@@ -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) \
do \
{ \
......@@ -2919,7 +2876,7 @@ sp_proc_stmt_compound_ok:
sp_proc_stmt_if:
IF_SYM
{
if (maybe_start_compound_statement(thd))
if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT;
Lex->sphead->new_cont_backpatch(NULL);
}
......@@ -3160,7 +3117,7 @@ sp_elseifs:
case_stmt_specification:
CASE_SYM
{
if (maybe_start_compound_statement(thd))
if (Lex->maybe_start_compound_statement(thd))
MYSQL_YYABORT;
/**
......@@ -3438,7 +3395,7 @@ sp_block_statements_and_exceptions:
sp_unlabeled_block_not_atomic:
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;
Lex->sp_block_init(thd);
}
......@@ -3540,79 +3497,68 @@ repeat_body:
}
;
pop_sp_label:
pop_sp_loop_label:
sp_opt_label
{
sp_label *lab;
Lex->sphead->backpatch(lab= Lex->spcont->pop_label());
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);
if (Lex->sp_pop_loop_label(thd, $1))
MYSQL_YYABORT;
}
;
sp_labeled_control:
label_declaration_oracle LOOP_SYM
{
if (push_sp_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
}
loop_body pop_sp_label
loop_body pop_sp_loop_label
{ }
| label_declaration_oracle WHILE_SYM
{
if (push_sp_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
}
while_body pop_sp_label
while_body pop_sp_loop_label
{ }
| label_declaration_oracle REPEAT_SYM
{
if (push_sp_label(thd, $1))
if (Lex->sp_push_loop_label(thd, $1))
MYSQL_YYABORT;
}
repeat_body pop_sp_label
repeat_body pop_sp_loop_label
{ }
;
sp_unlabeled_control:
LOOP_SYM
{
if (push_sp_empty_label(thd))
if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
}
loop_body
pop_sp_empty_label
{ }
{
Lex->sp_pop_loop_empty_label(thd);
}
| WHILE_SYM
{
if (push_sp_empty_label(thd))
if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
Lex->sphead->reset_lex(thd);
}
while_body
pop_sp_empty_label
{ }
{
Lex->sp_pop_loop_empty_label(thd);
}
| REPEAT_SYM
{
if (push_sp_empty_label(thd))
if (Lex->sp_push_loop_empty_label(thd))
MYSQL_YYABORT;
}
repeat_body
pop_sp_empty_label
{ }
{
Lex->sp_pop_loop_empty_label(thd);
}
;
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