mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
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.
This commit is contained in:
parent
f6611aa0ab
commit
b12330b3d9
5 changed files with 80 additions and 26 deletions
|
@ -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 ':'
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue