mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-10411 Providing compatibility for basic PL/SQL constructs
Moving the code from *.yy to methods: LEX::sp_change_context() LEX::sp_leave_statement() LEX::sp_iterate_statement() to reuse the same code between LEAVE and ITERATE statements. EXIT statement will also reuse the same code.
This commit is contained in:
@@ -2571,12 +2571,12 @@ bool sp_head::add_instr_jump(THD *thd, sp_pcontext *spcont, uint dest)
|
|||||||
|
|
||||||
|
|
||||||
bool sp_head::add_instr_jump_forward_with_backpatch(THD *thd,
|
bool sp_head::add_instr_jump_forward_with_backpatch(THD *thd,
|
||||||
sp_pcontext *spcont)
|
sp_pcontext *spcont,
|
||||||
|
sp_label *lab)
|
||||||
{
|
{
|
||||||
sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(instructions(), spcont);
|
sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(instructions(), spcont);
|
||||||
if (i == NULL || add_instr(i))
|
if (i == NULL || add_instr(i))
|
||||||
return true;
|
return true;
|
||||||
sp_label *lab= spcont->last_label();
|
|
||||||
push_backpatch(thd, i, lab);
|
push_backpatch(thd, i, lab);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -344,7 +344,15 @@ public:
|
|||||||
add_instr_jump(THD *thd, sp_pcontext *spcont, uint dest);
|
add_instr_jump(THD *thd, sp_pcontext *spcont, uint dest);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
add_instr_jump_forward_with_backpatch(THD *thd, sp_pcontext *spcont);
|
add_instr_jump_forward_with_backpatch(THD *thd, sp_pcontext *spcont,
|
||||||
|
sp_label *lab);
|
||||||
|
bool
|
||||||
|
add_instr_jump_forward_with_backpatch(THD *thd, sp_pcontext *spcont)
|
||||||
|
{
|
||||||
|
return add_instr_jump_forward_with_backpatch(thd, spcont,
|
||||||
|
spcont->last_label());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns true if any substatement in the routine directly
|
Returns true if any substatement in the routine directly
|
||||||
|
@@ -5449,6 +5449,63 @@ LEX::sp_block_with_exceptions_finalize_exceptions(THD *thd,
|
|||||||
return sphead->add_instr_jump(thd, spcont, executable_section_ip);
|
return sphead->add_instr_jump(thd, spcont, executable_section_ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive)
|
||||||
|
{
|
||||||
|
uint n;
|
||||||
|
uint ip= sphead->instructions();
|
||||||
|
if ((n= spcont->diff_handlers(ctx, exclusive)))
|
||||||
|
{
|
||||||
|
sp_instr_hpop *hpop= new (thd->mem_root) sp_instr_hpop(ip++, spcont, n);
|
||||||
|
if (hpop == NULL || sphead->add_instr(hpop))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((n= spcont->diff_cursors(ctx, exclusive)))
|
||||||
|
{
|
||||||
|
sp_instr_cpop *cpop= new (thd->mem_root) sp_instr_cpop(ip++, spcont, n);
|
||||||
|
if (cpop == NULL || sphead->add_instr(cpop))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_leave_statement(THD *thd, const LEX_STRING label_name)
|
||||||
|
{
|
||||||
|
sp_label *lab= spcont->find_label(label_name);
|
||||||
|
if (!lab)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", label_name.str);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
When jumping to a BEGIN-END block end, the target jump
|
||||||
|
points to the block hpop/cpop cleanup instructions,
|
||||||
|
so we should exclude the block context here.
|
||||||
|
When jumping to something else (i.e., SP_LAB_ITER),
|
||||||
|
there are no hpop/cpop at the jump destination,
|
||||||
|
so we should include the block context here for cleanup.
|
||||||
|
*/
|
||||||
|
bool exclusive= (lab->type == sp_label::BEGIN);
|
||||||
|
return sp_change_context(thd, lab->ctx, exclusive) ||
|
||||||
|
sphead->add_instr_jump_forward_with_backpatch(thd, spcont, lab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name)
|
||||||
|
{
|
||||||
|
sp_label *lab= spcont->find_label(label_name);
|
||||||
|
if (!lab || lab->type != sp_label::ITERATION)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", label_name.str);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return sp_change_context(thd, lab->ctx, false) ||
|
||||||
|
sphead->add_instr_jump(thd, spcont, lab->ip); /* Jump back */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
uint binlog_unsafe_map[256];
|
uint binlog_unsafe_map[256];
|
||||||
|
|
||||||
|
@@ -3151,6 +3151,10 @@ public:
|
|||||||
bool sp_block_with_exceptions_finalize_exceptions(THD *thd,
|
bool sp_block_with_exceptions_finalize_exceptions(THD *thd,
|
||||||
uint executable_section_ip,
|
uint executable_section_ip,
|
||||||
uint exception_count);
|
uint exception_count);
|
||||||
|
bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive);
|
||||||
|
bool sp_leave_statement(THD *thd, const LEX_STRING label_name);
|
||||||
|
bool sp_iterate_statement(THD *thd, const LEX_STRING label_name);
|
||||||
|
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
|
@@ -3600,90 +3600,15 @@ sp_proc_stmt_return:
|
|||||||
sp_proc_stmt_leave:
|
sp_proc_stmt_leave:
|
||||||
LEAVE_SYM label_ident
|
LEAVE_SYM label_ident
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
if (Lex->sp_leave_statement(thd, $2))
|
||||||
sp_head *sp = lex->sphead;
|
|
||||||
sp_pcontext *ctx= lex->spcont;
|
|
||||||
sp_label *lab= ctx->find_label($2);
|
|
||||||
|
|
||||||
if (! lab)
|
|
||||||
my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str));
|
|
||||||
|
|
||||||
sp_instr_jump *i;
|
|
||||||
uint ip= sp->instructions();
|
|
||||||
uint n;
|
|
||||||
/*
|
|
||||||
When jumping to a BEGIN-END block end, the target jump
|
|
||||||
points to the block hpop/cpop cleanup instructions,
|
|
||||||
so we should exclude the block context here.
|
|
||||||
When jumping to something else (i.e., SP_LAB_ITER),
|
|
||||||
there are no hpop/cpop at the jump destination,
|
|
||||||
so we should include the block context here for cleanup.
|
|
||||||
*/
|
|
||||||
bool exclusive= (lab->type == sp_label::BEGIN);
|
|
||||||
|
|
||||||
n= ctx->diff_handlers(lab->ctx, exclusive);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
sp_instr_hpop *hpop= new (thd->mem_root)
|
|
||||||
sp_instr_hpop(ip++, ctx, n);
|
|
||||||
if (hpop == NULL)
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
sp->add_instr(hpop);
|
|
||||||
}
|
|
||||||
n= ctx->diff_cursors(lab->ctx, exclusive);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
sp_instr_cpop *cpop= new (thd->mem_root)
|
|
||||||
sp_instr_cpop(ip++, ctx, n);
|
|
||||||
if (cpop == NULL)
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
sp->add_instr(cpop);
|
|
||||||
}
|
|
||||||
i= new (thd->mem_root) sp_instr_jump(ip, ctx);
|
|
||||||
if (i == NULL)
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
sp->push_backpatch(thd, i, lab); /* Jumping forward */
|
|
||||||
sp->add_instr(i);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
sp_proc_stmt_iterate:
|
sp_proc_stmt_iterate:
|
||||||
ITERATE_SYM label_ident
|
ITERATE_SYM label_ident
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
if (Lex->sp_iterate_statement(thd, $2))
|
||||||
sp_head *sp= lex->sphead;
|
|
||||||
sp_pcontext *ctx= lex->spcont;
|
|
||||||
sp_label *lab= ctx->find_label($2);
|
|
||||||
|
|
||||||
if (! lab || lab->type != sp_label::ITERATION)
|
|
||||||
my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str));
|
|
||||||
|
|
||||||
sp_instr_jump *i;
|
|
||||||
uint ip= sp->instructions();
|
|
||||||
uint n;
|
|
||||||
|
|
||||||
n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
sp_instr_hpop *hpop= new (thd->mem_root)
|
|
||||||
sp_instr_hpop(ip++, ctx, n);
|
|
||||||
if (hpop == NULL ||
|
|
||||||
sp->add_instr(hpop))
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
sp_instr_cpop *cpop= new (thd->mem_root)
|
|
||||||
sp_instr_cpop(ip++, ctx, n);
|
|
||||||
if (cpop == NULL ||
|
|
||||||
sp->add_instr(cpop))
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
i= new (thd->mem_root)
|
|
||||||
sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
|
|
||||||
if (i == NULL ||
|
|
||||||
sp->add_instr(i))
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@@ -3007,90 +3007,15 @@ sp_proc_stmt_return:
|
|||||||
sp_proc_stmt_leave:
|
sp_proc_stmt_leave:
|
||||||
LEAVE_SYM label_ident
|
LEAVE_SYM label_ident
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
if (Lex->sp_leave_statement(thd, $2))
|
||||||
sp_head *sp = lex->sphead;
|
|
||||||
sp_pcontext *ctx= lex->spcont;
|
|
||||||
sp_label *lab= ctx->find_label($2);
|
|
||||||
|
|
||||||
if (! lab)
|
|
||||||
my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str));
|
|
||||||
|
|
||||||
sp_instr_jump *i;
|
|
||||||
uint ip= sp->instructions();
|
|
||||||
uint n;
|
|
||||||
/*
|
|
||||||
When jumping to a BEGIN-END block end, the target jump
|
|
||||||
points to the block hpop/cpop cleanup instructions,
|
|
||||||
so we should exclude the block context here.
|
|
||||||
When jumping to something else (i.e., SP_LAB_ITER),
|
|
||||||
there are no hpop/cpop at the jump destination,
|
|
||||||
so we should include the block context here for cleanup.
|
|
||||||
*/
|
|
||||||
bool exclusive= (lab->type == sp_label::BEGIN);
|
|
||||||
|
|
||||||
n= ctx->diff_handlers(lab->ctx, exclusive);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
sp_instr_hpop *hpop= new (thd->mem_root)
|
|
||||||
sp_instr_hpop(ip++, ctx, n);
|
|
||||||
if (hpop == NULL)
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
sp->add_instr(hpop);
|
|
||||||
}
|
|
||||||
n= ctx->diff_cursors(lab->ctx, exclusive);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
sp_instr_cpop *cpop= new (thd->mem_root)
|
|
||||||
sp_instr_cpop(ip++, ctx, n);
|
|
||||||
if (cpop == NULL)
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
sp->add_instr(cpop);
|
|
||||||
}
|
|
||||||
i= new (thd->mem_root) sp_instr_jump(ip, ctx);
|
|
||||||
if (i == NULL)
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
sp->push_backpatch(thd, i, lab); /* Jumping forward */
|
|
||||||
sp->add_instr(i);
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
sp_proc_stmt_iterate:
|
sp_proc_stmt_iterate:
|
||||||
ITERATE_SYM label_ident
|
ITERATE_SYM label_ident
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
if (Lex->sp_iterate_statement(thd, $2))
|
||||||
sp_head *sp= lex->sphead;
|
|
||||||
sp_pcontext *ctx= lex->spcont;
|
|
||||||
sp_label *lab= ctx->find_label($2);
|
|
||||||
|
|
||||||
if (! lab || lab->type != sp_label::ITERATION)
|
|
||||||
my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str));
|
|
||||||
|
|
||||||
sp_instr_jump *i;
|
|
||||||
uint ip= sp->instructions();
|
|
||||||
uint n;
|
|
||||||
|
|
||||||
n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
sp_instr_hpop *hpop= new (thd->mem_root)
|
|
||||||
sp_instr_hpop(ip++, ctx, n);
|
|
||||||
if (hpop == NULL ||
|
|
||||||
sp->add_instr(hpop))
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
sp_instr_cpop *cpop= new (thd->mem_root)
|
|
||||||
sp_instr_cpop(ip++, ctx, n);
|
|
||||||
if (cpop == NULL ||
|
|
||||||
sp->add_instr(cpop))
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
i= new (thd->mem_root)
|
|
||||||
sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
|
|
||||||
if (i == NULL ||
|
|
||||||
sp->add_instr(i))
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
Reference in New Issue
Block a user