diff options
author | unknown <pem@mysql.com> | 2002-12-17 10:01:52 +0100 |
---|---|---|
committer | unknown <pem@mysql.com> | 2002-12-17 10:01:52 +0100 |
commit | b12330b3d9597b6da2ee8ef51765093e9de38e42 (patch) | |
tree | 469b436d3b14fa1ce75e1ba75885837f65c38b0a | |
parent | f6611aa0ab45aa5586101b34c444b8fab305fac9 (diff) | |
download | mariadb-git-b12330b3d9597b6da2ee8ef51765093e9de38e42.tar.gz |
Added parsing of CASE (both generic and "simple").
sql/sp_head.cc:
Init. the simple_case flag.
sql/sp_head.h:
New flag for (simple)case parsing.
sql/sp_pcontext.cc:
Removed push_gen_label method (not needed any more).
sql/sp_pcontext.h:
Removed push_gen_label method (not needed any more).
Fixed bug in pop().
sql/sql_yacc.yy:
Added CASE parsing.
-rw-r--r-- | sql/sp_head.cc | 1 | ||||
-rw-r--r-- | sql/sp_head.h | 2 | ||||
-rw-r--r-- | sql/sp_pcontext.cc | 14 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 5 | ||||
-rw-r--r-- | 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 @@ -107,20 +107,6 @@ sp_pcontext::push_label(char *name, uint ip) } 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) { List_iterator_fast<sp_label_t> li(m_label); 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; } @@ -120,9 +120,6 @@ class sp_pcontext : public Sql_alloc push_label(char *name, uint ip); sp_label_t * - push_gen_label(uint ip); - - sp_label_t * find_label(char *name); inline sp_label_t * 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: <caseval> = <whenval> */ + 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 ':' { |