Merge mysql.com:/usr/local/bk/mysql-5.0
into mysql.com:/home/pem/work/mysql-5.0-merge
This commit is contained in:
commit
d90c1ae62f
@ -63,6 +63,11 @@ iterate foo;
|
|||||||
end|
|
end|
|
||||||
ERROR 42000: ITERATE with no matching label: foo
|
ERROR 42000: ITERATE with no matching label: foo
|
||||||
create procedure foo()
|
create procedure foo()
|
||||||
|
begin
|
||||||
|
goto foo;
|
||||||
|
end|
|
||||||
|
ERROR 42000: GOTO with no matching label: foo
|
||||||
|
create procedure foo()
|
||||||
foo: loop
|
foo: loop
|
||||||
foo: loop
|
foo: loop
|
||||||
set @x=2;
|
set @x=2;
|
||||||
|
@ -398,6 +398,87 @@ id data
|
|||||||
i 3
|
i 3
|
||||||
delete from t1|
|
delete from t1|
|
||||||
drop procedure i|
|
drop procedure i|
|
||||||
|
create procedure j()
|
||||||
|
begin
|
||||||
|
declare y int;
|
||||||
|
label a;
|
||||||
|
select * from t1;
|
||||||
|
select count(*) into y from t1;
|
||||||
|
if y > 2 then
|
||||||
|
goto b;
|
||||||
|
end if;
|
||||||
|
insert into t1 values ("j", y);
|
||||||
|
goto a;
|
||||||
|
label b;
|
||||||
|
end|
|
||||||
|
call j()|
|
||||||
|
id data
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
j 2
|
||||||
|
drop procedure j|
|
||||||
|
create procedure k(a int)
|
||||||
|
begin
|
||||||
|
declare x int default 0;
|
||||||
|
declare continue handler for sqlstate '42S98' set x = 1;
|
||||||
|
label a;
|
||||||
|
select * from t1;
|
||||||
|
b:
|
||||||
|
while x < 2 do
|
||||||
|
begin
|
||||||
|
declare continue handler for sqlstate '42S99' set x = 2;
|
||||||
|
if a = 0 then
|
||||||
|
set x = x + 1;
|
||||||
|
iterate b;
|
||||||
|
elseif a = 1 then
|
||||||
|
leave b;
|
||||||
|
elseif a = 2 then
|
||||||
|
set a = 1;
|
||||||
|
goto a;
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
end while b;
|
||||||
|
select * from t1;
|
||||||
|
end|
|
||||||
|
call k(0)|
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
j 2
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
j 2
|
||||||
|
call k(1)|
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
j 2
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
j 2
|
||||||
|
call k(2)|
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
j 2
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
j 2
|
||||||
|
id data
|
||||||
|
j 0
|
||||||
|
j 1
|
||||||
|
j 2
|
||||||
|
drop procedure k|
|
||||||
|
delete from t1|
|
||||||
insert into t1 values ("foo", 3), ("bar", 19)|
|
insert into t1 values ("foo", 3), ("bar", 19)|
|
||||||
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
|
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
|
||||||
create procedure sel1()
|
create procedure sel1()
|
||||||
@ -1487,7 +1568,7 @@ Grants for root@localhost
|
|||||||
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
|
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
|
||||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
master-bin.000001 22185
|
master-bin.000001 22451
|
||||||
Database Table In_use Name_locked
|
Database Table In_use Name_locked
|
||||||
Privilege Context Comment
|
Privilege Context Comment
|
||||||
Alter Tables To alter the table
|
Alter Tables To alter the table
|
||||||
@ -1541,7 +1622,7 @@ Grants for root@localhost
|
|||||||
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
|
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
|
||||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||||
master-bin.000001 22185
|
master-bin.000001 22451
|
||||||
Database Table In_use Name_locked
|
Database Table In_use Name_locked
|
||||||
Privilege Context Comment
|
Privilege Context Comment
|
||||||
Alter Tables To alter the table
|
Alter Tables To alter the table
|
||||||
@ -1580,10 +1661,10 @@ show processlist;
|
|||||||
end|
|
end|
|
||||||
call bug4902_2()|
|
call bug4902_2()|
|
||||||
Id User Host db Command Time State Info
|
Id User Host db Command Time State Info
|
||||||
# root localhost test Query 0 NULL call bug4902_2()
|
# root localhost test Query # NULL call bug4902_2()
|
||||||
call bug4902_2()|
|
call bug4902_2()|
|
||||||
Id User Host db Command Time State Info
|
Id User Host db Command Time State Info
|
||||||
# root localhost test Query 0 NULL call bug4902_2()
|
# root localhost test Query # NULL call bug4902_2()
|
||||||
drop procedure bug4902_2|
|
drop procedure bug4902_2|
|
||||||
drop table if exists t3|
|
drop table if exists t3|
|
||||||
create procedure bug4904()
|
create procedure bug4904()
|
||||||
|
@ -82,7 +82,7 @@ drop procedure if exists foo|
|
|||||||
--error 1304
|
--error 1304
|
||||||
show create procedure foo|
|
show create procedure foo|
|
||||||
|
|
||||||
# LEAVE/ITERATE with no match
|
# LEAVE/ITERATE/GOTO with no match
|
||||||
--error 1307
|
--error 1307
|
||||||
create procedure foo()
|
create procedure foo()
|
||||||
foo: loop
|
foo: loop
|
||||||
@ -98,6 +98,11 @@ create procedure foo()
|
|||||||
foo: begin
|
foo: begin
|
||||||
iterate foo;
|
iterate foo;
|
||||||
end|
|
end|
|
||||||
|
--error 1307
|
||||||
|
create procedure foo()
|
||||||
|
begin
|
||||||
|
goto foo;
|
||||||
|
end|
|
||||||
|
|
||||||
# Redefining label
|
# Redefining label
|
||||||
--error 1308
|
--error 1308
|
||||||
|
@ -468,6 +468,65 @@ delete from t1|
|
|||||||
drop procedure i|
|
drop procedure i|
|
||||||
|
|
||||||
|
|
||||||
|
# The non-standard GOTO, for compatibility
|
||||||
|
#
|
||||||
|
# QQQ The "label" syntax is temporary.
|
||||||
|
# QQQ This is no nearly enough, more tests are needed
|
||||||
|
#
|
||||||
|
create procedure j()
|
||||||
|
begin
|
||||||
|
declare y int;
|
||||||
|
|
||||||
|
label a;
|
||||||
|
select * from t1;
|
||||||
|
select count(*) into y from t1;
|
||||||
|
if y > 2 then
|
||||||
|
goto b;
|
||||||
|
end if;
|
||||||
|
insert into t1 values ("j", y);
|
||||||
|
goto a;
|
||||||
|
label b;
|
||||||
|
end|
|
||||||
|
|
||||||
|
call j()|
|
||||||
|
|
||||||
|
drop procedure j|
|
||||||
|
|
||||||
|
# With dummy handlers, just to test restore of contexts with jumps
|
||||||
|
create procedure k(a int)
|
||||||
|
begin
|
||||||
|
declare x int default 0;
|
||||||
|
declare continue handler for sqlstate '42S98' set x = 1;
|
||||||
|
|
||||||
|
label a;
|
||||||
|
select * from t1;
|
||||||
|
b:
|
||||||
|
while x < 2 do
|
||||||
|
begin
|
||||||
|
declare continue handler for sqlstate '42S99' set x = 2;
|
||||||
|
|
||||||
|
if a = 0 then
|
||||||
|
set x = x + 1;
|
||||||
|
iterate b;
|
||||||
|
elseif a = 1 then
|
||||||
|
leave b;
|
||||||
|
elseif a = 2 then
|
||||||
|
set a = 1;
|
||||||
|
goto a;
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
end while b;
|
||||||
|
|
||||||
|
select * from t1;
|
||||||
|
end|
|
||||||
|
|
||||||
|
call k(0)|
|
||||||
|
call k(1)|
|
||||||
|
call k(2)|
|
||||||
|
|
||||||
|
drop procedure k|
|
||||||
|
delete from t1|
|
||||||
|
|
||||||
# SELECT with one of more result set sent back to the clinet
|
# SELECT with one of more result set sent back to the clinet
|
||||||
insert into t1 values ("foo", 3), ("bar", 19)|
|
insert into t1 values ("foo", 3), ("bar", 19)|
|
||||||
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
|
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
|
||||||
@ -1725,9 +1784,9 @@ create procedure bug4902_2()
|
|||||||
begin
|
begin
|
||||||
show processlist;
|
show processlist;
|
||||||
end|
|
end|
|
||||||
--replace_column 1 #
|
--replace_column 1 # 6 #
|
||||||
call bug4902_2()|
|
call bug4902_2()|
|
||||||
--replace_column 1 #
|
--replace_column 1 # 6 #
|
||||||
call bug4902_2()|
|
call bug4902_2()|
|
||||||
drop procedure bug4902_2|
|
drop procedure bug4902_2|
|
||||||
|
|
||||||
|
@ -209,6 +209,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
|
{ "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)},
|
||||||
{ "GET_FORMAT", SYM(GET_FORMAT)},
|
{ "GET_FORMAT", SYM(GET_FORMAT)},
|
||||||
{ "GLOBAL", SYM(GLOBAL_SYM)},
|
{ "GLOBAL", SYM(GLOBAL_SYM)},
|
||||||
|
{ "GOTO", SYM(GOTO_SYM)},
|
||||||
{ "GRANT", SYM(GRANT)},
|
{ "GRANT", SYM(GRANT)},
|
||||||
{ "GRANTS", SYM(GRANTS)},
|
{ "GRANTS", SYM(GRANTS)},
|
||||||
{ "GROUP", SYM(GROUP)},
|
{ "GROUP", SYM(GROUP)},
|
||||||
@ -256,6 +257,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "KEY", SYM(KEY_SYM)},
|
{ "KEY", SYM(KEY_SYM)},
|
||||||
{ "KEYS", SYM(KEYS)},
|
{ "KEYS", SYM(KEYS)},
|
||||||
{ "KILL", SYM(KILL_SYM)},
|
{ "KILL", SYM(KILL_SYM)},
|
||||||
|
{ "LABEL", SYM(LABEL_SYM)},
|
||||||
{ "LANGUAGE", SYM(LANGUAGE_SYM)},
|
{ "LANGUAGE", SYM(LANGUAGE_SYM)},
|
||||||
{ "LAST", SYM(LAST_SYM)},
|
{ "LAST", SYM(LAST_SYM)},
|
||||||
{ "LEADING", SYM(LEADING)},
|
{ "LEADING", SYM(LEADING)},
|
||||||
|
@ -846,12 +846,36 @@ sp_head::backpatch(sp_label_t *lab)
|
|||||||
List_iterator_fast<bp_t> li(m_backpatch);
|
List_iterator_fast<bp_t> li(m_backpatch);
|
||||||
|
|
||||||
while ((bp= li++))
|
while ((bp= li++))
|
||||||
if (bp->lab == lab)
|
{
|
||||||
|
if (bp->lab == lab ||
|
||||||
|
(bp->lab->type == SP_LAB_REF &&
|
||||||
|
my_strcasecmp(system_charset_info, bp->lab->name, lab->name) == 0))
|
||||||
{
|
{
|
||||||
sp_instr_jump *i= static_cast<sp_instr_jump *>(bp->instr);
|
sp_scope_t sdiff;
|
||||||
|
|
||||||
i->set_destination(dest);
|
if (bp->lab->type == SP_LAB_REF)
|
||||||
|
bp->lab= lab;
|
||||||
|
m_pcont->diff_scopes(0, &sdiff);
|
||||||
|
bp->instr->backpatch(dest, sdiff.hndlrs, sdiff.curs);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sp_head::check_backpatch(THD *thd)
|
||||||
|
{
|
||||||
|
bp_t *bp;
|
||||||
|
List_iterator_fast<bp_t> li(m_backpatch);
|
||||||
|
|
||||||
|
while ((bp= li++))
|
||||||
|
{
|
||||||
|
if (bp->lab->type == SP_LAB_REF)
|
||||||
|
{
|
||||||
|
net_printf(thd, ER_SP_LILABEL_MISMATCH, "GOTO", bp->lab->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1199,8 +1223,9 @@ sp_instr_jump::print(String *str)
|
|||||||
uint
|
uint
|
||||||
sp_instr_jump::opt_mark(sp_head *sp)
|
sp_instr_jump::opt_mark(sp_head *sp)
|
||||||
{
|
{
|
||||||
marked= 1;
|
|
||||||
m_dest= opt_shortcut_jump(sp);
|
m_dest= opt_shortcut_jump(sp);
|
||||||
|
if (m_dest != m_ip+1) /* Jumping to following instruction? */
|
||||||
|
marked= 1;
|
||||||
m_optdest= sp->get_instr(m_dest);
|
m_optdest= sp->get_instr(m_dest);
|
||||||
return m_dest;
|
return m_dest;
|
||||||
}
|
}
|
||||||
|
@ -182,6 +182,13 @@ public:
|
|||||||
void
|
void
|
||||||
backpatch(struct sp_label *);
|
backpatch(struct sp_label *);
|
||||||
|
|
||||||
|
// Check that no unresolved references exist.
|
||||||
|
// If none found, 0 is returned, otherwise errors have been issued
|
||||||
|
// and -1 is returned.
|
||||||
|
// This is called by the parser at the end of a create procedure/function.
|
||||||
|
int
|
||||||
|
check_backpatch(THD *thd);
|
||||||
|
|
||||||
char *name(uint *lenp = 0) const
|
char *name(uint *lenp = 0) const
|
||||||
{
|
{
|
||||||
if (lenp)
|
if (lenp)
|
||||||
@ -272,7 +279,7 @@ public:
|
|||||||
|
|
||||||
virtual void print(String *str) = 0;
|
virtual void print(String *str) = 0;
|
||||||
|
|
||||||
virtual void set_destination(uint dest)
|
virtual void backpatch(uint dest, uint hpop, uint cpop)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual uint opt_mark(sp_head *sp)
|
virtual uint opt_mark(sp_head *sp)
|
||||||
@ -394,8 +401,7 @@ public:
|
|||||||
|
|
||||||
virtual void opt_move(uint dst, List<sp_instr> *ibp);
|
virtual void opt_move(uint dst, List<sp_instr> *ibp);
|
||||||
|
|
||||||
virtual void
|
virtual void backpatch(uint dest, uint hpop, uint cpop)
|
||||||
set_destination(uint dest)
|
|
||||||
{
|
{
|
||||||
if (m_dest == 0) // Don't reset
|
if (m_dest == 0) // Don't reset
|
||||||
m_dest= dest;
|
m_dest= dest;
|
||||||
@ -575,6 +581,21 @@ public:
|
|||||||
|
|
||||||
virtual void print(String *str);
|
virtual void print(String *str);
|
||||||
|
|
||||||
|
virtual void backpatch(uint dest, uint hpop, uint cpop)
|
||||||
|
{
|
||||||
|
if (hpop > m_count)
|
||||||
|
m_count= 0;
|
||||||
|
else
|
||||||
|
m_count-= hpop;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint opt_mark(sp_head *sp)
|
||||||
|
{
|
||||||
|
if (m_count)
|
||||||
|
marked= 1;
|
||||||
|
return m_ip+1;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint m_count;
|
uint m_count;
|
||||||
@ -655,6 +676,21 @@ public:
|
|||||||
|
|
||||||
virtual void print(String *str);
|
virtual void print(String *str);
|
||||||
|
|
||||||
|
virtual void backpatch(uint dest, uint hpop, uint cpop)
|
||||||
|
{
|
||||||
|
if (cpop > m_count)
|
||||||
|
m_count= 0;
|
||||||
|
else
|
||||||
|
m_count-= cpop;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint opt_mark(sp_head *sp)
|
||||||
|
{
|
||||||
|
if (m_count)
|
||||||
|
marked= 1;
|
||||||
|
return m_ip+1;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint m_count;
|
uint m_count;
|
||||||
|
@ -27,12 +27,14 @@
|
|||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
|
|
||||||
sp_pcontext::sp_pcontext()
|
sp_pcontext::sp_pcontext()
|
||||||
: Sql_alloc(), m_params(0), m_framesize(0), m_handlers(0), m_cursmax(0)
|
: Sql_alloc(), m_params(0), m_framesize(0), m_handlers(0), m_cursmax(0),
|
||||||
|
m_hndlrlev(0)
|
||||||
{
|
{
|
||||||
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
|
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
|
||||||
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
|
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
|
||||||
VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8));
|
VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8));
|
||||||
VOID(my_init_dynamic_array(&m_scopes, sizeof(sp_scope_t), 16, 8));
|
VOID(my_init_dynamic_array(&m_scopes, sizeof(sp_scope_t), 16, 8));
|
||||||
|
VOID(my_init_dynamic_array(&m_glabel, sizeof(sp_label_t *), 16, 8));
|
||||||
m_label.empty();
|
m_label.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +45,7 @@ sp_pcontext::destroy()
|
|||||||
delete_dynamic(&m_cond);
|
delete_dynamic(&m_cond);
|
||||||
delete_dynamic(&m_cursor);
|
delete_dynamic(&m_cursor);
|
||||||
delete_dynamic(&m_scopes);
|
delete_dynamic(&m_scopes);
|
||||||
|
delete_dynamic(&m_glabel);
|
||||||
m_label.empty();
|
m_label.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,14 +56,46 @@ sp_pcontext::push_scope()
|
|||||||
|
|
||||||
s.vars= m_pvar.elements;
|
s.vars= m_pvar.elements;
|
||||||
s.conds= m_cond.elements;
|
s.conds= m_cond.elements;
|
||||||
|
s.hndlrs= m_hndlrlev;
|
||||||
s.curs= m_cursor.elements;
|
s.curs= m_cursor.elements;
|
||||||
|
s.glab= m_glabel.elements;
|
||||||
insert_dynamic(&m_scopes, (gptr)&s);
|
insert_dynamic(&m_scopes, (gptr)&s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_pcontext::pop_scope()
|
sp_pcontext::pop_scope(sp_scope_t *sp)
|
||||||
{
|
{
|
||||||
(void)pop_dynamic(&m_scopes);
|
byte *p= pop_dynamic(&m_scopes);
|
||||||
|
|
||||||
|
if (sp && p)
|
||||||
|
memcpy(sp, p, sizeof(sp_scope_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sp_pcontext::diff_scopes(uint sold, sp_scope_t *diffs)
|
||||||
|
{
|
||||||
|
uint snew= m_scopes.elements;
|
||||||
|
sp_scope_t scope;
|
||||||
|
|
||||||
|
diffs->vars= diffs->conds= diffs->hndlrs= diffs->curs= diffs->glab= 0;
|
||||||
|
while (snew-- > sold)
|
||||||
|
{
|
||||||
|
get_dynamic(&m_scopes, (gptr)&scope, snew);
|
||||||
|
diffs->vars+= scope.vars;
|
||||||
|
diffs->conds+= scope.conds;
|
||||||
|
diffs->hndlrs+= scope.hndlrs;
|
||||||
|
diffs->curs+= scope.curs;
|
||||||
|
diffs->glab+= scope.glab;
|
||||||
|
}
|
||||||
|
if (sold)
|
||||||
|
{
|
||||||
|
get_dynamic(&m_scopes, (gptr)&scope, sold-1);
|
||||||
|
diffs->vars-= scope.vars;
|
||||||
|
diffs->conds-= scope.conds;
|
||||||
|
diffs->hndlrs-= scope.hndlrs;
|
||||||
|
diffs->curs-= scope.curs;
|
||||||
|
diffs->glab-= scope.glab;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,7 +167,8 @@ sp_pcontext::push_label(char *name, uint ip)
|
|||||||
{
|
{
|
||||||
lab->name= name;
|
lab->name= name;
|
||||||
lab->ip= ip;
|
lab->ip= ip;
|
||||||
lab->isbegin= FALSE;
|
lab->type= SP_LAB_GOTO;
|
||||||
|
lab->scopes= 0;
|
||||||
m_label.push_front(lab);
|
m_label.push_front(lab);
|
||||||
}
|
}
|
||||||
return lab;
|
return lab;
|
||||||
@ -245,3 +281,41 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
|
|||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sp_label_t *
|
||||||
|
sp_pcontext::push_glabel(char *name, uint ip)
|
||||||
|
{
|
||||||
|
sp_label_t *lab = (sp_label_t *)sql_alloc(sizeof(sp_label_t));
|
||||||
|
|
||||||
|
if (lab)
|
||||||
|
{
|
||||||
|
lab->name= name;
|
||||||
|
lab->ip= ip;
|
||||||
|
lab->type= SP_LAB_GOTO;
|
||||||
|
lab->scopes= 0;
|
||||||
|
insert_dynamic(&m_glabel, (gptr)&lab);
|
||||||
|
}
|
||||||
|
return lab;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp_label_t *
|
||||||
|
sp_pcontext::find_glabel(char *name)
|
||||||
|
{
|
||||||
|
uint i= m_glabel.elements;
|
||||||
|
|
||||||
|
while (i--)
|
||||||
|
{
|
||||||
|
sp_label_t *lab;
|
||||||
|
|
||||||
|
get_dynamic(&m_glabel, (gptr)&lab, i);
|
||||||
|
if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
|
||||||
|
return lab;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sp_pcontext::pop_glabel(uint count)
|
||||||
|
{
|
||||||
|
(void)pop_dynamic(&m_glabel);
|
||||||
|
}
|
||||||
|
@ -39,11 +39,18 @@ typedef struct sp_pvar
|
|||||||
Item *dflt;
|
Item *dflt;
|
||||||
} sp_pvar_t;
|
} sp_pvar_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define SP_LAB_REF 0 // Unresolved reference (for goto)
|
||||||
|
#define SP_LAB_GOTO 1 // Free goto label
|
||||||
|
#define SP_LAB_BEGIN 2 // Label at BEGIN
|
||||||
|
#define SP_LAB_ITER 3 // Label at iteration control
|
||||||
|
|
||||||
typedef struct sp_label
|
typedef struct sp_label
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
uint ip; // Instruction index
|
uint ip; // Instruction index
|
||||||
my_bool isbegin; // For ITERATE error checking
|
int type; // begin/iter or ref/free
|
||||||
|
uint scopes; // No. of scopes at label
|
||||||
} sp_label_t;
|
} sp_label_t;
|
||||||
|
|
||||||
typedef struct sp_cond_type
|
typedef struct sp_cond_type
|
||||||
@ -61,7 +68,7 @@ typedef struct sp_cond
|
|||||||
|
|
||||||
typedef struct sp_scope
|
typedef struct sp_scope
|
||||||
{
|
{
|
||||||
uint vars, conds, curs;
|
uint vars, conds, hndlrs, curs, glab;
|
||||||
} sp_scope_t;
|
} sp_scope_t;
|
||||||
|
|
||||||
class sp_pcontext : public Sql_alloc
|
class sp_pcontext : public Sql_alloc
|
||||||
@ -82,7 +89,18 @@ class sp_pcontext : public Sql_alloc
|
|||||||
push_scope();
|
push_scope();
|
||||||
|
|
||||||
void
|
void
|
||||||
pop_scope();
|
pop_scope(sp_scope_t *sp = 0);
|
||||||
|
|
||||||
|
uint
|
||||||
|
scopes()
|
||||||
|
{
|
||||||
|
return m_scopes.elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets '*diffs' to the differences between current scope index snew and sold
|
||||||
|
void
|
||||||
|
diff_scopes(uint sold, sp_scope_t *diffs);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parameters and variables
|
// Parameters and variables
|
||||||
@ -223,6 +241,18 @@ class sp_pcontext : public Sql_alloc
|
|||||||
return m_handlers;
|
return m_handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
push_handlers(uint count)
|
||||||
|
{
|
||||||
|
m_hndlrlev+= count;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
pop_handlers(uint count)
|
||||||
|
{
|
||||||
|
m_hndlrlev-= count;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Cursors
|
// Cursors
|
||||||
//
|
//
|
||||||
@ -246,17 +276,32 @@ class sp_pcontext : public Sql_alloc
|
|||||||
return m_cursmax;
|
return m_cursmax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// GOTO labels
|
||||||
|
//
|
||||||
|
|
||||||
|
sp_label_t *
|
||||||
|
push_glabel(char *name, uint ip);
|
||||||
|
|
||||||
|
sp_label_t *
|
||||||
|
find_glabel(char *name);
|
||||||
|
|
||||||
|
void
|
||||||
|
pop_glabel(uint count);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint m_params; // The number of parameters
|
uint m_params; // The number of parameters
|
||||||
uint m_framesize; // The maximum framesize
|
uint m_framesize; // The maximum framesize
|
||||||
uint m_handlers; // The total number of handlers
|
uint m_handlers; // The total number of handlers
|
||||||
uint m_cursmax; // The maximum number of cursors
|
uint m_cursmax; // The maximum number of cursors
|
||||||
|
uint m_hndlrlev; // Current number of active handlers
|
||||||
|
|
||||||
DYNAMIC_ARRAY m_pvar; // Parameters/variables
|
DYNAMIC_ARRAY m_pvar; // Parameters/variables
|
||||||
DYNAMIC_ARRAY m_cond; // Conditions
|
DYNAMIC_ARRAY m_cond; // Conditions
|
||||||
DYNAMIC_ARRAY m_cursor; // Cursors
|
DYNAMIC_ARRAY m_cursor; // Cursors
|
||||||
DYNAMIC_ARRAY m_scopes; // For error checking
|
DYNAMIC_ARRAY m_scopes; // For error checking
|
||||||
|
DYNAMIC_ARRAY m_glabel; // Goto labels
|
||||||
|
|
||||||
List<sp_label_t> m_label; // The label list
|
List<sp_label_t> m_label; // The label list
|
||||||
|
|
||||||
|
145
sql/sql_yacc.yy
145
sql/sql_yacc.yy
@ -611,6 +611,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
%token CURSOR_SYM
|
%token CURSOR_SYM
|
||||||
%token ELSEIF_SYM
|
%token ELSEIF_SYM
|
||||||
%token ITERATE_SYM
|
%token ITERATE_SYM
|
||||||
|
%token GOTO_SYM
|
||||||
|
%token LABEL_SYM
|
||||||
%token LEAVE_SYM
|
%token LEAVE_SYM
|
||||||
%token LOOP_SYM
|
%token LOOP_SYM
|
||||||
%token REPEAT_SYM
|
%token REPEAT_SYM
|
||||||
@ -1180,13 +1182,16 @@ create:
|
|||||||
sp_proc_stmt
|
sp_proc_stmt
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
sp_head *sp= lex->sphead;
|
||||||
|
|
||||||
lex->sphead->init_strings(YYTHD, lex, $3);
|
if (sp->check_backpatch(YYTHD))
|
||||||
|
YYABORT;
|
||||||
|
sp->init_strings(YYTHD, lex, $3);
|
||||||
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
|
||||||
/* Restore flag if it was cleared above */
|
/* Restore flag if it was cleared above */
|
||||||
if (lex->sphead->m_old_cmq)
|
if (sp->m_old_cmq)
|
||||||
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
|
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
|
||||||
lex->sphead->restore_thd_mem_root(YYTHD);
|
sp->restore_thd_mem_root(YYTHD);
|
||||||
}
|
}
|
||||||
| CREATE or_replace algorithm VIEW_SYM table_ident
|
| CREATE or_replace algorithm VIEW_SYM table_ident
|
||||||
{
|
{
|
||||||
@ -1286,6 +1291,8 @@ create_function_tail:
|
|||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp= lex->sphead;
|
sp_head *sp= lex->sphead;
|
||||||
|
|
||||||
|
if (sp->check_backpatch(YYTHD))
|
||||||
|
YYABORT;
|
||||||
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
|
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
|
||||||
sp->init_strings(YYTHD, lex, lex->spname);
|
sp->init_strings(YYTHD, lex, lex->spname);
|
||||||
/* Restore flag if it was cleared above */
|
/* Restore flag if it was cleared above */
|
||||||
@ -1816,7 +1823,8 @@ sp_proc_stmt:
|
|||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp = lex->sphead;
|
sp_head *sp = lex->sphead;
|
||||||
sp_label_t *lab= lex->spcont->find_label($2.str);
|
sp_pcontext *ctx= lex->spcont;
|
||||||
|
sp_label_t *lab= ctx->find_label($2.str);
|
||||||
|
|
||||||
if (! lab)
|
if (! lab)
|
||||||
{
|
{
|
||||||
@ -1825,8 +1833,20 @@ sp_proc_stmt:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sp_instr_jump *i= new sp_instr_jump(sp->instructions());
|
uint ip= sp->instructions();
|
||||||
|
sp_scope_t sdiff;
|
||||||
|
sp_instr_jump *i;
|
||||||
|
sp_instr_hpop *ih;
|
||||||
|
sp_instr_cpop *ic;
|
||||||
|
|
||||||
|
ctx->diff_scopes(0, &sdiff);
|
||||||
|
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
|
||||||
|
sp->push_backpatch(ih, lab);
|
||||||
|
sp->add_instr(ih);
|
||||||
|
ic= new sp_instr_cpop(ip++, sdiff.curs);
|
||||||
|
sp->push_backpatch(ic, lab);
|
||||||
|
sp->add_instr(ic);
|
||||||
|
i= new sp_instr_jump(ip);
|
||||||
sp->push_backpatch(i, lab); /* Jumping forward */
|
sp->push_backpatch(i, lab); /* Jumping forward */
|
||||||
sp->add_instr(i);
|
sp->add_instr(i);
|
||||||
}
|
}
|
||||||
@ -1834,19 +1854,101 @@ sp_proc_stmt:
|
|||||||
| ITERATE_SYM IDENT
|
| ITERATE_SYM IDENT
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_label_t *lab= lex->spcont->find_label($2.str);
|
sp_head *sp= lex->sphead;
|
||||||
|
sp_pcontext *ctx= lex->spcont;
|
||||||
|
sp_label_t *lab= ctx->find_label($2.str);
|
||||||
|
|
||||||
if (! lab || lab->isbegin)
|
if (! lab || lab->type != SP_LAB_ITER)
|
||||||
{
|
{
|
||||||
net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "ITERATE", $2.str);
|
net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "ITERATE", $2.str);
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint ip= lex->sphead->instructions();
|
sp_instr_jump *i;
|
||||||
sp_instr_jump *i= new sp_instr_jump(ip, lab->ip); /* Jump back */
|
uint ip= sp->instructions();
|
||||||
|
sp_scope_t sdiff;
|
||||||
|
|
||||||
lex->sphead->add_instr(i);
|
ctx->diff_scopes(lab->scopes, &sdiff);
|
||||||
|
if (sdiff.hndlrs)
|
||||||
|
sp->add_instr(new sp_instr_hpop(ip++, sdiff.hndlrs));
|
||||||
|
if (sdiff.curs)
|
||||||
|
sp->add_instr(new sp_instr_cpop(ip++, sdiff.curs));
|
||||||
|
i= new sp_instr_jump(ip, lab->ip); /* Jump back */
|
||||||
|
sp->add_instr(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| LABEL_SYM IDENT
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
sp_head *sp= lex->sphead;
|
||||||
|
sp_pcontext *ctx= lex->spcont;
|
||||||
|
sp_label_t *lab= ctx->find_label($2.str);
|
||||||
|
|
||||||
|
if (! lab)
|
||||||
|
lab= ctx->find_glabel($2.str);
|
||||||
|
if (lab)
|
||||||
|
{
|
||||||
|
net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $2.str);
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lab= ctx->push_glabel($2.str, sp->instructions());
|
||||||
|
lab->type= SP_LAB_GOTO;
|
||||||
|
lab->scopes= ctx->scopes();
|
||||||
|
sp->backpatch(lab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| GOTO_SYM IDENT
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
sp_head *sp= lex->sphead;
|
||||||
|
sp_pcontext *ctx= lex->spcont;
|
||||||
|
uint ip= lex->sphead->instructions();
|
||||||
|
sp_label_t *lab= ctx->find_label($2.str);
|
||||||
|
sp_scope_t sdiff;
|
||||||
|
sp_instr_jump *i;
|
||||||
|
sp_instr_hpop *ih;
|
||||||
|
sp_instr_cpop *ic;
|
||||||
|
|
||||||
|
if (! lab)
|
||||||
|
lab= ctx->find_glabel($2.str);
|
||||||
|
|
||||||
|
if (! lab)
|
||||||
|
{
|
||||||
|
lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t));
|
||||||
|
lab->name= $2.str;
|
||||||
|
lab->ip= 0;
|
||||||
|
lab->type= SP_LAB_REF;
|
||||||
|
lab->scopes= 0;
|
||||||
|
|
||||||
|
ctx->diff_scopes(0, &sdiff);
|
||||||
|
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
|
||||||
|
sp->push_backpatch(ih, lab);
|
||||||
|
sp->add_instr(ih);
|
||||||
|
ic= new sp_instr_cpop(ip++, sdiff.curs);
|
||||||
|
sp->add_instr(ic);
|
||||||
|
sp->push_backpatch(ic, lab);
|
||||||
|
i= new sp_instr_jump(ip);
|
||||||
|
sp->push_backpatch(i, lab); /* Jumping forward */
|
||||||
|
sp->add_instr(i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx->diff_scopes(lab->scopes, &sdiff);
|
||||||
|
if (sdiff.hndlrs)
|
||||||
|
{
|
||||||
|
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
|
||||||
|
sp->add_instr(ih);
|
||||||
|
}
|
||||||
|
if (sdiff.curs)
|
||||||
|
{
|
||||||
|
ic= new sp_instr_cpop(ip++, sdiff.curs);
|
||||||
|
sp->add_instr(ic);
|
||||||
|
}
|
||||||
|
i= new sp_instr_jump(ip, lab->ip); /* Jump back */
|
||||||
|
sp->add_instr(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| OPEN_SYM ident
|
| OPEN_SYM ident
|
||||||
@ -2041,7 +2143,8 @@ sp_labeled_control:
|
|||||||
IDENT ':'
|
IDENT ':'
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_label_t *lab= lex->spcont->find_label($1.str);
|
sp_pcontext *ctx= lex->spcont;
|
||||||
|
sp_label_t *lab= ctx->find_label($1.str);
|
||||||
|
|
||||||
if (lab)
|
if (lab)
|
||||||
{
|
{
|
||||||
@ -2050,8 +2153,10 @@ sp_labeled_control:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lex->spcont->push_label($1.str,
|
lab= lex->spcont->push_label($1.str,
|
||||||
lex->sphead->instructions());
|
lex->sphead->instructions());
|
||||||
|
lab->type= SP_LAB_ITER;
|
||||||
|
lab->scopes= ctx->scopes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sp_unlabeled_control sp_opt_label
|
sp_unlabeled_control sp_opt_label
|
||||||
@ -2088,27 +2193,33 @@ sp_unlabeled_control:
|
|||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_label_t *lab= lex->spcont->last_label();
|
sp_label_t *lab= lex->spcont->last_label();
|
||||||
|
|
||||||
lab->isbegin= TRUE;
|
lab->type= SP_LAB_BEGIN;
|
||||||
/* Scope duplicate checking */
|
/* Scope duplicate checking */
|
||||||
lex->spcont->push_scope();
|
lex->spcont->push_scope();
|
||||||
}
|
}
|
||||||
sp_decls
|
sp_decls
|
||||||
|
{
|
||||||
|
Lex->spcont->push_handlers($3.hndlrs);
|
||||||
|
}
|
||||||
sp_proc_stmts
|
sp_proc_stmts
|
||||||
END
|
END
|
||||||
{
|
{
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp= lex->sphead;
|
sp_head *sp= lex->sphead;
|
||||||
sp_pcontext *ctx= lex->spcont;
|
sp_pcontext *ctx= lex->spcont;
|
||||||
|
sp_scope_t scope;
|
||||||
|
|
||||||
sp->backpatch(ctx->last_label()); /* We always has a label */
|
sp->backpatch(ctx->last_label()); /* We always have a label */
|
||||||
ctx->pop_pvar($3.vars);
|
ctx->pop_pvar($3.vars);
|
||||||
ctx->pop_cond($3.conds);
|
ctx->pop_cond($3.conds);
|
||||||
|
ctx->pop_handlers($3.hndlrs);
|
||||||
ctx->pop_cursor($3.curs);
|
ctx->pop_cursor($3.curs);
|
||||||
if ($3.hndlrs)
|
if ($3.hndlrs)
|
||||||
sp->add_instr(new sp_instr_hpop(sp->instructions(),$3.hndlrs));
|
sp->add_instr(new sp_instr_hpop(sp->instructions(), $3.hndlrs));
|
||||||
if ($3.curs)
|
if ($3.curs)
|
||||||
sp->add_instr(new sp_instr_cpop(sp->instructions(), $3.curs));
|
sp->add_instr(new sp_instr_cpop(sp->instructions(), $3.curs));
|
||||||
ctx->pop_scope();
|
ctx->pop_scope(&scope);
|
||||||
|
ctx->pop_glabel(scope.glab);
|
||||||
}
|
}
|
||||||
| LOOP_SYM
|
| LOOP_SYM
|
||||||
sp_proc_stmts END LOOP_SYM
|
sp_proc_stmts END LOOP_SYM
|
||||||
|
Loading…
x
Reference in New Issue
Block a user