Commit c4871b24 authored by pem@mysql.comhem.se's avatar pem@mysql.comhem.se

Fixed BUG#1862 (flush table in SPs didn't work).

Fixed various bugs: setting local variables to NULL, SELECT INTO var now actually
might work, SELECT INTO with not row now gives a "no data" warning (instead of
the "empty query" error), etc.
Updated test cases accordingly.
parent e44a0c2a
......@@ -187,7 +187,7 @@ end;
call p();
ERROR HY000: Cursor is not open
drop procedure p;
alter procedure bar3 SECURITY INVOKER;
alter procedure bar3 sql security invoker;
ERROR HY000: PROCEDURE bar3 does not exist
alter procedure bar3 name
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
......
......@@ -75,6 +75,23 @@ id data
locset 21
delete from t1;
drop procedure locset;
drop table if exists t3;
create table t3 ( d date, i int, f double, s varchar(32) );
create procedure nullset()
begin
declare ld date;
declare li int;
declare lf double;
declare ls varchar(32);
set ld = null, li = null, lf = null, ls = null;
insert into t3 values (ld, li, lf, ls);
end;
call nullset();
select * from t3;
d i f s
NULL NULL NULL NULL
drop table t3;
drop procedure nullset;
create procedure mixset(x char(16), y int)
begin
declare z int;
......@@ -390,6 +407,47 @@ into 100 100
into2 102 100
delete from t1;
drop procedure into_test2;
create procedure into_test3()
begin
declare x char(16);
declare y int;
select * into x,y from test.t1 limit 1;
insert into test.t2 values (x, y, 0.0);
end;
insert into t1 values ("into3", 19);
delete from t2;
call into_test3();
call into_test3();
select * from t2;
s i d
into3 19 0
into3 19 0
delete from t1;
delete from t2;
drop procedure into_test3;
create procedure into_test4()
begin
declare x int;
select data into x from test.t1 limit 1;
insert into test.t3 values ("into4", x);
end;
delete from t1;
drop table if exists t3;
create table t3 ( s char(16), d int);
call into_test4();
Warnings:
select * from t3;
s d
into4 NULL
insert into t1 values ("i4", 77);
call into_test4();
select * from t3;
s d
into4 NULL
into4 77
delete from t1;
drop table t3;
drop procedure into_test4;
create procedure into_outfile(x char(16), y int)
begin
insert into test.t1 values (x, y);
......@@ -475,9 +533,6 @@ s i d
xxxyyy 12 2.71828182845905
select * from t2;
s i d
a 1 1.1
b 2 1.2
c 3 1.3
xxxyyy 12 2.71828182845905
ab 24 1324.36598821719
delete from t2;
......@@ -551,7 +606,7 @@ create procedure hndlr4()
begin
declare x int default 0;
declare val int; # No default
declare continue handler for sqlexception set x=1;
declare continue handler for 1306 set x=1;
select data into val from test.t3 where id='z' limit 1; # No hits
insert into test.t3 values ('z', val);
end;
......@@ -695,6 +750,21 @@ select @1, @2;
2 NULL
drop table t70;
drop procedure bug1656;
drop table if exists t3;
create table t3(a int);
create procedure bug1862()
begin
insert into t3 values(2);
flush tables;
end;
call bug1862();
call bug1862();
select * from t3;
a
2
2
drop table t3;
drop procedure bug1862;
drop table if exists fac;
create table fac (n int unsigned not null primary key, f bigint unsigned);
create procedure ifac(n int unsigned)
......@@ -839,21 +909,22 @@ drop table primes;
drop procedure opp;
drop procedure ip;
create procedure bar(x char(16), y int)
comment "111111111111" SECURITY INVOKER
comment "111111111111" sql security invoker
insert into test.t1 values (x, y);
show procedure status like 'bar';
Name Type Creator Modified Created Suid Comment
bar procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 N 111111111111
alter procedure bar name bar2 comment "2222222222" SECURITY DEFINER;
alter procedure bar name bar2 comment "2222222222" sql security definer;
alter procedure bar2 name bar comment "3333333333";
alter procedure bar;
show create procedure bar;
Procedure Create Procedure
bar create procedure bar(x char(16), y int)
comment "111111111111" SECURITY INVOKER
comment "111111111111" sql security invoker
insert into test.t1 values (x, y)
show procedure status like 'bar';
Name Type Creator Modified Created Suid Comment
bar procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y 3333333333
drop procedure bar;
drop table t1;
drop table t2;
......@@ -257,7 +257,7 @@ call p()|
drop procedure p|
--error 1282
alter procedure bar3 SECURITY INVOKER|
alter procedure bar3 sql security invoker|
--error 1059
alter procedure bar3 name
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|
......
......@@ -109,6 +109,29 @@ delete from t1|
drop procedure locset|
# Set things to null
--disable_warnings
drop table if exists t3|
--enable_warnings
create table t3 ( d date, i int, f double, s varchar(32) )|
create procedure nullset()
begin
declare ld date;
declare li int;
declare lf double;
declare ls varchar(32);
set ld = null, li = null, lf = null, ls = null;
insert into t3 values (ld, li, lf, ls);
end|
call nullset()|
select * from t3|
drop table t3|
drop procedure nullset|
# The peculiar (non-standard) mixture of variables types in SET.
create procedure mixset(x char(16), y int)
begin
......@@ -460,6 +483,52 @@ delete from t1|
drop procedure into_test2|
# SELECT * INTO ... (bug test)
create procedure into_test3()
begin
declare x char(16);
declare y int;
select * into x,y from test.t1 limit 1;
insert into test.t2 values (x, y, 0.0);
end|
insert into t1 values ("into3", 19)|
delete from t2|
# Two call needed for bug test
call into_test3()|
call into_test3()|
select * from t2|
delete from t1|
delete from t2|
drop procedure into_test3|
# SELECT INTO with no data is a warning ("no data", which we will
# not see normally). When not caught, execution proceeds.
create procedure into_test4()
begin
declare x int;
select data into x from test.t1 limit 1;
insert into test.t3 values ("into4", x);
end|
delete from t1|
--disable_warnings
drop table if exists t3|
--enable_warnings
create table t3 ( s char(16), d int)|
call into_test4()|
select * from t3|
insert into t1 values ("i4", 77)|
call into_test4()|
select * from t3|
delete from t1|
drop table t3|
drop procedure into_test4|
# These two (and the two procedures above) caused an assert() to fail in
# sql_base.cc:lock_tables() at some point.
......@@ -658,7 +727,7 @@ create procedure hndlr4()
begin
declare x int default 0;
declare val int; # No default
declare continue handler for sqlexception set x=1;
declare continue handler for 1306 set x=1;
select data into val from test.t3 where id='z' limit 1; # No hits
......@@ -823,6 +892,28 @@ drop table t70|
drop procedure bug1656|
#
# BUG#1862
#
--disable_warnings
drop table if exists t3|
--enable_warnings
create table t3(a int)|
create procedure bug1862()
begin
insert into t3 values(2);
flush tables;
end|
call bug1862()|
# the second call caused a segmentation
call bug1862()|
select * from t3|
drop table t3|
drop procedure bug1862|
#
# Some "real" examples
#
......@@ -946,16 +1037,17 @@ drop procedure ip|
# Comment & suid
create procedure bar(x char(16), y int)
comment "111111111111" SECURITY INVOKER
comment "111111111111" sql security invoker
insert into test.t1 values (x, y)|
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
show procedure status like 'bar'|
alter procedure bar name bar2 comment "2222222222" SECURITY DEFINER|
alter procedure bar name bar2 comment "2222222222" sql security definer|
alter procedure bar2 name bar comment "3333333333"|
alter procedure bar|
show create procedure bar|
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
show procedure status like 'bar'|
drop procedure bar|
delimiter ;|
drop table t1;
......
......@@ -130,7 +130,7 @@ static SYMBOL symbols[] = {
{ "DECLARE", SYM(DECLARE_SYM),0,0},
{ "DES_KEY_FILE", SYM(DES_KEY_FILE),0,0},
{ "DEFAULT", SYM(DEFAULT),0,0},
{ "DEFINER", SYM(DEFINER),0,0},
{ "DEFINER", SYM(DEFINER_SYM),0,0},
{ "DELAYED", SYM(DELAYED_SYM),0,0},
{ "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM),0,0},
{ "DELETE", SYM(DELETE_SYM),0,0},
......@@ -233,7 +233,7 @@ static SYMBOL symbols[] = {
{ "ISOLATION", SYM(ISOLATION),0,0},
{ "ISSUER", SYM(ISSUER_SYM),0,0},
{ "ITERATE", SYM(ITERATE_SYM),0,0},
{ "INVOKER", SYM(INVOKER),0,0},
{ "INVOKER", SYM(INVOKER_SYM),0,0},
{ "JOIN", SYM(JOIN_SYM),0,0},
{ "KEY", SYM(KEY_SYM),0,0},
{ "KEYS", SYM(KEYS),0,0},
......@@ -370,7 +370,7 @@ static SYMBOL symbols[] = {
{ "SAVEPOINT", SYM(SAVEPOINT_SYM),0,0},
{ "SECOND", SYM(SECOND_SYM),0,0},
{ "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM),0,0},
{ "SECURITY", SYM(SECURITY),0,0},
{ "SECURITY", SYM(SECURITY_SYM),0,0},
{ "SEPARATOR", SYM(SEPARATOR_SYM),0,0},
{ "SELECT", SYM(SELECT_SYM),0,0},
{ "SENSITIVE", SYM(SENSITIVE_SYM),0,0},
......@@ -389,6 +389,7 @@ static SYMBOL symbols[] = {
{ "SONAME", SYM(UDF_SONAME_SYM),0,0},
{ "SPATIAL", SYM(SPATIAL_SYM),0,0},
{ "SPECIFIC", SYM(SPECIFIC_SYM),0,0},
{ "SQL", SYM(SQL_SYM),0,0},
{ "SQLEXCEPTION", SYM(SQLEXCEPTION_SYM),0,0},
{ "SQLSTATE", SYM(SQLSTATE_SYM),0,0},
{ "SQLWARNING", SYM(SQLWARNING_SYM),0,0},
......
......@@ -234,7 +234,9 @@ sp_head::execute(THD *thd)
DBUG_PRINT("execute", ("Instruction %u", ip));
ret= i->execute(thd, &ip);
// Check if an exception has occurred and a handler has been found
if (ret && !thd->killed && ctx)
// Note: We havo to check even if ret==0, since warnings (and some
// errors don't return a non-zero value.
if (!thd->killed && ctx)
{
uint hf;
......@@ -509,12 +511,20 @@ sp_head::restore_lex(THD *thd)
// Update some state in the old one first
oldlex->ptr= sublex->ptr;
oldlex->next_state= sublex->next_state;
// Save WHERE clause pointers to avoid damaging by optimisation
for (SELECT_LEX *sl= sublex->all_selects_list ;
sl ;
sl= sl->next_select_in_list())
{
// Save WHERE clause pointers to avoid damaging by optimisation
sl->prep_where= sl->where;
if (sl->with_wild)
{
// Copy item_list. We will restore it before calling the
// sub-statement, so it's ok to pop them.
sl->item_list_copy.empty();
while (Item *it= sl->item_list.pop())
sl->item_list_copy.push_back(it);
}
}
// Collect some data from the sub statement lex.
......@@ -687,14 +697,22 @@ sp_instr_stmt::exec_stmt(THD *thd, LEX *lex)
sl ;
sl= sl->next_select_in_list())
{
if (lex->sql_command == SQLCOM_CREATE_TABLE ||
lex->sql_command == SQLCOM_INSERT_SELECT)
{ // Destroys sl->table_list.first
sl->table_list_first_copy= sl->table_list.first;
}
if (sl->with_wild)
{
List_iterator_fast<Item> li(sl->item_list);
// Restore item_list
// Note: We have to do this before executing the sub-statement,
// to make sure that the list nodes are in the right
// memroot.
List_iterator_fast<Item> li(sl->item_list_copy);
// Copy item_list
sl->item_list_copy.empty();
sl->item_list.empty();
while (Item *it= li++)
sl->item_list_copy.push_back(it);
sl->item_list.push_back(it);
}
sl->ref_pointer_array= 0;
if (sl->prep_where)
......@@ -725,12 +743,19 @@ sp_instr_stmt::exec_stmt(THD *thd, LEX *lex)
sl ;
sl= sl->next_select_in_list())
{
if (sl->with_wild)
TABLE_LIST *tabs;
// We have closed all tables, get rid of pointers to them
for (tabs=(TABLE_LIST *)sl->table_list.first ;
tabs ;
tabs= tabs->next)
{
// Restore item_list
sl->item_list.empty();
while (Item *it= sl->item_list_copy.pop())
sl->item_list.push_back(it);
tabs->table= NULL;
}
if (lex->sql_command == SQLCOM_CREATE_TABLE ||
lex->sql_command == SQLCOM_INSERT_SELECT)
{ // Restore sl->table_list.first
sl->table_list.first= sl->table_list_first_copy;
}
for (ORDER *order= (ORDER *)sl->order_list.first ;
order ;
......
......@@ -1253,14 +1253,8 @@ bool select_dumpvar::send_data(List<Item> &items)
bool select_dumpvar::send_eof()
{
if (row_count)
{
::send_ok(thd,row_count);
return 0;
}
else
{
my_error(ER_EMPTY_QUERY,MYF(0));
return 1;
}
if (! row_count)
send_warning(thd, ER_SP_FETCH_NO_DATA);
::send_ok(thd,row_count);
return 0;
}
......@@ -362,6 +362,7 @@ public:
SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
List<Item> item_list; /* list of fields & expressions */
List<Item> item_list_copy; /* For SPs */
byte *table_list_first_copy; /* For SPs */
List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr;
/*
......
......@@ -137,7 +137,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CREATE
%token CROSS
%token CUBE_SYM
%token DEFINER
%token DEFINER_SYM
%token DELETE_SYM
%token DUAL_SYM
%token DO_SYM
......@@ -167,6 +167,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SELECT_SYM
%token SHOW
%token SLAVE
%token SQL_SYM
%token SQL_THREAD
%token START_SYM
%token STD_SYM
......@@ -270,7 +271,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token INOUT_SYM
%token INTO
%token IN_SYM
%token INVOKER
%token INVOKER_SYM
%token ISOLATION
%token JOIN_SYM
%token KEYS
......@@ -364,7 +365,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ROW_FORMAT_SYM
%token ROW_SYM
%token RTREE_SYM
%token SECURITY
%token SECURITY_SYM
%token SET
%token SEPARATOR_SYM
%token SERIAL_SYM
......@@ -1120,20 +1121,20 @@ create_function_tail:
;
sp_comment:
/* Empty */ { $$.str=0; }
/* Empty */ { $$.str= 0; $$.length= 0; }
| COMMENT_SYM TEXT_STRING_sys { $$= $2; }
;
sp_newname:
/* Empty */ { $$.str=0; }
/* Empty */ { $$.str= 0; $$.length= 0; }
| NAME_SYM ident { $$= $2; }
;
sp_suid:
/* Empty */ { Lex->suid= IS_DEFAULT_SUID; }
| SECURITY DEFINER { Lex->suid= IS_SUID; }
| SECURITY INVOKER { Lex->suid= IS_NOT_SUID; }
/* Empty */ { Lex->suid= IS_DEFAULT_SUID; }
| SQL_SYM SECURITY_SYM DEFINER_SYM { Lex->suid= IS_SUID; }
| SQL_SYM SECURITY_SYM INVOKER_SYM { Lex->suid= IS_NOT_SUID; }
;
call:
......@@ -2603,30 +2604,35 @@ alter:
lex->name=$3.str;
}
| ALTER PROCEDURE ident sp_newname sp_comment sp_suid
/* QQ Characteristics missing for now */
opt_restrict
{
THD *thd= YYTHD;
LEX *lex=Lex;
/* This is essensially an no-op right now, since we haven't
put the characteristics in yet. */
lex->sql_command= SQLCOM_ALTER_PROCEDURE;
lex->udf.name= $3;
lex->name= $4.str;
lex->comment= &$5;
/* $5 is a yacc/bison internal struct, so we can't keep
the pointer to it for use outside the parser. */
lex->comment= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
lex->comment->str= $5.str;
lex->comment->length= $5.length;
}
| ALTER FUNCTION_SYM ident sp_newname sp_comment sp_suid
/* QQ Characteristics missing for now */
opt_restrict
{
THD *thd= YYTHD;
LEX *lex=Lex;
/* This is essensially an no-op right now, since we haven't
put the characteristics in yet. */
lex->sql_command= SQLCOM_ALTER_FUNCTION;
lex->udf.name= $3;
lex->name= $4.str;
lex->comment= &$5;
/* $5 is a yacc/bison internal struct, so we can't keep
the pointer to it for use outside the parser. */
lex->comment= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
lex->comment= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
lex->comment->str= $5.str;
lex->comment->length= $5.length;
}
;
......@@ -5612,7 +5618,7 @@ keyword:
| DATETIME {}
| DATE_SYM {}
| DAY_SYM {}
| DEFINER {}
| DEFINER_SYM {}
| DELAY_KEY_WRITE_SYM {}
| DES_KEY_FILE {}
| DIRECTORY_SYM {}
......@@ -5648,7 +5654,7 @@ keyword:
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
| INVOKER {}
| INVOKER_SYM {}
| IMPORT {}
| INDEXES {}
| ISOLATION {}
......@@ -5735,7 +5741,7 @@ keyword:
| RTREE_SYM {}
| SAVEPOINT_SYM {}
| SECOND_SYM {}
| SECURITY {}
| SECURITY_SYM {}
| SERIAL_SYM {}
| SERIALIZABLE_SYM {}
| SESSION_SYM {}
......
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