summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2016-08-16 15:24:24 +0400
committerAlexander Barkov <bar@mariadb.org>2017-04-05 15:02:43 +0400
commitf37a943f49f704bbffc536ac1e324f1f65bb8fcd (patch)
tree6ff637e35946c46df8a123b63290175bf109bc60 /sql
parent4b61495576bc240392d7aaaec38ecac8631e447c (diff)
downloadmariadb-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.cc4
-rw-r--r--sql/sp_head.h10
-rw-r--r--sql/sql_lex.cc57
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_yacc.yy79
-rw-r--r--sql/sql_yacc_ora.yy79
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;
}
;