diff options
author | Alexander Barkov <bar@mariadb.org> | 2016-08-16 15:24:24 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2017-04-05 15:02:43 +0400 |
commit | f37a943f49f704bbffc536ac1e324f1f65bb8fcd (patch) | |
tree | 6ff637e35946c46df8a123b63290175bf109bc60 /sql | |
parent | 4b61495576bc240392d7aaaec38ecac8631e447c (diff) | |
download | mariadb-git-f37a943f49f704bbffc536ac1e324f1f65bb8fcd.tar.gz |
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.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sp_head.cc | 4 | ||||
-rw-r--r-- | sql/sp_head.h | 10 | ||||
-rw-r--r-- | sql/sql_lex.cc | 57 | ||||
-rw-r--r-- | sql/sql_lex.h | 4 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 79 | ||||
-rw-r--r-- | sql/sql_yacc_ora.yy | 79 |
6 files changed, 76 insertions, 157 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 1ecbc1b2e5f..d02749db030 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -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, - sp_pcontext *spcont) + sp_pcontext *spcont, + sp_label *lab) { sp_instr_jump *i= new (thd->mem_root) sp_instr_jump(instructions(), spcont); if (i == NULL || add_instr(i)) return true; - sp_label *lab= spcont->last_label(); push_backpatch(thd, i, lab); return false; } diff --git a/sql/sp_head.h b/sql/sp_head.h index b4c3cdaac6c..3d55d9e911d 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -344,7 +344,15 @@ public: add_instr_jump(THD *thd, sp_pcontext *spcont, uint dest); 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 diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index fec4e309d3f..4b346836f04 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -5449,6 +5449,63 @@ LEX::sp_block_with_exceptions_finalize_exceptions(THD *thd, 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 uint binlog_unsafe_map[256]; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ac76dddffcb..c2d1ef83959 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3151,6 +3151,10 @@ public: bool sp_block_with_exceptions_finalize_exceptions(THD *thd, uint executable_section_ip, 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 bool check_add_key(DDL_options_st ddl) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 1d637276f3d..53ab7eb14ac 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3600,90 +3600,15 @@ sp_proc_stmt_return: sp_proc_stmt_leave: LEAVE_SYM label_ident { - LEX *lex= Lex; - 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) + if (Lex->sp_leave_statement(thd, $2)) MYSQL_YYABORT; - sp->push_backpatch(thd, i, lab); /* Jumping forward */ - sp->add_instr(i); } ; sp_proc_stmt_iterate: ITERATE_SYM label_ident { - LEX *lex= Lex; - 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)) + if (Lex->sp_iterate_statement(thd, $2)) MYSQL_YYABORT; } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index ada471b880d..d003680fcc5 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -3007,90 +3007,15 @@ sp_proc_stmt_return: sp_proc_stmt_leave: LEAVE_SYM label_ident { - LEX *lex= Lex; - 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) + if (Lex->sp_leave_statement(thd, $2)) MYSQL_YYABORT; - sp->push_backpatch(thd, i, lab); /* Jumping forward */ - sp->add_instr(i); } ; sp_proc_stmt_iterate: ITERATE_SYM label_ident { - LEX *lex= Lex; - 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)) + if (Lex->sp_iterate_statement(thd, $2)) MYSQL_YYABORT; } ; |