mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Fixed bugs in the parameter evaluation and modified the execution engine
for better jump support. Some flow control support added too (but not complete).
This commit is contained in:
10
sql/lex.h
10
sql/lex.h
@@ -59,6 +59,7 @@ static SYMBOL symbols[] = {
|
||||
{ "ANY", SYM(ANY_SYM),0,0},
|
||||
{ "AS", SYM(AS),0,0},
|
||||
{ "ASC", SYM(ASC),0,0},
|
||||
{ "ASENSITIVE", SYM(ASENSITIVE_SYM),0,0},
|
||||
{ "AVG", SYM(AVG_SYM),0,0},
|
||||
{ "AVG_ROW_LENGTH", SYM(AVG_ROW_LENGTH),0,0},
|
||||
{ "AUTO_INCREMENT", SYM(AUTO_INC),0,0},
|
||||
@@ -107,6 +108,7 @@ static SYMBOL symbols[] = {
|
||||
{ "CURRENT_DATE", SYM(CURDATE),0,0},
|
||||
{ "CURRENT_TIME", SYM(CURTIME),0,0},
|
||||
{ "CURRENT_TIMESTAMP", SYM(NOW_SYM),0,0},
|
||||
{ "CURSOR", SYM(CURSOR_SYM),0,0},
|
||||
{ "DATA", SYM(DATA_SYM),0,0},
|
||||
{ "DATABASE", SYM(DATABASE),0,0},
|
||||
{ "DATABASES", SYM(DATABASES),0,0},
|
||||
@@ -141,6 +143,7 @@ static SYMBOL symbols[] = {
|
||||
{ "ERRORS", SYM(ERRORS),0,0},
|
||||
{ "END", SYM(END),0,0},
|
||||
{ "ELSE", SYM(ELSE),0,0},
|
||||
{ "ELSEIF", SYM(ELSEIF_SYM),0,0},
|
||||
{ "ESCAPE", SYM(ESCAPE_SYM),0,0},
|
||||
{ "ESCAPED", SYM(ESCAPED),0,0},
|
||||
{ "ENABLE", SYM(ENABLE_SYM),0,0},
|
||||
@@ -196,6 +199,7 @@ static SYMBOL symbols[] = {
|
||||
{ "INNOBASE", SYM(INNOBASE_SYM),0,0},
|
||||
{ "INNODB", SYM(INNOBASE_SYM),0,0},
|
||||
{ "INOUT", SYM(INOUT_SYM),0,0},
|
||||
{ "INSENSITIVE", SYM(INSENSITIVE_SYM),0,0},
|
||||
{ "INSERT", SYM(INSERT),0,0},
|
||||
{ "INSERT_METHOD", SYM(INSERT_METHOD),0,0},
|
||||
{ "INT", SYM(INT_SYM),0,0},
|
||||
@@ -213,12 +217,14 @@ static SYMBOL symbols[] = {
|
||||
{ "ISOLATION", SYM(ISOLATION),0,0},
|
||||
{ "ISAM", SYM(ISAM_SYM),0,0},
|
||||
{ "ISSUER", SYM(ISSUER_SYM),0,0},
|
||||
{ "ITERATE", SYM(ITERATE_SYM),0,0},
|
||||
{ "JOIN", SYM(JOIN_SYM),0,0},
|
||||
{ "KEY", SYM(KEY_SYM),0,0},
|
||||
{ "KEYS", SYM(KEYS),0,0},
|
||||
{ "KILL", SYM(KILL_SYM),0,0},
|
||||
{ "LAST", SYM(LAST_SYM),0,0},
|
||||
{ "LEADING", SYM(LEADING),0,0},
|
||||
{ "LEAVE", SYM(LEAVE_SYM),0,0},
|
||||
{ "LEFT", SYM(LEFT),0,0},
|
||||
{ "LEVEL", SYM(LEVEL_SYM),0,0},
|
||||
{ "LIKE", SYM(LIKE),0,0},
|
||||
@@ -233,6 +239,7 @@ static SYMBOL symbols[] = {
|
||||
{ "LOGS", SYM(LOGS_SYM),0,0},
|
||||
{ "LONG", SYM(LONG_SYM),0,0},
|
||||
{ "LONGBLOB", SYM(LONGBLOB),0,0},
|
||||
{ "LOOP", SYM(LOOP_SYM),0,0},
|
||||
{ "LONGTEXT", SYM(LONGTEXT),0,0},
|
||||
{ "LOW_PRIORITY", SYM(LOW_PRIORITY),0,0},
|
||||
{ "MASTER", SYM(MASTER_SYM),0,0},
|
||||
@@ -313,6 +320,7 @@ static SYMBOL symbols[] = {
|
||||
{ "REPEATABLE", SYM(REPEATABLE_SYM),0,0},
|
||||
{ "REQUIRE", SYM(REQUIRE_SYM),0,0},
|
||||
{ "RESET", SYM(RESET_SYM),0,0},
|
||||
{ "UNTIL", SYM(UNTIL_SYM),0,0},
|
||||
{ "USER_RESOURCES", SYM(RESOURCES),0,0},
|
||||
{ "RESTORE", SYM(RESTORE_SYM),0,0},
|
||||
{ "RESTRICT", SYM(RESTRICT),0,0},
|
||||
@@ -327,6 +335,7 @@ static SYMBOL symbols[] = {
|
||||
{ "RTREE", SYM(RTREE_SYM),0,0},
|
||||
{ "SECOND", SYM(SECOND_SYM),0,0},
|
||||
{ "SELECT", SYM(SELECT_SYM),0,0},
|
||||
{ "SENSITIVE", SYM(SENSITIVE_SYM),0,0},
|
||||
{ "SERIAL", SYM(SERIAL_SYM),0,0},
|
||||
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0},
|
||||
{ "SESSION", SYM(SESSION_SYM),0,0},
|
||||
@@ -401,6 +410,7 @@ static SYMBOL symbols[] = {
|
||||
{ "WRITE", SYM(WRITE_SYM),0,0},
|
||||
{ "WHEN", SYM(WHEN_SYM),0,0},
|
||||
{ "WHERE", SYM(WHERE),0,0},
|
||||
{ "WHILE", SYM(WHILE_SYM),0,0},
|
||||
{ "XOR", SYM(XOR),0,0},
|
||||
{ "X509", SYM(X509_SYM),0,0},
|
||||
{ "YEAR", SYM(YEAR_SYM),0,0},
|
||||
|
||||
@@ -59,9 +59,9 @@ eval_func_item(Item *it, enum enum_field_types type)
|
||||
{
|
||||
char buffer[MAX_FIELD_WIDTH];
|
||||
String tmp(buffer, sizeof(buffer), default_charset_info);
|
||||
String *s= it->val_str(&tmp);
|
||||
|
||||
(void)it->val_str(&tmp);
|
||||
it= new Item_string(buffer, sizeof(buffer), default_charset_info);
|
||||
it= new Item_string(s->c_ptr_quick(), s->length(), default_charset_info);
|
||||
break;
|
||||
}
|
||||
case MYSQL_TYPE_NULL:
|
||||
@@ -149,15 +149,21 @@ sp_head::execute(THD *thd)
|
||||
{
|
||||
sp_pvar_t *pvar = pctx->find_pvar(i);
|
||||
|
||||
// QQ Passing an argument is, in a sense, a "SET". We have to evaluate
|
||||
// any expression at this point.
|
||||
nctx->push_item(it->this_item());
|
||||
// Note: If it's OUT or INOUT, it must be a variable.
|
||||
// QQ: Need to handle "global" user/host variables too!!!
|
||||
if (!pvar || pvar->mode == sp_param_in)
|
||||
nctx->set_oindex(i, -1);
|
||||
if (! pvar)
|
||||
nctx->set_oindex(i, -1); // Shouldn't happen
|
||||
else
|
||||
nctx->set_oindex(i, static_cast<Item_splocal *>(it)->get_offset());
|
||||
{
|
||||
if (pvar->mode == sp_param_out)
|
||||
nctx->push_item(it->this_item()); // OUT
|
||||
else
|
||||
nctx->push_item(eval_func_item(it, pvar->type)); // IN or INOUT
|
||||
// Note: If it's OUT or INOUT, it must be a variable.
|
||||
// QQ: Need to handle "global" user/host variables too!!!
|
||||
if (pvar->mode == sp_param_in)
|
||||
nctx->set_oindex(i, -1); // IN
|
||||
else // OUT or INOUT
|
||||
nctx->set_oindex(i, static_cast<Item_splocal *>(it)->get_offset());
|
||||
}
|
||||
}
|
||||
// The rest of the frame are local variables which are all IN.
|
||||
// QQ We haven't found any hint of what the value is when unassigned,
|
||||
@@ -176,14 +182,12 @@ sp_head::execute(THD *thd)
|
||||
|
||||
while (ret == 0)
|
||||
{
|
||||
int offset;
|
||||
sp_instr *i;
|
||||
|
||||
i = get_instr(ip); // Returns NULL when we're done.
|
||||
if (i == NULL)
|
||||
break;
|
||||
ret= i->execute(thd, &offset);
|
||||
ip += offset;
|
||||
ret= i->execute(thd, &ip);
|
||||
}
|
||||
|
||||
thd->net.no_send_ok= nsok;
|
||||
@@ -250,6 +254,27 @@ sp_head::restore_lex(THD *thd)
|
||||
memcpy(&thd->lex, &m_lex, sizeof(LEX)); // Restore lex
|
||||
}
|
||||
|
||||
void
|
||||
sp_head::push_backpatch(uint ip)
|
||||
{
|
||||
(void)m_backpatch.push_front(&ip);
|
||||
}
|
||||
|
||||
void
|
||||
sp_head::backpatch(uint dest)
|
||||
{
|
||||
while (! m_backpatch.is_empty())
|
||||
{
|
||||
uint *ip= m_backpatch.pop();
|
||||
sp_instr_jump *i= static_cast<sp_instr_jump *>(get_instr(*ip));
|
||||
|
||||
i->set_destination(dest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
// Finds the SP 'name'. Currently this always reads from the database
|
||||
// and prepares (parse) it, but in the future it will first look in
|
||||
// the in-memory cache for SPs. (And store newly prepared SPs there of
|
||||
@@ -350,12 +375,13 @@ sp_drop(THD *thd, char *name, uint namelen)
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// sp_instr_stmt
|
||||
//
|
||||
int
|
||||
sp_instr_stmt::execute(THD *thd, int *offsetp)
|
||||
sp_instr_stmt::execute(THD *thd, uint *nextp)
|
||||
{
|
||||
LEX olex; // The other lex
|
||||
|
||||
@@ -368,7 +394,7 @@ sp_instr_stmt::execute(THD *thd, int *offsetp)
|
||||
|
||||
memcpy(&thd->lex, &olex, sizeof(LEX)); // Restore the other lex
|
||||
|
||||
*offsetp = 1;
|
||||
*nextp = m_ip+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -376,9 +402,41 @@ sp_instr_stmt::execute(THD *thd, int *offsetp)
|
||||
// sp_instr_set
|
||||
//
|
||||
int
|
||||
sp_instr_set::execute(THD *thd, int *offsetp)
|
||||
sp_instr_set::execute(THD *thd, uint *nextp)
|
||||
{
|
||||
thd->spcont->set_item(m_offset, eval_func_item(m_value, m_type));
|
||||
*offsetp = 1;
|
||||
*nextp = m_ip+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// sp_instr_jump_if
|
||||
//
|
||||
|
||||
int
|
||||
sp_instr_jump_if::execute(THD *thd, uint *nextp)
|
||||
{
|
||||
Item *it= eval_func_item(m_expr, MYSQL_TYPE_TINY);
|
||||
|
||||
if (it->val_int())
|
||||
*nextp = m_dest;
|
||||
else
|
||||
*nextp = m_ip+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// sp_instr_jump_if_not
|
||||
//
|
||||
|
||||
int
|
||||
sp_instr_jump_if_not::execute(THD *thd, uint *nextp)
|
||||
{
|
||||
Item *it= eval_func_item(m_expr, MYSQL_TYPE_TINY);
|
||||
|
||||
if (! it->val_int())
|
||||
*nextp = m_dest;
|
||||
else
|
||||
*nextp = m_ip+1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
136
sql/sp_head.h
136
sql/sp_head.h
@@ -72,6 +72,12 @@ public:
|
||||
void
|
||||
restore_lex(THD *thd);
|
||||
|
||||
void
|
||||
push_backpatch(uint ip);
|
||||
|
||||
void
|
||||
backpatch(uint dest);
|
||||
|
||||
private:
|
||||
|
||||
Item_string *m_name;
|
||||
@@ -79,6 +85,7 @@ private:
|
||||
LEX *m_mylex; // My own lex
|
||||
LEX m_lex; // Temp. store for the other lex
|
||||
DYNAMIC_ARRAY m_instr; // The "instructions"
|
||||
List<uint> m_backpatch; // Instructions needing backpaching
|
||||
|
||||
inline sp_instr *
|
||||
get_instr(uint i)
|
||||
@@ -106,6 +113,10 @@ int
|
||||
sp_drop(THD *thd, char *name, uint namelen);
|
||||
|
||||
|
||||
//
|
||||
// "Instructions"...
|
||||
//
|
||||
|
||||
class sp_instr : public Sql_alloc
|
||||
{
|
||||
sp_instr(const sp_instr &); /* Prevent use of these */
|
||||
@@ -114,24 +125,28 @@ class sp_instr : public Sql_alloc
|
||||
public:
|
||||
|
||||
// Should give each a name or type code for debugging purposes?
|
||||
sp_instr()
|
||||
: Sql_alloc()
|
||||
sp_instr(uint ip)
|
||||
: Sql_alloc(), m_ip(ip)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr()
|
||||
{}
|
||||
|
||||
// Execute this instrution. '*offsetp' will be set to an offset to the
|
||||
// next instruction to execute. (For most instruction this will be 1,
|
||||
// i.e. the following instruction.)
|
||||
// Execute this instrution. '*nextp' will be set to the index of the next
|
||||
// instruction to execute. (For most instruction this will be the
|
||||
// instruction following this one.)
|
||||
// Returns 0 on success, non-zero if some error occured.
|
||||
virtual int
|
||||
execute(THD *thd, int *offsetp)
|
||||
execute(THD *thd, uint *nextp)
|
||||
{ // Default is a no-op.
|
||||
*offsetp = 1; // Next instruction
|
||||
*nextp = m_ip+1; // Next instruction
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
uint m_ip; // My index
|
||||
|
||||
}; // class sp_instr : public Sql_alloc
|
||||
|
||||
|
||||
@@ -145,14 +160,14 @@ class sp_instr_stmt : public sp_instr
|
||||
|
||||
public:
|
||||
|
||||
sp_instr_stmt()
|
||||
: sp_instr()
|
||||
sp_instr_stmt(uint ip)
|
||||
: sp_instr(ip)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_stmt()
|
||||
{}
|
||||
|
||||
virtual int execute(THD *thd, int *offsetp);
|
||||
virtual int execute(THD *thd, uint *nextp);
|
||||
|
||||
inline void
|
||||
set_lex(LEX *lex)
|
||||
@@ -180,21 +195,114 @@ class sp_instr_set : public sp_instr
|
||||
|
||||
public:
|
||||
|
||||
sp_instr_set(uint offset, Item *val, enum enum_field_types type)
|
||||
: sp_instr(), m_offset(offset), m_value(val), m_type(type)
|
||||
sp_instr_set(uint ip, uint offset, Item *val, enum enum_field_types type)
|
||||
: sp_instr(ip), m_offset(offset), m_value(val), m_type(type)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_set()
|
||||
{}
|
||||
|
||||
virtual int execute(THD *thd, int *offsetp);
|
||||
virtual int execute(THD *thd, uint *nextp);
|
||||
|
||||
private:
|
||||
|
||||
uint m_offset;
|
||||
uint m_offset; // Frame offset
|
||||
Item *m_value;
|
||||
enum enum_field_types m_type; // The declared type
|
||||
|
||||
}; // class sp_instr_set : public sp_instr
|
||||
|
||||
|
||||
class sp_instr_jump : public sp_instr
|
||||
{
|
||||
sp_instr_jump(const sp_instr_jump &); /* Prevent use of these */
|
||||
void operator=(sp_instr_jump &);
|
||||
|
||||
public:
|
||||
|
||||
sp_instr_jump(uint ip)
|
||||
: sp_instr(ip)
|
||||
{}
|
||||
|
||||
sp_instr_jump(uint ip, uint dest)
|
||||
: sp_instr(ip), m_dest(dest)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_jump()
|
||||
{}
|
||||
|
||||
virtual int execute(THD *thd, uint *nextp)
|
||||
{
|
||||
*nextp= m_dest;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_destination(uint dest)
|
||||
{
|
||||
m_dest= dest;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int m_dest; // Where we will go
|
||||
|
||||
}; // class sp_instr_jump : public sp_instr
|
||||
|
||||
|
||||
class sp_instr_jump_if : public sp_instr_jump
|
||||
{
|
||||
sp_instr_jump_if(const sp_instr_jump_if &); /* Prevent use of these */
|
||||
void operator=(sp_instr_jump_if &);
|
||||
|
||||
public:
|
||||
|
||||
sp_instr_jump_if(uint ip, Item *i)
|
||||
: sp_instr_jump(ip), m_expr(i)
|
||||
{}
|
||||
|
||||
sp_instr_jump_if(uint ip, Item *i, uint dest)
|
||||
: sp_instr_jump(ip, dest), m_expr(i)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_jump_if()
|
||||
{}
|
||||
|
||||
virtual int execute(THD *thd, uint *nextp);
|
||||
|
||||
private:
|
||||
|
||||
int m_dest; // Where we will go
|
||||
Item *m_expr; // The condition
|
||||
|
||||
}; // class sp_instr_jump_if : public sp_instr_jump
|
||||
|
||||
|
||||
class sp_instr_jump_if_not : public sp_instr_jump
|
||||
{
|
||||
sp_instr_jump_if_not(const sp_instr_jump_if_not &); /* Prevent use of these */
|
||||
void operator=(sp_instr_jump_if_not &);
|
||||
|
||||
public:
|
||||
|
||||
sp_instr_jump_if_not(uint ip, Item *i)
|
||||
: sp_instr_jump(ip), m_expr(i)
|
||||
{}
|
||||
|
||||
sp_instr_jump_if_not(uint ip, Item *i, uint dest)
|
||||
: sp_instr_jump(ip, dest), m_expr(i)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_jump_if_not()
|
||||
{}
|
||||
|
||||
virtual int execute(THD *thd, uint *nextp);
|
||||
|
||||
private:
|
||||
|
||||
int m_dest; // Where we will go
|
||||
Item *m_expr; // The condition
|
||||
|
||||
}; // class sp_instr_jump_if_not : public sp_instr_jump
|
||||
|
||||
#endif /* _SP_HEAD_H_ */
|
||||
|
||||
@@ -24,14 +24,16 @@
|
||||
|
||||
#include "mysql_priv.h"
|
||||
#include "sp_pcontext.h"
|
||||
#include "sp_head.h"
|
||||
|
||||
sp_pcontext::sp_pcontext()
|
||||
: m_params(0), m_framesize(0), m_i(0)
|
||||
: m_params(0), m_framesize(0), m_i(0), m_genlab(0)
|
||||
{
|
||||
m_pvar_size = 16;
|
||||
m_pvar = (sp_pvar_t *)my_malloc(m_pvar_size * sizeof(sp_pvar_t), MYF(MY_WME));
|
||||
if (m_pvar)
|
||||
memset(m_pvar, 0, m_pvar_size * sizeof(sp_pvar_t));
|
||||
m_label.empty();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -89,3 +91,41 @@ sp_pcontext::push(LEX_STRING *name, enum enum_field_types type,
|
||||
m_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sp_pcontext::push_label(char *name, uint ip)
|
||||
{
|
||||
sp_label_t *lab = (sp_label_t *)my_malloc(sizeof(sp_label_t), MYF(MY_WME));
|
||||
|
||||
if (lab)
|
||||
{
|
||||
lab->name= name;
|
||||
lab->ip= ip;
|
||||
m_label.push_front(lab);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sp_pcontext::push_gen_label(uint ip)
|
||||
{
|
||||
char *s= my_malloc(10, MYF(MY_WME)); // 10=...
|
||||
|
||||
if (s)
|
||||
{
|
||||
sprintf(s, ".%08x", m_genlab++); // ...9+1
|
||||
push_label(s, ip);
|
||||
}
|
||||
}
|
||||
|
||||
sp_label_t *
|
||||
sp_pcontext::find_label(char *name)
|
||||
{
|
||||
List_iterator_fast<sp_label_t> li(m_label);
|
||||
sp_label_t *lab;
|
||||
|
||||
while ((lab= li++))
|
||||
if (strcasecmp(name, lab->name) == 0)
|
||||
return lab;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ typedef struct
|
||||
my_bool isset;
|
||||
} sp_pvar_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
uint ip; // Instruction index
|
||||
} sp_label_t;
|
||||
|
||||
class sp_pcontext : public Sql_alloc
|
||||
{
|
||||
sp_pcontext(const sp_pcontext &); /* Prevent use of these */
|
||||
@@ -89,6 +95,7 @@ class sp_pcontext : public Sql_alloc
|
||||
void
|
||||
push(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode);
|
||||
|
||||
// Pop the last 'num' slots of the frame
|
||||
inline void
|
||||
pop(uint num = 1)
|
||||
{
|
||||
@@ -109,6 +116,21 @@ class sp_pcontext : public Sql_alloc
|
||||
return m_pvar+i;
|
||||
}
|
||||
|
||||
void
|
||||
push_label(char *name, uint ip);
|
||||
|
||||
void
|
||||
push_gen_label(uint ip);
|
||||
|
||||
sp_label_t *
|
||||
find_label(char *name);
|
||||
|
||||
inline void
|
||||
pop_label()
|
||||
{
|
||||
m_label.pop();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint m_params; // The number of parameters
|
||||
@@ -121,6 +143,9 @@ private:
|
||||
void
|
||||
grow();
|
||||
|
||||
List<sp_label_t> m_label; // The label list
|
||||
uint m_genlab; // Gen. label counter
|
||||
|
||||
}; // class sp_pcontext : public Sql_alloc
|
||||
|
||||
|
||||
|
||||
152
sql/sql_yacc.yy
152
sql/sql_yacc.yy
@@ -526,6 +526,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
||||
%token SQL_SMALL_RESULT
|
||||
%token SQL_BUFFER_RESULT
|
||||
|
||||
%token CURSOR_SYM
|
||||
%token ELSEIF_SYM
|
||||
%token ITERATE_SYM
|
||||
%token LEAVE_SYM
|
||||
%token LOOP_SYM
|
||||
%token UNTIL_SYM
|
||||
%token WHILE_SYM
|
||||
%token ASENSITIVE_SYM
|
||||
%token INSENSITIVE_SYM
|
||||
%token SENSITIVE_SYM
|
||||
/* QQ This is a dummy, until we have solved the SET syntax problem. */
|
||||
%token SPSET_SYM
|
||||
|
||||
@@ -680,7 +690,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
|
||||
statement
|
||||
END_OF_INPUT
|
||||
|
||||
%type <NONE> call sp_proc_body sp_proc_stmts sp_proc_stmt
|
||||
%type <NONE> call sp_proc_stmts sp_proc_stmt
|
||||
%type <num> sp_decls sp_decl sp_decl_idents sp_opt_inout
|
||||
|
||||
%type <NONE>
|
||||
@@ -906,7 +916,7 @@ create:
|
||||
{
|
||||
Lex->spcont->set_params();
|
||||
}
|
||||
sp_proc_body
|
||||
sp_proc_stmt
|
||||
{
|
||||
Lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
||||
}
|
||||
@@ -974,26 +984,9 @@ sp_opt_locator:
|
||||
| AS LOCATOR_SYM
|
||||
;
|
||||
|
||||
sp_proc_body:
|
||||
{
|
||||
Lex->sphead->reset_lex(YYTHD);
|
||||
}
|
||||
sp_proc_stmt
|
||||
{
|
||||
Lex->sphead->restore_lex(YYTHD);
|
||||
}
|
||||
| begin
|
||||
sp_decls
|
||||
sp_proc_stmts
|
||||
END
|
||||
{
|
||||
Lex->spcont->pop($2);
|
||||
}
|
||||
;
|
||||
|
||||
sp_proc_stmts:
|
||||
sp_proc_body ';'
|
||||
| sp_proc_stmts sp_proc_body ';'
|
||||
sp_proc_stmt ';'
|
||||
| sp_proc_stmts sp_proc_stmt ';'
|
||||
;
|
||||
|
||||
sp_decls:
|
||||
@@ -1037,14 +1030,69 @@ 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);
|
||||
}
|
||||
statement
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_instr_stmt *i= new sp_instr_stmt();
|
||||
sp_instr_stmt *i= new sp_instr_stmt(lex->sphead->instructions());
|
||||
|
||||
i->set_lex(lex);
|
||||
lex->sphead->add_instr(i);
|
||||
lex->sphead->restore_lex(YYTHD);
|
||||
}
|
||||
/* | sp_if
|
||||
| sp_case */
|
||||
| sp_labeled_control
|
||||
{}
|
||||
| { /* Unlabeled controls get a secret label. */
|
||||
LEX *lex= Lex;
|
||||
|
||||
Lex->spcont->push_gen_label(lex->sphead->instructions());
|
||||
}
|
||||
sp_unlabeled_control
|
||||
{
|
||||
/* QQ backpatch here */
|
||||
Lex->spcont->pop_label();
|
||||
}
|
||||
| LEAVE_SYM IDENT
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_label_t *lab= lex->spcont->find_label($2.str);
|
||||
|
||||
if (! lab)
|
||||
{
|
||||
printf("QQ LEAVE with no matching label\n");
|
||||
YYABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint ip= lex->sphead->instructions();
|
||||
sp_instr_jump *i= new sp_instr_jump(ip, 0);
|
||||
|
||||
lex->sphead->push_backpatch(ip);
|
||||
lex->sphead->add_instr(i);
|
||||
}
|
||||
}
|
||||
| ITERATE_SYM IDENT
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_label_t *lab= lex->spcont->find_label($2.str);
|
||||
|
||||
if (! lab)
|
||||
{
|
||||
printf("QQ ITERATE with no matching label\n");
|
||||
YYABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint ip= lex->sphead->instructions();
|
||||
sp_instr_jump *i= new sp_instr_jump(ip, lab->ip);
|
||||
|
||||
lex->sphead->add_instr(i);
|
||||
}
|
||||
}
|
||||
|
|
||||
/* QQ Dummy. We need to fix the old SET syntax to make it work for
|
||||
local SP variables as well. */
|
||||
@@ -1059,7 +1107,8 @@ sp_proc_stmt:
|
||||
else
|
||||
{
|
||||
/* QQ Check type match! */
|
||||
sp_instr_set *i = new sp_instr_set(spv->offset, $4, spv->type);
|
||||
sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(),
|
||||
spv->offset, $4, spv->type);
|
||||
|
||||
lex->sphead->add_instr(i);
|
||||
spv->isset= TRUE;
|
||||
@@ -1067,6 +1116,63 @@ sp_proc_stmt:
|
||||
}
|
||||
;
|
||||
|
||||
sp_labeled_control:
|
||||
IDENT ':'
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_label_t *lab= lex->spcont->find_label($1.str);
|
||||
|
||||
if (lab)
|
||||
{
|
||||
printf("QQ Redefining label\n");
|
||||
YYABORT;
|
||||
}
|
||||
else
|
||||
lex->spcont->push_label($1.str,
|
||||
lex->sphead->instructions());
|
||||
}
|
||||
sp_unlabeled_control IDENT
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_label_t *lab= lex->spcont->find_label($5.str);
|
||||
|
||||
if (! lab)
|
||||
{
|
||||
printf("QQ end-label without match\n");
|
||||
YYABORT;
|
||||
}
|
||||
else if (strcasecmp($5.str, lab->name) != 0)
|
||||
{
|
||||
printf("QQ mismatching labels\n");
|
||||
YYABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* QQ backpatch here */
|
||||
lex->spcont->pop_label();
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
sp_unlabeled_control:
|
||||
begin
|
||||
sp_decls
|
||||
sp_proc_stmts
|
||||
END
|
||||
{
|
||||
Lex->spcont->pop($2);
|
||||
}
|
||||
| LOOP_SYM
|
||||
sp_proc_stmts
|
||||
END LOOP_SYM
|
||||
| WHILE_SYM expr DO_SYM
|
||||
sp_proc_stmts
|
||||
END WHILE_SYM
|
||||
| FUNC_ARG2 /* "REPEAT" actually... */
|
||||
sp_proc_stmts
|
||||
UNTIL_SYM expr END FUNC_ARG2
|
||||
;
|
||||
|
||||
create2:
|
||||
'(' field_list ')' opt_create_table_options create3 {}
|
||||
| opt_create_table_options create3 {}
|
||||
|
||||
Reference in New Issue
Block a user