summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <pem@mysql.com>2002-12-17 10:01:52 +0100
committerunknown <pem@mysql.com>2002-12-17 10:01:52 +0100
commitb12330b3d9597b6da2ee8ef51765093e9de38e42 (patch)
tree469b436d3b14fa1ce75e1ba75885837f65c38b0a
parentf6611aa0ab45aa5586101b34c444b8fab305fac9 (diff)
downloadmariadb-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.cc1
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sp_pcontext.cc14
-rw-r--r--sql/sp_pcontext.h5
-rw-r--r--sql/sql_yacc.yy84
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 ':'
{