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,
}
/**
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').
This helper is used for 'searched' cases only.
......@@ -396,36 +341,13 @@ int case_stmt_action_then(LEX *lex)
/*
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)
*/
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
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);
optional_flush_tables_arguments opt_dyncol_type dyncol_type
opt_time_precision kill_type kill_option int_num
opt_default_time_precision
case_stmt_body
/*
Bit field of MYSQL_START_TRANS_OPT_* flags.
......@@ -1905,7 +1828,7 @@ END_OF_INPUT
%type <NONE> sp_proc_stmt_leave
%type <NONE> sp_proc_stmt_iterate
%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 <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
......@@ -4011,51 +3934,87 @@ sp_elseifs:
;
case_stmt_specification:
simple_case_stmt
| searched_case_stmt
;
simple_case_stmt:
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))
MYSQL_YYABORT;
/**
An example of the CASE statement in use is
<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
END
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_SYM
{
LEX *lex= Lex;
case_stmt_action_case(lex);
}
searched_when_clause_list
else_clause_opt
END
CASE_SYM
case_stmt_body:
{ Lex->sphead->reset_lex(thd); /* For expr $2 */ }
expr
{
LEX *lex= Lex;
case_stmt_action_end_case(lex, false);
if (case_stmt_action_expr(Lex, $2))
MYSQL_YYABORT;
if (Lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
simple_when_clause_list
{ $$= 1; }
| searched_when_clause_list
{ $$= 0; }
;
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