diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 7b5e0c8f1ee..a53543c993e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -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: -
-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 -- The actions are used to generate the following code: -
-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" -- - @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
+ 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 ++ The actions are used to generate the following code: +
+ 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" ++ */ + + 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: