Commit 065f8066 authored by konstantin@mysql.com's avatar konstantin@mysql.com

Merge mysql.com:/home/kostja/mysql/mysql-5.0-for_merge

into  mysql.com:/home/kostja/mysql/mysql-5.1-merge
parents bcb4178c 88285b92
...@@ -2500,19 +2500,8 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, ...@@ -2500,19 +2500,8 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
*create_conn= 0; *create_conn= 0;
goto err; goto err;
} }
else
{
handle_no_error(q);
/* 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;
}
/* /*
TODO: change this to 0 in future versions, but the 'kill' test relies on 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'); ...@@ -617,3 +617,7 @@ select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn');
i v i v
4 3r4f 4 3r4f
drop table t1; 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 ...@@ -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 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 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 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 Output from mysqltest-x.inc
Output from mysqltest-x.inc Output from mysqltest-x.inc
......
...@@ -49,7 +49,7 @@ Pos Instruction ...@@ -49,7 +49,7 @@ Pos Instruction
9 set err@1 1 9 set err@1 1
10 hreturn 5 10 hreturn 5
11 cfetch c@0 n@4 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) 13 set nulls@2 (nulls@2 + 1)
14 jump 17 14 jump 17
15 set count@3 (count@3 + 1) 15 set count@3 (count@3 + 1)
......
...@@ -522,7 +522,7 @@ fetch c into v; ...@@ -522,7 +522,7 @@ fetch c into v;
end| end|
delete from t1| delete from t1|
call bug7299()| call bug7299()|
ERROR 02000: No data to FETCH ERROR 02000: No data - zero rows fetched, selected, or processed
drop procedure bug7299| drop procedure bug7299|
create procedure bug9073() create procedure bug9073()
begin begin
......
...@@ -522,7 +522,7 @@ delete from t1| ...@@ -522,7 +522,7 @@ delete from t1|
create table t3 ( s char(16), d int)| create table t3 ( s char(16), d int)|
call into_test4()| call into_test4()|
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
select * from t3| select * from t3|
s d s d
into4 NULL into4 NULL
...@@ -1787,10 +1787,10 @@ end| ...@@ -1787,10 +1787,10 @@ end|
call bug1863(10)| call bug1863(10)|
Warnings: Warnings:
Note 1051 Unknown table 'temp_t1' 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)| call bug1863(10)|
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
select * from t4| select * from t4|
f1 rc t3 f1 rc t3
2 0 NULL 2 0 NULL
...@@ -2084,10 +2084,10 @@ end| ...@@ -2084,10 +2084,10 @@ end|
call bug4579_1()| call bug4579_1()|
call bug4579_1()| call bug4579_1()|
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
call bug4579_1()| call bug4579_1()|
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
drop procedure bug4579_1| drop procedure bug4579_1|
drop procedure bug4579_2| drop procedure bug4579_2|
drop table t3| drop table t3|
...@@ -2507,7 +2507,7 @@ call bug7743("OneWord")| ...@@ -2507,7 +2507,7 @@ call bug7743("OneWord")|
var var
NULL NULL
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
call bug7743("anotherword")| call bug7743("anotherword")|
var var
2 2
...@@ -2515,7 +2515,7 @@ call bug7743("AnotherWord")| ...@@ -2515,7 +2515,7 @@ call bug7743("AnotherWord")|
var var
NULL NULL
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
drop procedure bug7743| drop procedure bug7743|
drop table t4| drop table t4|
delete from t3| delete from t3|
...@@ -4296,6 +4296,90 @@ id county ...@@ -4296,6 +4296,90 @@ id county
2 NULL 2 NULL
drop table t3| drop table t3|
drop procedure bug15441| 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 table if exists t3|
drop procedure if exists bug15231_1| drop procedure if exists bug15231_1|
drop procedure if exists bug15231_2| drop procedure if exists bug15231_2|
...@@ -4340,7 +4424,7 @@ After NOT FOUND condtition is triggered ...@@ -4340,7 +4424,7 @@ After NOT FOUND condtition is triggered
xid xdone xid xdone
1 0 1 0
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
call bug15231_3()| call bug15231_3()|
Result Result
Missed it (correct) Missed it (correct)
......
...@@ -537,10 +537,10 @@ select @@query_prealloc_size = @test; ...@@ -537,10 +537,10 @@ select @@query_prealloc_size = @test;
create table t1 (a int); create table t1 (a int);
select a into @x from t1; select a into @x from t1;
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
show warnings; show warnings;
Level Code Message Level Code Message
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
drop table t1; drop table t1;
set @@warning_count=1; set @@warning_count=1;
ERROR HY000: Variable 'warning_count' is a read only variable ERROR HY000: Variable 'warning_count' is a read only variable
......
...@@ -350,12 +350,12 @@ select * from v1; ...@@ -350,12 +350,12 @@ select * from v1;
f2() f2()
NULL NULL
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
select * from v2; select * from v2;
f2() f2()
NULL NULL
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
select * from v3; 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 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; select * from v4;
...@@ -396,12 +396,12 @@ select * from v3; ...@@ -396,12 +396,12 @@ select * from v3;
f2() f2()
NULL NULL
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
select * from v4; select * from v4;
f2() f2()
NULL NULL
Warnings: Warnings:
Warning 1329 No data to FETCH Warning 1329 No data - zero rows fetched, selected, or processed
select * from v5; 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 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; drop view v1, v2, v3, v4, v5;
......
...@@ -439,3 +439,13 @@ select * from t1; ...@@ -439,3 +439,13 @@ select * from t1;
alter table t1 add unique key (i, v); alter table t1 add unique key (i, v);
select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn'); select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn');
drop table t1; 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; ...@@ -909,7 +909,13 @@ select "a" as col1, "c" as col2;
--error 1 --error 1
--exec echo "source var/tmp/con.sql;" | $MYSQL_TEST 2>&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 # Test mysqltest arguments
......
...@@ -3753,7 +3753,7 @@ drop procedure if exists bug7088_2| ...@@ -3753,7 +3753,7 @@ drop procedure if exists bug7088_2|
--disable_parsing # temporarily disabled until Bar fixes BUG#11986 --disable_parsing # temporarily disabled until Bar fixes BUG#11986
create procedure bug6063() create procedure bug6063()
lbel: begin end| lâbel: begin end|
call bug6063()| call bug6063()|
# QQ Known bug: this will not show the label correctly. # QQ Known bug: this will not show the label correctly.
show create procedure bug6063| show create procedure bug6063|
...@@ -5048,6 +5048,93 @@ call bug15441('Yale')| ...@@ -5048,6 +5048,93 @@ call bug15441('Yale')|
drop table t3| drop table t3|
drop procedure bug15441| 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 # BUG#15231: Stored procedure bug with not found condition handler
......
...@@ -376,3 +376,4 @@ insert INTO t2 SELECT * FROM t1; ...@@ -376,3 +376,4 @@ insert INTO t2 SELECT * FROM t1;
select * from t2; select * from t2;
drop table t1, t2; drop table t1, t2;
...@@ -5172,8 +5172,8 @@ ER_SP_WRONG_NO_OF_FETCH_ARGS ...@@ -5172,8 +5172,8 @@ ER_SP_WRONG_NO_OF_FETCH_ARGS
eng "Incorrect number of FETCH variables" eng "Incorrect number of FETCH variables"
ger "Falsche Anzahl von FETCH-Variablen" ger "Falsche Anzahl von FETCH-Variablen"
ER_SP_FETCH_NO_DATA 02000 ER_SP_FETCH_NO_DATA 02000
eng "No data to FETCH" eng "No data - zero rows fetched, selected, or processed"
ger "Keine Daten mit FETCH abzuholen" ger "Keine Daten - null Zeilen geholt (fetch), ausgewhlt oder verarbeitet"
ER_SP_DUP_PARAM 42000 ER_SP_DUP_PARAM 42000
eng "Duplicate parameter: %s" eng "Duplicate parameter: %s"
ger "Doppelter Parameter: %s" ger "Doppelter Parameter: %s"
......
...@@ -433,7 +433,8 @@ sp_head::operator delete(void *ptr, size_t size) ...@@ -433,7 +433,8 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head() sp_head::sp_head()
:Query_arena(&main_mem_root, INITIALIZED_FOR_SP), :Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
m_flags(0), m_recursion_level(0), m_next_cached_sp(0), 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; m_return_field_def.charset = NULL;
...@@ -442,6 +443,7 @@ sp_head::sp_head() ...@@ -442,6 +443,7 @@ sp_head::sp_head()
DBUG_ENTER("sp_head::sp_head"); DBUG_ENTER("sp_head::sp_head");
m_backpatch.empty(); m_backpatch.empty();
m_cont_backpatch.empty();
m_lex.empty(); m_lex.empty();
hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0); 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); 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, ...@@ -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 void
sp_head::set_info(longlong created, longlong modified, sp_head::set_info(longlong created, longlong modified,
st_sp_chistics *chistics, ulong sql_mode) st_sp_chistics *chistics, ulong sql_mode)
...@@ -1964,7 +1999,10 @@ sp_head::show_create_function(THD *thd) ...@@ -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() void sp_head::optimize()
...@@ -1987,7 +2025,7 @@ void sp_head::optimize() ...@@ -1987,7 +2025,7 @@ void sp_head::optimize()
else else
{ {
if (src != dst) if (src != dst)
{ { // Move the instruction and update prev. jumps
sp_instr *ibp; sp_instr *ibp;
List_iterator_fast<sp_instr> li(bp); List_iterator_fast<sp_instr> li(bp);
...@@ -1995,8 +2033,7 @@ void sp_head::optimize() ...@@ -1995,8 +2033,7 @@ void sp_head::optimize()
while ((ibp= li++)) while ((ibp= li++))
{ {
sp_instr_jump *ji= static_cast<sp_instr_jump *>(ibp); sp_instr_jump *ji= static_cast<sp_instr_jump *>(ibp);
if (ji->m_dest == src) ji->set_destination(src, dst);
ji->m_dest= dst;
} }
} }
i->opt_move(dst, &bp); i->opt_move(dst, &bp);
...@@ -2429,67 +2466,6 @@ sp_instr_jump::opt_move(uint dst, List<sp_instr> *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 sp_instr_jump_if_not class functions
*/ */
...@@ -2511,7 +2487,10 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp) ...@@ -2511,7 +2487,10 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp)
it= sp_prepare_func_item(thd, &m_expr); it= sp_prepare_func_item(thd, &m_expr);
if (! it) if (! it)
{
res= -1; res= -1;
*nextp = m_cont_dest;
}
else else
{ {
res= 0; res= 0;
...@@ -2529,11 +2508,13 @@ void ...@@ -2529,11 +2508,13 @@ void
sp_instr_jump_if_not::print(String *str) sp_instr_jump_if_not::print(String *str)
{ {
/* jump_if_not dest ... */ /* 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; return;
str->qs_append(STRING_WITH_LEN("jump_if_not ")); str->qs_append(STRING_WITH_LEN("jump_if_not "));
str->qs_append(m_dest); str->qs_append(m_dest);
str->qs_append(' '); str->append('(');
str->qs_append(m_cont_dest);
str->append(") ");
m_expr->print(str); m_expr->print(str);
} }
...@@ -2550,9 +2531,35 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp) ...@@ -2550,9 +2531,35 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp)
m_optdest= sp->get_instr(m_dest); m_optdest= sp->get_instr(m_dest);
} }
sp->opt_mark(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; 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 sp_instr_freturn class functions
......
...@@ -41,6 +41,7 @@ sp_get_flags_for_command(LEX *lex); ...@@ -41,6 +41,7 @@ sp_get_flags_for_command(LEX *lex);
struct sp_label; struct sp_label;
class sp_instr; class sp_instr;
class sp_instr_jump_if_not;
struct sp_cond_type; struct sp_cond_type;
struct sp_pvar; struct sp_pvar;
...@@ -265,6 +266,18 @@ class sp_head :private Query_arena ...@@ -265,6 +266,18 @@ class sp_head :private Query_arena
int int
check_backpatch(THD *thd); 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 char *name(uint *lenp = 0) const
{ {
if (lenp) if (lenp)
...@@ -355,6 +368,18 @@ class sp_head :private Query_arena ...@@ -355,6 +368,18 @@ class sp_head :private Query_arena
sp_instr *instr; sp_instr *instr;
} bp_t; } bp_t;
List<bp_t> m_backpatch; // Instructions needing backpatching 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 Multi-set representing optimized list of tables to be locked by this
routine. Does not include tables which are used by invoked routines. routine. Does not include tables which are used by invoked routines.
...@@ -668,50 +693,17 @@ class sp_instr_jump : public sp_instr ...@@ -668,50 +693,17 @@ class sp_instr_jump : public sp_instr
m_dest= dest; m_dest= dest;
} }
protected: virtual void set_destination(uint old_dest, uint new_dest)
sp_instr *m_optdest; // Used during optimization
}; // 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; if (m_dest == old_dest)
m_dest= new_dest;
} }
private: protected:
Item *m_expr; // The condition sp_instr *m_optdest; // Used during optimization
sp_lex_keeper m_lex_keeper;
}; // class sp_instr_jump_if : public sp_instr_jump }; // class sp_instr_jump : public sp_instr
class sp_instr_jump_if_not : public sp_instr_jump class sp_instr_jump_if_not : public sp_instr_jump
...@@ -721,12 +713,16 @@ class sp_instr_jump_if_not : public sp_instr_jump ...@@ -721,12 +713,16 @@ class sp_instr_jump_if_not : public sp_instr_jump
public: 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_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_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() virtual ~sp_instr_jump_if_not()
...@@ -745,10 +741,20 @@ class sp_instr_jump_if_not : public sp_instr_jump ...@@ -745,10 +741,20 @@ class sp_instr_jump_if_not : public sp_instr_jump
return m_ip; 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: private:
Item *m_expr; // The condition Item *m_expr; // The condition
sp_lex_keeper m_lex_keeper; sp_lex_keeper m_lex_keeper;
sp_instr *m_cont_optdest; // Used during optimization
}; // class sp_instr_jump_if_not : public sp_instr_jump }; // class sp_instr_jump_if_not : public sp_instr_jump
......
...@@ -52,6 +52,15 @@ typedef struct sp_pvar ...@@ -52,6 +52,15 @@ typedef struct sp_pvar
#define SP_LAB_BEGIN 2 // Label at BEGIN #define SP_LAB_BEGIN 2 // Label at BEGIN
#define SP_LAB_ITER 3 // Label at iteration control #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 typedef struct sp_label
{ {
char *name; char *name;
......
...@@ -220,7 +220,7 @@ sp_rcontext::find_handler(uint sql_errno, ...@@ -220,7 +220,7 @@ sp_rcontext::find_handler(uint sql_errno,
Only "exception conditions" are propagated to handlers in calling Only "exception conditions" are propagated to handlers in calling
contexts. If no handler is found locally for a "completion condition" contexts. If no handler is found locally for a "completion condition"
(warning or "not found") we will simply resume execution. (warning or "not found") we will simply resume execution.
*/ */
if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) && if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR) level == MYSQL_ERROR::WARN_LEVEL_ERROR)
return m_prev_runtime_ctx->find_handler(sql_errno, level); return m_prev_runtime_ctx->find_handler(sql_errno, level);
......
...@@ -422,12 +422,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -422,12 +422,13 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (!lock) if (!lock)
goto err0; // mysql_lock_tables() printed error message already goto err0; // mysql_lock_tables() printed error message already
if (cond && ((!cond->fixed && if (cond)
cond->fix_fields(thd, &cond)) || cond->check_cols(1)))
{ {
if (table->query_id != thd->query_id) if (table->query_id != thd->query_id)
cond->cleanup(); // File was reopened cond->cleanup(); // File was reopened
goto err0; if ((!cond->fixed &&
cond->fix_fields(thd, &cond)) || cond->check_cols(1))
goto err0;
} }
if (keyname) if (keyname)
......
...@@ -2288,7 +2288,9 @@ sp_proc_stmt: ...@@ -2288,7 +2288,9 @@ sp_proc_stmt:
; ;
sp_proc_stmt_if: 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: sp_proc_stmt_statement:
...@@ -2366,13 +2368,17 @@ sp_proc_stmt_case_simple: ...@@ -2366,13 +2368,17 @@ sp_proc_stmt_case_simple:
CASE_SYM WHEN_SYM CASE_SYM WHEN_SYM
{ {
Lex->sphead->m_flags&= ~sp_head::IN_SIMPLE_CASE; 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: sp_proc_stmt_case:
CASE_SYM CASE_SYM
{ Lex->sphead->reset_lex(YYTHD); } {
Lex->sphead->reset_lex(YYTHD);
Lex->sphead->new_cont_backpatch(NULL);
}
expr WHEN_SYM expr WHEN_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -2396,6 +2402,7 @@ sp_proc_stmt_case: ...@@ -2396,6 +2402,7 @@ sp_proc_stmt_case:
sp_case END CASE_SYM sp_case END CASE_SYM
{ {
Lex->spcont->pop_case_expr_id(); Lex->spcont->pop_case_expr_id();
Lex->sphead->do_cont_backpatch();
} }
; ;
...@@ -2686,6 +2693,7 @@ sp_if: ...@@ -2686,6 +2693,7 @@ sp_if:
$2, lex); $2, lex);
sp->push_backpatch(i, ctx->push_label((char *)"", 0)); sp->push_backpatch(i, ctx->push_label((char *)"", 0));
sp->add_cont_backpatch(i);
sp->add_instr(i); sp->add_instr(i);
sp->restore_lex(YYTHD); sp->restore_lex(YYTHD);
} }
...@@ -2744,6 +2752,7 @@ sp_case: ...@@ -2744,6 +2752,7 @@ sp_case:
i= new sp_instr_jump_if_not(ip, ctx, expr, lex); i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
} }
sp->push_backpatch(i, ctx->push_label((char *)"", 0)); sp->push_backpatch(i, ctx->push_label((char *)"", 0));
sp->add_cont_backpatch(i);
sp->add_instr(i); sp->add_instr(i);
sp->restore_lex(YYTHD); sp->restore_lex(YYTHD);
} }
...@@ -2873,6 +2882,7 @@ sp_unlabeled_control: ...@@ -2873,6 +2882,7 @@ sp_unlabeled_control:
/* Jumping forward */ /* Jumping forward */
sp->push_backpatch(i, lex->spcont->last_label()); sp->push_backpatch(i, lex->spcont->last_label());
sp->new_cont_backpatch(i);
sp->add_instr(i); sp->add_instr(i);
sp->restore_lex(YYTHD); sp->restore_lex(YYTHD);
} }
...@@ -2884,6 +2894,7 @@ sp_unlabeled_control: ...@@ -2884,6 +2894,7 @@ sp_unlabeled_control:
sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip); sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
lex->sphead->add_instr(i); lex->sphead->add_instr(i);
lex->sphead->do_cont_backpatch();
} }
| REPEAT_SYM sp_proc_stmts1 UNTIL_SYM | REPEAT_SYM sp_proc_stmts1 UNTIL_SYM
{ Lex->sphead->reset_lex(YYTHD); } { Lex->sphead->reset_lex(YYTHD); }
...@@ -2897,6 +2908,8 @@ sp_unlabeled_control: ...@@ -2897,6 +2908,8 @@ sp_unlabeled_control:
lex); lex);
lex->sphead->add_instr(i); lex->sphead->add_instr(i);
lex->sphead->restore_lex(YYTHD); lex->sphead->restore_lex(YYTHD);
/* We can shortcut the cont_backpatch here */
i->m_cont_dest= ip+1;
} }
; ;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment