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 sp_proc_stmt_leave %type sp_proc_stmt_iterate %type sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close -%type case_stmt_specification simple_case_stmt searched_case_stmt +%type case_stmt_specification %type sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list %type 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 +
+            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: