Commit 60475b8f authored by Sergei Golubchik's avatar Sergei Golubchik

cleanup sql_yacc.yy: rules for the CASE ... END CASE statement

parent 319f206d
...@@ -245,61 +245,6 @@ static sp_head *make_sp_head(THD *thd, sp_name *name, ...@@ -245,61 +245,6 @@ static sp_head *make_sp_head(THD *thd, sp_name *name,
} }
/**
Helper action for a case statement (entering the CASE).
This helper is used for both 'simple' and 'searched' cases.
This helper, with the other case_stmt_action_..., is executed when
the following SQL code is parsed:
<pre>
CREATE PROCEDURE proc_19194_simple(i int)
BEGIN
DECLARE str CHAR(10);
CASE i
WHEN 1 THEN SET str="1";
WHEN 2 THEN SET str="2";
WHEN 3 THEN SET str="3";
ELSE SET str="unknown";
END CASE;
SELECT str;
END
</pre>
The actions are used to generate the following code:
<pre>
SHOW PROCEDURE CODE proc_19194_simple;
Pos Instruction
0 set str@1 NULL
1 set_case_expr (12) 0 i@0
2 jump_if_not 5(12) (case_expr@0 = 1)
3 set str@1 _latin1'1'
4 jump 12
5 jump_if_not 8(12) (case_expr@0 = 2)
6 set str@1 _latin1'2'
7 jump 12
8 jump_if_not 11(12) (case_expr@0 = 3)
9 set str@1 _latin1'3'
10 jump 12
11 set str@1 _latin1'unknown'
12 stmt 0 "SELECT str"
</pre>
@param lex the parser lex context
*/
void case_stmt_action_case(LEX *lex)
{
lex->sphead->new_cont_backpatch(NULL);
/*
BACKPATCH: Creating target label for the jump to
"case_stmt_action_end_case"
(Instruction 12 in the example)
*/
lex->spcont->push_label(current_thd, empty_lex_str, lex->sphead->instructions());
}
/** /**
Helper action for a case expression statement (the expr in 'CASE expr'). Helper action for a case expression statement (the expr in 'CASE expr').
This helper is used for 'searched' cases only. This helper is used for 'searched' cases only.
...@@ -396,36 +341,13 @@ int case_stmt_action_then(LEX *lex) ...@@ -396,36 +341,13 @@ int case_stmt_action_then(LEX *lex)
/* /*
BACKPATCH: Registering forward jump from BACKPATCH: Registering forward jump from
"case_stmt_action_then" to "case_stmt_action_end_case" "case_stmt_action_then" to after END CASE
(jump from instruction 4 to 12, 7 to 12 ... in the example) (jump from instruction 4 to 12, 7 to 12 ... in the example)
*/ */
return sp->push_backpatch(i, ctx->last_label()); return sp->push_backpatch(i, ctx->last_label());
} }
/**
Helper action for an end case.
This helper is used for both 'simple' and 'searched' cases.
@param lex the parser lex context
@param simple true for simple cases, false for searched cases
*/
void case_stmt_action_end_case(LEX *lex, bool simple)
{
/*
BACKPATCH: Resolving forward jump from
"case_stmt_action_then" to "case_stmt_action_end_case"
(jump from instruction 4 to 12, 7 to 12 ... in the example)
*/
lex->sphead->backpatch(lex->spcont->pop_label());
if (simple)
lex->spcont->pop_case_expr_id();
lex->sphead->do_cont_backpatch();
}
static bool static bool
find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp) find_sys_var_null_base(THD *thd, struct sys_var_with_base *tmp)
{ {
...@@ -1706,6 +1628,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1706,6 +1628,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
optional_flush_tables_arguments opt_dyncol_type dyncol_type optional_flush_tables_arguments opt_dyncol_type dyncol_type
opt_time_precision kill_type kill_option int_num opt_time_precision kill_type kill_option int_num
opt_default_time_precision opt_default_time_precision
case_stmt_body
/* /*
Bit field of MYSQL_START_TRANS_OPT_* flags. Bit field of MYSQL_START_TRANS_OPT_* flags.
...@@ -1905,7 +1828,7 @@ END_OF_INPUT ...@@ -1905,7 +1828,7 @@ END_OF_INPUT
%type <NONE> sp_proc_stmt_leave %type <NONE> sp_proc_stmt_leave
%type <NONE> sp_proc_stmt_iterate %type <NONE> sp_proc_stmt_iterate
%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close %type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
%type <NONE> case_stmt_specification simple_case_stmt searched_case_stmt %type <NONE> case_stmt_specification
%type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list %type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value %type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
...@@ -4011,51 +3934,87 @@ sp_elseifs: ...@@ -4011,51 +3934,87 @@ sp_elseifs:
; ;
case_stmt_specification: case_stmt_specification:
simple_case_stmt
| searched_case_stmt
;
simple_case_stmt:
CASE_SYM CASE_SYM
{ {
LEX *lex= Lex;
case_stmt_action_case(lex);
lex->sphead->reset_lex(thd); /* For expr $3 */
}
expr
{
LEX *lex= Lex;
if (case_stmt_action_expr(lex, $3))
MYSQL_YYABORT;
/* For expr $3 */ /**
if (lex->sphead->restore_lex(thd)) An example of the CASE statement in use is
MYSQL_YYABORT; <pre>
CREATE PROCEDURE proc_19194_simple(i int)
BEGIN
DECLARE str CHAR(10);
CASE i
WHEN 1 THEN SET str="1";
WHEN 2 THEN SET str="2";
WHEN 3 THEN SET str="3";
ELSE SET str="unknown";
END CASE;
SELECT str;
END
</pre>
The actions are used to generate the following code:
<pre>
SHOW PROCEDURE CODE proc_19194_simple;
Pos Instruction
0 set str@1 NULL
1 set_case_expr (12) 0 i@0
2 jump_if_not 5(12) (case_expr@0 = 1)
3 set str@1 _latin1'1'
4 jump 12
5 jump_if_not 8(12) (case_expr@0 = 2)
6 set str@1 _latin1'2'
7 jump 12
8 jump_if_not 11(12) (case_expr@0 = 3)
9 set str@1 _latin1'3'
10 jump 12
11 set str@1 _latin1'unknown'
12 stmt 0 "SELECT str"
</pre>
*/
Lex->sphead->new_cont_backpatch(NULL);
/*
BACKPATCH: Creating target label for the jump to after END CASE
(instruction 12 in the example)
*/
Lex->spcont->push_label(current_thd, empty_lex_str, Lex->sphead->instructions());
} }
simple_when_clause_list case_stmt_body
else_clause_opt else_clause_opt
END END
CASE_SYM CASE_SYM
{ {
LEX *lex= Lex; /*
case_stmt_action_end_case(lex, true); BACKPATCH: Resolving forward jump from
"case_stmt_action_then" to after END CASE
(jump from instruction 4 to 12, 7 to 12 ... in the example)
*/
Lex->sphead->backpatch(Lex->spcont->pop_label());
if ($3)
Lex->spcont->pop_case_expr_id();
Lex->sphead->do_cont_backpatch();
} }
; ;
searched_case_stmt: case_stmt_body:
CASE_SYM { Lex->sphead->reset_lex(thd); /* For expr $2 */ }
{ expr
LEX *lex= Lex;
case_stmt_action_case(lex);
}
searched_when_clause_list
else_clause_opt
END
CASE_SYM
{ {
LEX *lex= Lex; if (case_stmt_action_expr(Lex, $2))
case_stmt_action_end_case(lex, false); MYSQL_YYABORT;
if (Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
} }
simple_when_clause_list
{ $$= 1; }
| searched_when_clause_list
{ $$= 0; }
; ;
simple_when_clause_list: simple_when_clause_list:
......
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