summaryrefslogtreecommitdiff
path: root/sql/sql_yacc.yy
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_yacc.yy')
-rw-r--r--sql/sql_yacc.yy147
1 files changed, 129 insertions, 18 deletions
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 751125c9fe8..498fb1b7fcf 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -611,6 +611,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CURSOR_SYM
%token ELSEIF_SYM
%token ITERATE_SYM
+%token GOTO_SYM
+%token LABEL_SYM
%token LEAVE_SYM
%token LOOP_SYM
%token REPEAT_SYM
@@ -1180,13 +1182,16 @@ create:
sp_proc_stmt
{
LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
- lex->sphead->init_strings(YYTHD, lex, $3);
+ if (sp->check_backpatch(YYTHD))
+ YYABORT;
+ sp->init_strings(YYTHD, lex, $3);
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
/* Restore flag if it was cleared above */
- if (lex->sphead->m_old_cmq)
+ if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
- lex->sphead->restore_thd_mem_root(YYTHD);
+ sp->restore_thd_mem_root(YYTHD);
}
| CREATE or_replace algorithm VIEW_SYM table_ident
{
@@ -1286,6 +1291,8 @@ create_function_tail:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
+ if (sp->check_backpatch(YYTHD))
+ YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(YYTHD, lex, lex->spname);
/* Restore flag if it was cleared above */
@@ -1816,7 +1823,8 @@ sp_proc_stmt:
{
LEX *lex= Lex;
sp_head *sp = lex->sphead;
- sp_label_t *lab= lex->spcont->find_label($2.str);
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *lab= ctx->find_label($2.str);
if (! lab)
{
@@ -1825,8 +1833,20 @@ sp_proc_stmt:
}
else
{
- sp_instr_jump *i= new sp_instr_jump(sp->instructions());
-
+ uint ip= sp->instructions();
+ sp_scope_t sdiff;
+ sp_instr_jump *i;
+ sp_instr_hpop *ih;
+ sp_instr_cpop *ic;
+
+ ctx->diff_scopes(0, &sdiff);
+ ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
+ sp->push_backpatch(ih, lab);
+ sp->add_instr(ih);
+ ic= new sp_instr_cpop(ip++, sdiff.curs);
+ sp->push_backpatch(ic, lab);
+ sp->add_instr(ic);
+ i= new sp_instr_jump(ip);
sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i);
}
@@ -1834,19 +1854,101 @@ sp_proc_stmt:
| ITERATE_SYM IDENT
{
LEX *lex= Lex;
- sp_label_t *lab= lex->spcont->find_label($2.str);
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *lab= ctx->find_label($2.str);
- if (! lab || lab->isbegin)
+ if (! lab || lab->type != SP_LAB_ITER)
{
net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "ITERATE", $2.str);
YYABORT;
}
else
{
- uint ip= lex->sphead->instructions();
- sp_instr_jump *i= new sp_instr_jump(ip, lab->ip); /* Jump back */
+ sp_instr_jump *i;
+ uint ip= sp->instructions();
+ sp_scope_t sdiff;
+
+ ctx->diff_scopes(lab->scopes, &sdiff);
+ if (sdiff.hndlrs)
+ sp->add_instr(new sp_instr_hpop(ip++, sdiff.hndlrs));
+ if (sdiff.curs)
+ sp->add_instr(new sp_instr_cpop(ip++, sdiff.curs));
+ i= new sp_instr_jump(ip, lab->ip); /* Jump back */
+ sp->add_instr(i);
+ }
+ }
+ | LABEL_SYM IDENT
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *lab= ctx->find_label($2.str);
- lex->sphead->add_instr(i);
+ if (! lab)
+ lab= ctx->find_glabel($2.str);
+ if (lab)
+ {
+ net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $2.str);
+ YYABORT;
+ }
+ else
+ {
+ lab= ctx->push_glabel($2.str, sp->instructions());
+ lab->type= SP_LAB_GOTO;
+ lab->scopes= ctx->scopes();
+ sp->backpatch(lab);
+ }
+ }
+ | GOTO_SYM IDENT
+ {
+ LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
+ sp_pcontext *ctx= lex->spcont;
+ uint ip= lex->sphead->instructions();
+ sp_label_t *lab= ctx->find_label($2.str);
+ sp_scope_t sdiff;
+ sp_instr_jump *i;
+ sp_instr_hpop *ih;
+ sp_instr_cpop *ic;
+
+ if (! lab)
+ lab= ctx->find_glabel($2.str);
+
+ if (! lab)
+ {
+ lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t));
+ lab->name= $2.str;
+ lab->ip= 0;
+ lab->type= SP_LAB_REF;
+ lab->scopes= 0;
+
+ ctx->diff_scopes(0, &sdiff);
+ ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
+ sp->push_backpatch(ih, lab);
+ sp->add_instr(ih);
+ ic= new sp_instr_cpop(ip++, sdiff.curs);
+ sp->add_instr(ic);
+ sp->push_backpatch(ic, lab);
+ i= new sp_instr_jump(ip);
+ sp->push_backpatch(i, lab); /* Jumping forward */
+ sp->add_instr(i);
+ }
+ else
+ {
+ ctx->diff_scopes(lab->scopes, &sdiff);
+ if (sdiff.hndlrs)
+ {
+ ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
+ sp->add_instr(ih);
+ }
+ if (sdiff.curs)
+ {
+ ic= new sp_instr_cpop(ip++, sdiff.curs);
+ sp->add_instr(ic);
+ }
+ i= new sp_instr_jump(ip, lab->ip); /* Jump back */
+ sp->add_instr(i);
}
}
| OPEN_SYM ident
@@ -2041,7 +2143,8 @@ sp_labeled_control:
IDENT ':'
{
LEX *lex= Lex;
- sp_label_t *lab= lex->spcont->find_label($1.str);
+ sp_pcontext *ctx= lex->spcont;
+ sp_label_t *lab= ctx->find_label($1.str);
if (lab)
{
@@ -2050,8 +2153,10 @@ sp_labeled_control:
}
else
{
- lex->spcont->push_label($1.str,
- lex->sphead->instructions());
+ lab= lex->spcont->push_label($1.str,
+ lex->sphead->instructions());
+ lab->type= SP_LAB_ITER;
+ lab->scopes= ctx->scopes();
}
}
sp_unlabeled_control sp_opt_label
@@ -2088,27 +2193,33 @@ sp_unlabeled_control:
LEX *lex= Lex;
sp_label_t *lab= lex->spcont->last_label();
- lab->isbegin= TRUE;
+ lab->type= SP_LAB_BEGIN;
/* Scope duplicate checking */
lex->spcont->push_scope();
}
sp_decls
+ {
+ Lex->spcont->push_handlers($3.hndlrs);
+ }
sp_proc_stmts
END
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
+ sp_scope_t scope;
- sp->backpatch(ctx->last_label()); /* We always has a label */
+ sp->backpatch(ctx->last_label()); /* We always have a label */
ctx->pop_pvar($3.vars);
ctx->pop_cond($3.conds);
+ ctx->pop_handlers($3.hndlrs);
ctx->pop_cursor($3.curs);
if ($3.hndlrs)
- sp->add_instr(new sp_instr_hpop(sp->instructions(),$3.hndlrs));
+ sp->add_instr(new sp_instr_hpop(sp->instructions(), $3.hndlrs));
if ($3.curs)
sp->add_instr(new sp_instr_cpop(sp->instructions(), $3.curs));
- ctx->pop_scope();
+ ctx->pop_scope(&scope);
+ ctx->pop_glabel(scope.glab);
}
| LOOP_SYM
sp_proc_stmts END LOOP_SYM