Merge mysql.com:/home/kostja/mysql/mysql-5.0-for_merge
into mysql.com:/home/kostja/mysql/mysql-5.1-merge client/mysqltest.c: Auto merged mysql-test/r/alter_table.result: Auto merged mysql-test/r/create.result: Auto merged mysql-test/r/ctype_ucs.result: Auto merged mysql-test/r/mysqltest.result: Auto merged mysql-test/r/ps.result: Auto merged mysql-test/r/sp-error.result: Auto merged mysql-test/r/sp.result: Auto merged mysql-test/r/type_decimal.result: Auto merged mysql-test/r/variables.result: Auto merged mysql-test/r/view_grant.result: Auto merged mysql-test/t/alter_table.test: Auto merged mysql-test/t/create.test: Auto merged mysql-test/t/ctype_ucs.test: Auto merged mysql-test/t/mysqltest.test: Auto merged mysql-test/t/ps.test: Auto merged mysql-test/t/sp.test: Auto merged sql/ha_berkeley.cc: Auto merged sql/sp_head.cc: Auto merged sql/sp_head.h: Auto merged sql/sql_handler.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_table.cc: Auto merged sql/share/errmsg.txt: Auto merged mysql-test/mysql-test-run.pl: SCCS merged sql/sql_yacc.yy: Manual merge: resolve the conflict with moved sp_if rule
This commit is contained in:
commit
f0263ac452
@ -2500,19 +2500,8 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
|
||||
*create_conn= 0;
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_no_error(q);
|
||||
|
||||
/*
|
||||
Fail if there was no error but we expected it.
|
||||
We also don't want to have connection in this case.
|
||||
*/
|
||||
mysql_close(con);
|
||||
*create_conn= 0;
|
||||
error= 1;
|
||||
goto err;
|
||||
}
|
||||
handle_no_error(q);
|
||||
|
||||
/*
|
||||
TODO: change this to 0 in future versions, but the 'kill' test relies on
|
||||
|
@ -617,3 +617,7 @@ select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn');
|
||||
i v
|
||||
4 3r4f
|
||||
drop table t1;
|
||||
create table t1 (t varchar(255) default null, key t (t(80)))
|
||||
engine=myisam default charset=latin1;
|
||||
alter table t1 change t t text;
|
||||
drop table t1;
|
||||
|
@ -361,6 +361,7 @@ OK
|
||||
mysqltest: In included file "./var/tmp/con.sql": At line 7: Connection limit exhausted - increase MAX_CONS in mysqltest.c
|
||||
mysqltest: In included file "./var/tmp/con.sql": At line 3: connection 'test_con1' not found in connection pool
|
||||
mysqltest: In included file "./var/tmp/con.sql": At line 2: Connection test_con1 already exists
|
||||
connect(localhost,root,,test,MASTER_PORT,MASTER_SOCKET);
|
||||
Output from mysqltest-x.inc
|
||||
Output from mysqltest-x.inc
|
||||
Output from mysqltest-x.inc
|
||||
|
@ -49,7 +49,7 @@ Pos Instruction
|
||||
9 set err@1 1
|
||||
10 hreturn 5
|
||||
11 cfetch c@0 n@4
|
||||
12 jump_if_not 15 isnull(n@4)
|
||||
12 jump_if_not 15(17) isnull(n@4)
|
||||
13 set nulls@2 (nulls@2 + 1)
|
||||
14 jump 17
|
||||
15 set count@3 (count@3 + 1)
|
||||
|
@ -522,7 +522,7 @@ fetch c into v;
|
||||
end|
|
||||
delete from t1|
|
||||
call bug7299()|
|
||||
ERROR 02000: No data to FETCH
|
||||
ERROR 02000: No data - zero rows fetched, selected, or processed
|
||||
drop procedure bug7299|
|
||||
create procedure bug9073()
|
||||
begin
|
||||
|
@ -522,7 +522,7 @@ delete from t1|
|
||||
create table t3 ( s char(16), d int)|
|
||||
call into_test4()|
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
select * from t3|
|
||||
s d
|
||||
into4 NULL
|
||||
@ -1787,10 +1787,10 @@ end|
|
||||
call bug1863(10)|
|
||||
Warnings:
|
||||
Note 1051 Unknown table 'temp_t1'
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
call bug1863(10)|
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
select * from t4|
|
||||
f1 rc t3
|
||||
2 0 NULL
|
||||
@ -2084,10 +2084,10 @@ end|
|
||||
call bug4579_1()|
|
||||
call bug4579_1()|
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
call bug4579_1()|
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
drop procedure bug4579_1|
|
||||
drop procedure bug4579_2|
|
||||
drop table t3|
|
||||
@ -2507,7 +2507,7 @@ call bug7743("OneWord")|
|
||||
var
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
call bug7743("anotherword")|
|
||||
var
|
||||
2
|
||||
@ -2515,7 +2515,7 @@ call bug7743("AnotherWord")|
|
||||
var
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
drop procedure bug7743|
|
||||
drop table t4|
|
||||
delete from t3|
|
||||
@ -4296,6 +4296,90 @@ id county
|
||||
2 NULL
|
||||
drop table t3|
|
||||
drop procedure bug15441|
|
||||
drop procedure if exists bug14498_1|
|
||||
drop procedure if exists bug14498_2|
|
||||
drop procedure if exists bug14498_3|
|
||||
drop procedure if exists bug14498_4|
|
||||
drop procedure if exists bug14498_5|
|
||||
create procedure bug14498_1()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
if v then
|
||||
select 'yes' as 'v';
|
||||
else
|
||||
select 'no' as 'v';
|
||||
end if;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
create procedure bug14498_2()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
while v do
|
||||
select 'yes' as 'v';
|
||||
end while;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
create procedure bug14498_3()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
repeat
|
||||
select 'maybe' as 'v';
|
||||
until v end repeat;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
create procedure bug14498_4()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
case v
|
||||
when 1 then
|
||||
select '1' as 'v';
|
||||
when 2 then
|
||||
select '2' as 'v';
|
||||
else
|
||||
select '?' as 'v';
|
||||
end case;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
create procedure bug14498_5()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
case
|
||||
when v = 1 then
|
||||
select '1' as 'v';
|
||||
when v = 2 then
|
||||
select '2' as 'v';
|
||||
else
|
||||
select '?' as 'v';
|
||||
end case;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
call bug14498_1()|
|
||||
Handler
|
||||
error
|
||||
End
|
||||
done
|
||||
call bug14498_2()|
|
||||
Handler
|
||||
error
|
||||
End
|
||||
done
|
||||
call bug14498_3()|
|
||||
v
|
||||
maybe
|
||||
Handler
|
||||
error
|
||||
End
|
||||
done
|
||||
call bug14498_5()|
|
||||
Handler
|
||||
error
|
||||
End
|
||||
done
|
||||
drop procedure bug14498_1|
|
||||
drop procedure bug14498_2|
|
||||
drop procedure bug14498_3|
|
||||
drop procedure bug14498_4|
|
||||
drop procedure bug14498_5|
|
||||
drop table if exists t3|
|
||||
drop procedure if exists bug15231_1|
|
||||
drop procedure if exists bug15231_2|
|
||||
@ -4340,7 +4424,7 @@ After NOT FOUND condtition is triggered
|
||||
xid xdone
|
||||
1 0
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
call bug15231_3()|
|
||||
Result
|
||||
Missed it (correct)
|
||||
|
@ -537,10 +537,10 @@ select @@query_prealloc_size = @test;
|
||||
create table t1 (a int);
|
||||
select a into @x from t1;
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
drop table t1;
|
||||
set @@warning_count=1;
|
||||
ERROR HY000: Variable 'warning_count' is a read only variable
|
||||
|
@ -350,12 +350,12 @@ select * from v1;
|
||||
f2()
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
select * from v2;
|
||||
f2()
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
select * from v3;
|
||||
ERROR HY000: View 'mysqltest.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
select * from v4;
|
||||
@ -396,12 +396,12 @@ select * from v3;
|
||||
f2()
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
select * from v4;
|
||||
f2()
|
||||
NULL
|
||||
Warnings:
|
||||
Warning 1329 No data to FETCH
|
||||
Warning 1329 No data - zero rows fetched, selected, or processed
|
||||
select * from v5;
|
||||
ERROR HY000: View 'mysqltest.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
|
||||
drop view v1, v2, v3, v4, v5;
|
||||
|
@ -439,3 +439,13 @@ select * from t1;
|
||||
alter table t1 add unique key (i, v);
|
||||
select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn');
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#6073 "ALTER table minor glich": ALTER TABLE complains that an index
|
||||
# without # prefix is not allowed for TEXT columns, while index
|
||||
# is defined with prefix.
|
||||
#
|
||||
create table t1 (t varchar(255) default null, key t (t(80)))
|
||||
engine=myisam default charset=latin1;
|
||||
alter table t1 change t t text;
|
||||
drop table t1;
|
||||
|
@ -909,7 +909,13 @@ select "a" as col1, "c" as col2;
|
||||
--error 1
|
||||
--exec echo "source var/tmp/con.sql;" | $MYSQL_TEST 2>&1
|
||||
|
||||
|
||||
# connect when "disable_abort_on_error" caused "connection not found"
|
||||
--replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT
|
||||
--disable_abort_on_error
|
||||
connect (con1,localhost,root,,);
|
||||
connection default;
|
||||
connection con1;
|
||||
--enable_abort_on_error
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Test mysqltest arguments
|
||||
|
@ -3753,7 +3753,7 @@ drop procedure if exists bug7088_2|
|
||||
|
||||
--disable_parsing # temporarily disabled until Bar fixes BUG#11986
|
||||
create procedure bug6063()
|
||||
lâbel: begin end|
|
||||
lâbel: begin end|
|
||||
call bug6063()|
|
||||
# QQ Known bug: this will not show the label correctly.
|
||||
show create procedure bug6063|
|
||||
@ -5048,6 +5048,93 @@ call bug15441('Yale')|
|
||||
drop table t3|
|
||||
drop procedure bug15441|
|
||||
|
||||
#
|
||||
# BUG#14498: Stored procedures: hang if undefined variable and exception
|
||||
#
|
||||
--disable_warnings
|
||||
drop procedure if exists bug14498_1|
|
||||
drop procedure if exists bug14498_2|
|
||||
drop procedure if exists bug14498_3|
|
||||
drop procedure if exists bug14498_4|
|
||||
drop procedure if exists bug14498_5|
|
||||
--enable_warnings
|
||||
|
||||
create procedure bug14498_1()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
|
||||
if v then
|
||||
select 'yes' as 'v';
|
||||
else
|
||||
select 'no' as 'v';
|
||||
end if;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
|
||||
create procedure bug14498_2()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
|
||||
while v do
|
||||
select 'yes' as 'v';
|
||||
end while;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
|
||||
create procedure bug14498_3()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
|
||||
repeat
|
||||
select 'maybe' as 'v';
|
||||
until v end repeat;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
|
||||
create procedure bug14498_4()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
|
||||
case v
|
||||
when 1 then
|
||||
select '1' as 'v';
|
||||
when 2 then
|
||||
select '2' as 'v';
|
||||
else
|
||||
select '?' as 'v';
|
||||
end case;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
|
||||
create procedure bug14498_5()
|
||||
begin
|
||||
declare continue handler for sqlexception select 'error' as 'Handler';
|
||||
|
||||
case
|
||||
when v = 1 then
|
||||
select '1' as 'v';
|
||||
when v = 2 then
|
||||
select '2' as 'v';
|
||||
else
|
||||
select '?' as 'v';
|
||||
end case;
|
||||
select 'done' as 'End';
|
||||
end|
|
||||
|
||||
call bug14498_1()|
|
||||
call bug14498_2()|
|
||||
call bug14498_3()|
|
||||
# We couldn't call this before, due to a known bug (BUG#14643)
|
||||
# QQ We still can't since the new set_case_expr instruction breaks
|
||||
# the semantics of case; it won't crash, but will get the wrong result.
|
||||
#call bug14498_4()|
|
||||
call bug14498_5()|
|
||||
|
||||
drop procedure bug14498_1|
|
||||
drop procedure bug14498_2|
|
||||
drop procedure bug14498_3|
|
||||
drop procedure bug14498_4|
|
||||
drop procedure bug14498_5|
|
||||
|
||||
#
|
||||
# BUG#15231: Stored procedure bug with not found condition handler
|
||||
|
@ -376,3 +376,4 @@ insert INTO t2 SELECT * FROM t1;
|
||||
|
||||
select * from t2;
|
||||
drop table t1, t2;
|
||||
|
||||
|
@ -5172,8 +5172,8 @@ ER_SP_WRONG_NO_OF_FETCH_ARGS
|
||||
eng "Incorrect number of FETCH variables"
|
||||
ger "Falsche Anzahl von FETCH-Variablen"
|
||||
ER_SP_FETCH_NO_DATA 02000
|
||||
eng "No data to FETCH"
|
||||
ger "Keine Daten mit FETCH abzuholen"
|
||||
eng "No data - zero rows fetched, selected, or processed"
|
||||
ger "Keine Daten - null Zeilen geholt (fetch), ausgewählt oder verarbeitet"
|
||||
ER_SP_DUP_PARAM 42000
|
||||
eng "Duplicate parameter: %s"
|
||||
ger "Doppelter Parameter: %s"
|
||||
|
143
sql/sp_head.cc
143
sql/sp_head.cc
@ -433,7 +433,8 @@ sp_head::operator delete(void *ptr, size_t size)
|
||||
sp_head::sp_head()
|
||||
:Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
|
||||
m_flags(0), m_recursion_level(0), m_next_cached_sp(0),
|
||||
m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this)
|
||||
m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this),
|
||||
m_cont_level(0)
|
||||
{
|
||||
m_return_field_def.charset = NULL;
|
||||
|
||||
@ -442,6 +443,7 @@ sp_head::sp_head()
|
||||
DBUG_ENTER("sp_head::sp_head");
|
||||
|
||||
m_backpatch.empty();
|
||||
m_cont_backpatch.empty();
|
||||
m_lex.empty();
|
||||
hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0);
|
||||
hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0);
|
||||
@ -1750,6 +1752,39 @@ sp_head::fill_field_definition(THD *thd, LEX *lex,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sp_head::new_cont_backpatch(sp_instr_jump_if_not *i)
|
||||
{
|
||||
m_cont_level+= 1;
|
||||
if (i)
|
||||
{
|
||||
/* Use the cont. destination slot to store the level */
|
||||
i->m_cont_dest= m_cont_level;
|
||||
(void)m_cont_backpatch.push_front(i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sp_head::add_cont_backpatch(sp_instr_jump_if_not *i)
|
||||
{
|
||||
i->m_cont_dest= m_cont_level;
|
||||
(void)m_cont_backpatch.push_front(i);
|
||||
}
|
||||
|
||||
void
|
||||
sp_head::do_cont_backpatch()
|
||||
{
|
||||
uint dest= instructions();
|
||||
uint lev= m_cont_level--;
|
||||
sp_instr_jump_if_not *i;
|
||||
|
||||
while ((i= m_cont_backpatch.head()) && i->m_cont_dest == lev)
|
||||
{
|
||||
i->m_cont_dest= dest;
|
||||
(void)m_cont_backpatch.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sp_head::set_info(longlong created, longlong modified,
|
||||
st_sp_chistics *chistics, ulong sql_mode)
|
||||
@ -1964,7 +1999,10 @@ sp_head::show_create_function(THD *thd)
|
||||
|
||||
|
||||
/*
|
||||
TODO: what does this do??
|
||||
Do some minimal optimization of the code:
|
||||
1) Mark used instructions
|
||||
1.1) While doing this, shortcut jumps to jump instructions
|
||||
2) Compact the code, removing unused instructions
|
||||
*/
|
||||
|
||||
void sp_head::optimize()
|
||||
@ -1987,7 +2025,7 @@ void sp_head::optimize()
|
||||
else
|
||||
{
|
||||
if (src != dst)
|
||||
{
|
||||
{ // Move the instruction and update prev. jumps
|
||||
sp_instr *ibp;
|
||||
List_iterator_fast<sp_instr> li(bp);
|
||||
|
||||
@ -1995,8 +2033,7 @@ void sp_head::optimize()
|
||||
while ((ibp= li++))
|
||||
{
|
||||
sp_instr_jump *ji= static_cast<sp_instr_jump *>(ibp);
|
||||
if (ji->m_dest == src)
|
||||
ji->m_dest= dst;
|
||||
ji->set_destination(src, dst);
|
||||
}
|
||||
}
|
||||
i->opt_move(dst, &bp);
|
||||
@ -2429,67 +2466,6 @@ sp_instr_jump::opt_move(uint dst, List<sp_instr> *bp)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
sp_instr_jump_if class functions
|
||||
*/
|
||||
|
||||
int
|
||||
sp_instr_jump_if::execute(THD *thd, uint *nextp)
|
||||
{
|
||||
DBUG_ENTER("sp_instr_jump_if::execute");
|
||||
DBUG_PRINT("info", ("destination: %u", m_dest));
|
||||
DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this));
|
||||
}
|
||||
|
||||
int
|
||||
sp_instr_jump_if::exec_core(THD *thd, uint *nextp)
|
||||
{
|
||||
Item *it;
|
||||
int res;
|
||||
|
||||
it= sp_prepare_func_item(thd, &m_expr);
|
||||
if (!it)
|
||||
res= -1;
|
||||
else
|
||||
{
|
||||
res= 0;
|
||||
if (it->val_bool())
|
||||
*nextp = m_dest;
|
||||
else
|
||||
*nextp = m_ip+1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
sp_instr_jump_if::print(String *str)
|
||||
{
|
||||
/* jump_if dest ... */
|
||||
if (str->reserve(SP_INSTR_UINT_MAXLEN+8+32)) // Add some for the expr. too
|
||||
return;
|
||||
str->qs_append(STRING_WITH_LEN("jump_if "));
|
||||
str->qs_append(m_dest);
|
||||
str->qs_append(' ');
|
||||
m_expr->print(str);
|
||||
}
|
||||
|
||||
uint
|
||||
sp_instr_jump_if::opt_mark(sp_head *sp)
|
||||
{
|
||||
sp_instr *i;
|
||||
|
||||
marked= 1;
|
||||
if ((i= sp->get_instr(m_dest)))
|
||||
{
|
||||
m_dest= i->opt_shortcut_jump(sp, this);
|
||||
m_optdest= sp->get_instr(m_dest);
|
||||
}
|
||||
sp->opt_mark(m_dest);
|
||||
return m_ip+1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
sp_instr_jump_if_not class functions
|
||||
*/
|
||||
@ -2511,7 +2487,10 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp)
|
||||
|
||||
it= sp_prepare_func_item(thd, &m_expr);
|
||||
if (! it)
|
||||
{
|
||||
res= -1;
|
||||
*nextp = m_cont_dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
res= 0;
|
||||
@ -2529,11 +2508,13 @@ void
|
||||
sp_instr_jump_if_not::print(String *str)
|
||||
{
|
||||
/* jump_if_not dest ... */
|
||||
if (str->reserve(SP_INSTR_UINT_MAXLEN+12+32)) // Add some for the expr. too
|
||||
if (str->reserve(2*SP_INSTR_UINT_MAXLEN+14+32)) // Add some for the expr. too
|
||||
return;
|
||||
str->qs_append(STRING_WITH_LEN("jump_if_not "));
|
||||
str->qs_append(m_dest);
|
||||
str->qs_append(' ');
|
||||
str->append('(');
|
||||
str->qs_append(m_cont_dest);
|
||||
str->append(") ");
|
||||
m_expr->print(str);
|
||||
}
|
||||
|
||||
@ -2550,9 +2531,35 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp)
|
||||
m_optdest= sp->get_instr(m_dest);
|
||||
}
|
||||
sp->opt_mark(m_dest);
|
||||
if ((i= sp->get_instr(m_cont_dest)))
|
||||
{
|
||||
m_cont_dest= i->opt_shortcut_jump(sp, this);
|
||||
m_cont_optdest= sp->get_instr(m_cont_dest);
|
||||
}
|
||||
sp->opt_mark(m_cont_dest);
|
||||
return m_ip+1;
|
||||
}
|
||||
|
||||
void
|
||||
sp_instr_jump_if_not::opt_move(uint dst, List<sp_instr> *bp)
|
||||
{
|
||||
/*
|
||||
cont. destinations may point backwards after shortcutting jumps
|
||||
during the mark phase. If it's still pointing forwards, only
|
||||
push this for backpatching if sp_instr_jump::opt_move() will not
|
||||
do it (i.e. if the m_dest points backwards).
|
||||
*/
|
||||
if (m_cont_dest > m_ip)
|
||||
{ // Forward
|
||||
if (m_dest < m_ip)
|
||||
bp->push_back(this);
|
||||
}
|
||||
else if (m_cont_optdest)
|
||||
m_cont_dest= m_cont_optdest->m_ip; // Backward
|
||||
/* This will take care of m_dest and m_ip */
|
||||
sp_instr_jump::opt_move(dst, bp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
sp_instr_freturn class functions
|
||||
|
@ -41,6 +41,7 @@ sp_get_flags_for_command(LEX *lex);
|
||||
|
||||
struct sp_label;
|
||||
class sp_instr;
|
||||
class sp_instr_jump_if_not;
|
||||
struct sp_cond_type;
|
||||
struct sp_pvar;
|
||||
|
||||
@ -265,6 +266,18 @@ public:
|
||||
int
|
||||
check_backpatch(THD *thd);
|
||||
|
||||
// Start a new cont. backpatch level. If 'i' is NULL, the level is just incr.
|
||||
void
|
||||
new_cont_backpatch(sp_instr_jump_if_not *i);
|
||||
|
||||
// Add an instruction to the current level
|
||||
void
|
||||
add_cont_backpatch(sp_instr_jump_if_not *i);
|
||||
|
||||
// Backpatch (and pop) the current level to the current position.
|
||||
void
|
||||
do_cont_backpatch();
|
||||
|
||||
char *name(uint *lenp = 0) const
|
||||
{
|
||||
if (lenp)
|
||||
@ -355,6 +368,18 @@ private:
|
||||
sp_instr *instr;
|
||||
} bp_t;
|
||||
List<bp_t> m_backpatch; // Instructions needing backpatching
|
||||
/*
|
||||
We need a special list for backpatching of conditional jump's continue
|
||||
destination (in the case of a continue handler catching an error in
|
||||
the test), since it would otherwise interfere with the normal backpatch
|
||||
mechanism - jump_if_not instructions have two different destination
|
||||
which are to be patched differently.
|
||||
Since these occur in a more restricted way (always the same "level" in
|
||||
the code), we don't need the label.
|
||||
*/
|
||||
List<sp_instr_jump_if_not> m_cont_backpatch;
|
||||
uint m_cont_level; // The current cont. backpatch level
|
||||
|
||||
/*
|
||||
Multi-set representing optimized list of tables to be locked by this
|
||||
routine. Does not include tables which are used by invoked routines.
|
||||
@ -668,6 +693,12 @@ public:
|
||||
m_dest= dest;
|
||||
}
|
||||
|
||||
virtual void set_destination(uint old_dest, uint new_dest)
|
||||
{
|
||||
if (m_dest == old_dest)
|
||||
m_dest= new_dest;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
sp_instr *m_optdest; // Used during optimization
|
||||
@ -675,45 +706,6 @@ protected:
|
||||
}; // 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, sp_pcontext *ctx, Item *i, LEX *lex)
|
||||
: sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE)
|
||||
{}
|
||||
|
||||
sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
|
||||
: sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_jump_if()
|
||||
{}
|
||||
|
||||
virtual int execute(THD *thd, uint *nextp);
|
||||
|
||||
virtual int exec_core(THD *thd, uint *nextp);
|
||||
|
||||
virtual void print(String *str);
|
||||
|
||||
virtual uint opt_mark(sp_head *sp);
|
||||
|
||||
virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
|
||||
{
|
||||
return m_ip;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Item *m_expr; // The condition
|
||||
sp_lex_keeper m_lex_keeper;
|
||||
|
||||
}; // 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 */
|
||||
@ -721,12 +713,16 @@ class sp_instr_jump_if_not : public sp_instr_jump
|
||||
|
||||
public:
|
||||
|
||||
uint m_cont_dest; // Where continue handlers will go
|
||||
|
||||
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, LEX *lex)
|
||||
: sp_instr_jump(ip, ctx), m_expr(i), m_lex_keeper(lex, TRUE)
|
||||
: sp_instr_jump(ip, ctx), m_cont_dest(0), m_expr(i),
|
||||
m_lex_keeper(lex, TRUE), m_cont_optdest(0)
|
||||
{}
|
||||
|
||||
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest, LEX *lex)
|
||||
: sp_instr_jump(ip, ctx, dest), m_expr(i), m_lex_keeper(lex, TRUE)
|
||||
: sp_instr_jump(ip, ctx, dest), m_cont_dest(0), m_expr(i),
|
||||
m_lex_keeper(lex, TRUE), m_cont_optdest(0)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_jump_if_not()
|
||||
@ -745,10 +741,20 @@ public:
|
||||
return m_ip;
|
||||
}
|
||||
|
||||
virtual void opt_move(uint dst, List<sp_instr> *ibp);
|
||||
|
||||
virtual void set_destination(uint old_dest, uint new_dest)
|
||||
{
|
||||
sp_instr_jump::set_destination(old_dest, new_dest);
|
||||
if (m_cont_dest == old_dest)
|
||||
m_cont_dest= new_dest;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Item *m_expr; // The condition
|
||||
sp_lex_keeper m_lex_keeper;
|
||||
sp_instr *m_cont_optdest; // Used during optimization
|
||||
|
||||
}; // class sp_instr_jump_if_not : public sp_instr_jump
|
||||
|
||||
|
@ -52,6 +52,15 @@ typedef struct sp_pvar
|
||||
#define SP_LAB_BEGIN 2 // Label at BEGIN
|
||||
#define SP_LAB_ITER 3 // Label at iteration control
|
||||
|
||||
/*
|
||||
An SQL/PSM label. Can refer to the identifier used with the
|
||||
"label_name:" construct which may precede some SQL/PSM statements, or
|
||||
to an implicit implementation-dependent identifier which the parser
|
||||
inserts before a high-level flow control statement such as
|
||||
IF/WHILE/REPEAT/LOOP, when such statement is rewritten into
|
||||
a combination of low-level jump/jump_if instructions and labels.
|
||||
*/
|
||||
|
||||
typedef struct sp_label
|
||||
{
|
||||
char *name;
|
||||
|
@ -220,7 +220,7 @@ sp_rcontext::find_handler(uint sql_errno,
|
||||
Only "exception conditions" are propagated to handlers in calling
|
||||
contexts. If no handler is found locally for a "completion condition"
|
||||
(warning or "not found") we will simply resume execution.
|
||||
*/
|
||||
*/
|
||||
if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) &&
|
||||
level == MYSQL_ERROR::WARN_LEVEL_ERROR)
|
||||
return m_prev_runtime_ctx->find_handler(sql_errno, level);
|
||||
|
@ -422,12 +422,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
if (!lock)
|
||||
goto err0; // mysql_lock_tables() printed error message already
|
||||
|
||||
if (cond && ((!cond->fixed &&
|
||||
cond->fix_fields(thd, &cond)) || cond->check_cols(1)))
|
||||
if (cond)
|
||||
{
|
||||
if (table->query_id != thd->query_id)
|
||||
cond->cleanup(); // File was reopened
|
||||
goto err0;
|
||||
if ((!cond->fixed &&
|
||||
cond->fix_fields(thd, &cond)) || cond->check_cols(1))
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (keyname)
|
||||
|
@ -2288,7 +2288,9 @@ sp_proc_stmt:
|
||||
;
|
||||
|
||||
sp_proc_stmt_if:
|
||||
IF sp_if END IF {}
|
||||
IF { Lex->sphead->new_cont_backpatch(NULL); }
|
||||
sp_if END IF
|
||||
{ Lex->sphead->do_cont_backpatch(); }
|
||||
;
|
||||
|
||||
sp_proc_stmt_statement:
|
||||
@ -2366,13 +2368,17 @@ sp_proc_stmt_case_simple:
|
||||
CASE_SYM WHEN_SYM
|
||||
{
|
||||
Lex->sphead->m_flags&= ~sp_head::IN_SIMPLE_CASE;
|
||||
Lex->sphead->new_cont_backpatch(NULL);
|
||||
}
|
||||
sp_case END CASE_SYM {}
|
||||
sp_case END CASE_SYM { Lex->sphead->do_cont_backpatch(); }
|
||||
;
|
||||
|
||||
sp_proc_stmt_case:
|
||||
CASE_SYM
|
||||
{ Lex->sphead->reset_lex(YYTHD); }
|
||||
{
|
||||
Lex->sphead->reset_lex(YYTHD);
|
||||
Lex->sphead->new_cont_backpatch(NULL);
|
||||
}
|
||||
expr WHEN_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
@ -2396,6 +2402,7 @@ sp_proc_stmt_case:
|
||||
sp_case END CASE_SYM
|
||||
{
|
||||
Lex->spcont->pop_case_expr_id();
|
||||
Lex->sphead->do_cont_backpatch();
|
||||
}
|
||||
;
|
||||
|
||||
@ -2686,6 +2693,7 @@ sp_if:
|
||||
$2, lex);
|
||||
|
||||
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
||||
sp->add_cont_backpatch(i);
|
||||
sp->add_instr(i);
|
||||
sp->restore_lex(YYTHD);
|
||||
}
|
||||
@ -2744,6 +2752,7 @@ sp_case:
|
||||
i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
|
||||
}
|
||||
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
||||
sp->add_cont_backpatch(i);
|
||||
sp->add_instr(i);
|
||||
sp->restore_lex(YYTHD);
|
||||
}
|
||||
@ -2873,6 +2882,7 @@ sp_unlabeled_control:
|
||||
|
||||
/* Jumping forward */
|
||||
sp->push_backpatch(i, lex->spcont->last_label());
|
||||
sp->new_cont_backpatch(i);
|
||||
sp->add_instr(i);
|
||||
sp->restore_lex(YYTHD);
|
||||
}
|
||||
@ -2884,6 +2894,7 @@ sp_unlabeled_control:
|
||||
sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
|
||||
|
||||
lex->sphead->add_instr(i);
|
||||
lex->sphead->do_cont_backpatch();
|
||||
}
|
||||
| REPEAT_SYM sp_proc_stmts1 UNTIL_SYM
|
||||
{ Lex->sphead->reset_lex(YYTHD); }
|
||||
@ -2897,6 +2908,8 @@ sp_unlabeled_control:
|
||||
lex);
|
||||
lex->sphead->add_instr(i);
|
||||
lex->sphead->restore_lex(YYTHD);
|
||||
/* We can shortcut the cont_backpatch here */
|
||||
i->m_cont_dest= ip+1;
|
||||
}
|
||||
;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user