Commit b12330b3 authored by unknown's avatar unknown

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.
parent f6611aa0
......@@ -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;
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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 ':'
{
......
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