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:
unknown 2002-12-17 10:01:52 +01:00
parent f6611aa0ab
commit b12330b3d9
5 changed files with 80 additions and 26 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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)
{

View file

@ -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);

View file

@ -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 ':'
{