From 58d3dda33f46348b3df51af8b3c04115d340e2b6 Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Tue, 17 Dec 2002 10:01:52 +0100 Subject: [PATCH] Added parsing of CASE (both generic and "simple"). --- sql/sp_head.cc | 1 + sql/sp_head.h | 2 ++ sql/sp_pcontext.cc | 14 -------- sql/sp_pcontext.h | 5 +-- sql/sql_yacc.yy | 84 +++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 80 insertions(+), 26 deletions(-) diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 226701bafe4..c61256e5edb 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -84,6 +84,7 @@ eval_func_item(THD *thd, Item *it, enum enum_field_types type) } sp_head::sp_head(LEX_STRING *name, LEX *lex) + : m_simple_case(FALSE) { const char *dstr = (const char*)lex->buf; diff --git a/sql/sp_head.h b/sql/sp_head.h index 097eb6718e6..f6d06b61f43 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -35,6 +35,8 @@ class sp_head : public Sql_alloc public: + my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise + static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 96296e54184..407151c3e38 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -106,20 +106,6 @@ sp_pcontext::push_label(char *name, uint ip) return lab; } -sp_label_t * -sp_pcontext::push_gen_label(uint ip) -{ - sp_label_t *lab= NULL; - char *s= my_malloc(10, MYF(MY_WME)); // 10=... - - if (s) - { - sprintf(s, ".%08x", m_genlab++); // ...9+1 - lab= push_label(s, ip); - } - return lab; -} - sp_label_t * sp_pcontext::find_label(char *name) { diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 2eb59172365..6ab38e77017 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -99,7 +99,7 @@ class sp_pcontext : public Sql_alloc inline void pop(uint num = 1) { - if (num >= m_i) + if (num < m_i) m_i -= num; } @@ -119,9 +119,6 @@ class sp_pcontext : public Sql_alloc sp_label_t * push_label(char *name, uint ip); - sp_label_t * - push_gen_label(uint ip); - sp_label_t * find_label(char *name); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3d562dcfdbe..dff59520149 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1030,7 +1030,6 @@ sp_decl_idents: } ; -/* Dummy for the spset thing. Will go away when the SET problem is fixed. */ sp_proc_stmt: { Lex->sphead->reset_lex(YYTHD); @@ -1045,13 +1044,39 @@ sp_proc_stmt: lex->sphead->restore_lex(YYTHD); } | IF sp_if END IF {} -/* | sp_case */ + | CASE_SYM WHEN_SYM + { + Lex->sphead->m_simple_case= FALSE; + } + sp_case END CASE_SYM {} + | CASE_SYM expr WHEN_SYM + { + /* We "fake" this by using an anonymous variable which we + set to the expression. Note that all WHENs are evaluate + at the same frame level, so we then know that it's the + top-most variable in the frame. */ + LEX *lex= Lex; + uint offset= lex->spcont->current_framesize(); + sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(), + offset, $2, MYSQL_TYPE_STRING); + LEX_STRING dummy; + + dummy.str= (char *)""; + dummy.length= 0; + lex->spcont->push(&dummy, MYSQL_TYPE_STRING, sp_param_in); + lex->sphead->add_instr(i); + lex->sphead->m_simple_case= TRUE; + } + sp_case END CASE_SYM + { + Lex->spcont->pop(); + } | sp_labeled_control {} | { /* Unlabeled controls get a secret label. */ LEX *lex= Lex; - lex->spcont->push_gen_label(lex->sphead->instructions()); + lex->spcont->push_label((char *)"", lex->sphead->instructions()); } sp_unlabeled_control { @@ -1127,7 +1152,7 @@ sp_if: uint ip= sp->instructions(); sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $1); - sp->push_backpatch(i, ctx->push_gen_label(0)); /* Forward only */ + sp->push_backpatch(i, ctx->push_label((char *)"", 0)); sp->add_instr(i); } sp_proc_stmts @@ -1139,15 +1164,13 @@ sp_if: sp->add_instr(i); sp->backpatch(ctx->pop_label()); - sp->push_backpatch(i, ctx->push_gen_label(0)); /* Forward only */ + sp->push_backpatch(i, ctx->push_label((char *)"", 0)); } sp_elseifs { LEX *lex= Lex; - sp_head *sp= lex->sphead; - sp_pcontext *ctx= lex->spcont; - sp->backpatch(ctx->pop_label()); + lex->sphead->backpatch(lex->spcont->pop_label()); } ; @@ -1157,6 +1180,51 @@ sp_elseifs: | ELSE sp_proc_stmts ; +sp_case: + expr THEN_SYM + { + sp_head *sp= Lex->sphead; + sp_pcontext *ctx= Lex->spcont; + uint ip= sp->instructions(); + sp_instr_jump_if_not *i; + + if (! sp->m_simple_case) + i= new sp_instr_jump_if_not(ip, $1); + else + { /* Simple case: = */ + Item *var= (Item*) new Item_splocal(ctx->current_framesize()-1); + Item *expr= Item_bool_func2::eq_creator(var, $1); + + i= new sp_instr_jump_if_not(ip, expr); + } + sp->push_backpatch(i, ctx->push_label((char *)"", 0)); + sp->add_instr(i); + } + sp_proc_stmts + { + sp_head *sp= Lex->sphead; + sp_pcontext *ctx= Lex->spcont; + uint ip= sp->instructions(); + sp_instr_jump *i = new sp_instr_jump(ip); + + sp->add_instr(i); + sp->backpatch(ctx->pop_label()); + sp->push_backpatch(i, ctx->push_label((char *)"", 0)); + } + sp_whens + { + LEX *lex= Lex; + + lex->sphead->backpatch(lex->spcont->pop_label()); + } + ; + +sp_whens: + /* Empty */ + | WHEN_SYM sp_case + | ELSE sp_proc_stmts + ; + sp_labeled_control: IDENT ':' {