Commit 58d3dda3 authored by pem@mysql.com's avatar pem@mysql.com

Added parsing of CASE (both generic and "simple").

parent b1593c9a
...@@ -84,6 +84,7 @@ eval_func_item(THD *thd, Item *it, enum enum_field_types type) ...@@ -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) sp_head::sp_head(LEX_STRING *name, LEX *lex)
: m_simple_case(FALSE)
{ {
const char *dstr = (const char*)lex->buf; const char *dstr = (const char*)lex->buf;
......
...@@ -35,6 +35,8 @@ class sp_head : public Sql_alloc ...@@ -35,6 +35,8 @@ class sp_head : public Sql_alloc
public: public:
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
static void *operator new(size_t size) static void *operator new(size_t size)
{ {
return (void*) sql_alloc((uint) size); return (void*) sql_alloc((uint) size);
......
...@@ -106,20 +106,6 @@ sp_pcontext::push_label(char *name, uint ip) ...@@ -106,20 +106,6 @@ sp_pcontext::push_label(char *name, uint ip)
return lab; 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_label_t *
sp_pcontext::find_label(char *name) sp_pcontext::find_label(char *name)
{ {
......
...@@ -99,7 +99,7 @@ class sp_pcontext : public Sql_alloc ...@@ -99,7 +99,7 @@ class sp_pcontext : public Sql_alloc
inline void inline void
pop(uint num = 1) pop(uint num = 1)
{ {
if (num >= m_i) if (num < m_i)
m_i -= num; m_i -= num;
} }
...@@ -119,9 +119,6 @@ class sp_pcontext : public Sql_alloc ...@@ -119,9 +119,6 @@ class sp_pcontext : public Sql_alloc
sp_label_t * sp_label_t *
push_label(char *name, uint ip); push_label(char *name, uint ip);
sp_label_t *
push_gen_label(uint ip);
sp_label_t * sp_label_t *
find_label(char *name); find_label(char *name);
......
...@@ -1030,7 +1030,6 @@ sp_decl_idents: ...@@ -1030,7 +1030,6 @@ sp_decl_idents:
} }
; ;
/* Dummy for the spset thing. Will go away when the SET problem is fixed. */
sp_proc_stmt: sp_proc_stmt:
{ {
Lex->sphead->reset_lex(YYTHD); Lex->sphead->reset_lex(YYTHD);
...@@ -1045,13 +1044,39 @@ sp_proc_stmt: ...@@ -1045,13 +1044,39 @@ sp_proc_stmt:
lex->sphead->restore_lex(YYTHD); lex->sphead->restore_lex(YYTHD);
} }
| IF sp_if END IF {} | 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 | sp_labeled_control
{} {}
| { /* Unlabeled controls get a secret label. */ | { /* Unlabeled controls get a secret label. */
LEX *lex= Lex; LEX *lex= Lex;
lex->spcont->push_gen_label(lex->sphead->instructions()); lex->spcont->push_label((char *)"", lex->sphead->instructions());
} }
sp_unlabeled_control sp_unlabeled_control
{ {
...@@ -1127,7 +1152,7 @@ sp_if: ...@@ -1127,7 +1152,7 @@ sp_if:
uint ip= sp->instructions(); uint ip= sp->instructions();
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $1); 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->add_instr(i);
} }
sp_proc_stmts sp_proc_stmts
...@@ -1139,15 +1164,13 @@ sp_if: ...@@ -1139,15 +1164,13 @@ sp_if:
sp->add_instr(i); sp->add_instr(i);
sp->backpatch(ctx->pop_label()); 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 sp_elseifs
{ {
LEX *lex= Lex; 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: ...@@ -1157,6 +1180,51 @@ sp_elseifs:
| ELSE sp_proc_stmts | 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: sp_labeled_control:
IDENT ':' IDENT ':'
{ {
......
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