summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2006-06-22 21:06:09 +0400
committerunknown <konstantin@mysql.com>2006-06-22 21:06:09 +0400
commit8eb00d0af7908d936b7aa5685f157db209f323c6 (patch)
tree5cadac596a6f0db7a6b49555a56497eb2732b0fc
parent41b9884db0db0b3e16562161a86e94a998bcce2d (diff)
parent67fd3c4a53f585f8e33b5094822cf639a27483de (diff)
downloadmariadb-git-8eb00d0af7908d936b7aa5685f157db209f323c6.tar.gz
Merge mysql.com:/opt/local/work/mysql-5.0-root
into mysql.com:/opt/local/work/mysql-5.0-runtime
-rw-r--r--mysql-test/r/sp-prelocking.result18
-rw-r--r--mysql-test/r/sp.result21
-rw-r--r--mysql-test/t/sp-prelocking.test31
-rw-r--r--mysql-test/t/sp.test27
-rw-r--r--sql/sp_head.cc4
-rw-r--r--sql/sql_parse.cc40
6 files changed, 136 insertions, 5 deletions
diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result
index 2335513b28a..7d8dd862748 100644
--- a/mysql-test/r/sp-prelocking.result
+++ b/mysql-test/r/sp-prelocking.result
@@ -237,3 +237,21 @@ deallocate prepare stmt;
drop table t1;
drop view v1, v2, v3;
drop function bug15683;
+drop table if exists t1, t2, t3;
+drop function if exists bug19634;
+create table t1 (id int, data int);
+create table t2 (id int);
+create table t3 (data int);
+create function bug19634() returns int return (select count(*) from t3);
+prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id and bug19634()";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+create trigger t1_bi before delete on t1 for each row insert into t3 values (old.data);
+prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id";
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+drop function bug19634;
+drop table t1, t2, t3;
+End of 5.0 tests
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index ff378f1f43b..d3874c769fa 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -4990,4 +4990,25 @@ CALL bug18037_p2()|
DROP FUNCTION bug18037_f1|
DROP PROCEDURE bug18037_p1|
DROP PROCEDURE bug18037_p2|
+drop table if exists t3|
+drop procedure if exists bug15217|
+create table t3 as select 1|
+create procedure bug15217()
+begin
+declare var1 char(255);
+declare cur1 cursor for select * from t3;
+open cur1;
+fetch cur1 into var1;
+select concat('data was: /', var1, '/');
+close cur1;
+end |
+call bug15217()|
+concat('data was: /', var1, '/')
+data was: /1/
+flush tables |
+call bug15217()|
+concat('data was: /', var1, '/')
+data was: /1/
+drop table t3|
+drop procedure bug15217|
drop table t1,t2;
diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test
index a7215462afb..b94de6236d3 100644
--- a/mysql-test/t/sp-prelocking.test
+++ b/mysql-test/t/sp-prelocking.test
@@ -272,3 +272,34 @@ drop table t1;
drop view v1, v2, v3;
drop function bug15683;
+
+#
+# Bug#19634 "Re-execution of multi-delete which involve trigger/stored
+# function crashes server"
+#
+--disable_warnings
+drop table if exists t1, t2, t3;
+drop function if exists bug19634;
+--enable_warnings
+create table t1 (id int, data int);
+create table t2 (id int);
+create table t3 (data int);
+create function bug19634() returns int return (select count(*) from t3);
+prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id and bug19634()";
+# This should not crash server
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
+create trigger t1_bi before delete on t1 for each row insert into t3 values (old.data);
+prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id";
+
+execute stmt;
+execute stmt;
+deallocate prepare stmt;
+
+drop function bug19634;
+drop table t1, t2, t3;
+
+
+--echo End of 5.0 tests
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 1d21a5da187..66498198157 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -5888,6 +5888,33 @@ DROP FUNCTION bug18037_f1|
DROP PROCEDURE bug18037_p1|
DROP PROCEDURE bug18037_p2|
+#
+# Bug#15217 "Using a SP cursor on a table created with PREPARE fails with
+# weird error". Check that the code that is supposed to work at
+# the first execution of a stored procedure actually works for
+# sp_instr_copen.
+
+--disable_warnings
+drop table if exists t3|
+drop procedure if exists bug15217|
+--enable_warnings
+create table t3 as select 1|
+create procedure bug15217()
+begin
+ declare var1 char(255);
+ declare cur1 cursor for select * from t3;
+ open cur1;
+ fetch cur1 into var1;
+ select concat('data was: /', var1, '/');
+ close cur1;
+end |
+# Returns expected result
+call bug15217()|
+flush tables |
+# Returns error with garbage as column name
+call bug15217()|
+drop table t3|
+drop procedure bug15217|
#
# BUG#NNNN: New bug synopsis
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 3b29a841966..ef2f895c8b2 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1075,7 +1075,6 @@ sp_head::execute(THD *thd)
thd->net.no_send_error= 0;
if (i->free_list)
cleanup_items(i->free_list);
- i->state= Query_arena::EXECUTED;
/*
If we've set thd->user_var_events_alloc to mem_root of this SP
@@ -2210,6 +2209,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
m_lex->mark_as_requiring_prelocking(NULL);
}
thd->rollback_item_tree_changes();
+ /* Update the state of the active arena. */
+ thd->stmt_arena->state= Query_arena::EXECUTED;
+
/*
Unlike for PS we should not call Item's destructors for newly created
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ba5c2ebf484..7ed96250240 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5202,8 +5202,26 @@ bool check_global_access(THD *thd, ulong want_access)
/*
- Check the privilege for all used tables. Table privileges are cached
- in the table list for GRANT checking
+ Check the privilege for all used tables.
+
+ SYNOPSYS
+ check_table_access()
+ thd Thread context
+ want_access Privileges requested
+ tables List of tables to be checked
+ no_errors FALSE/TRUE - report/don't report error to
+ the client (using my_error() call).
+
+ NOTES
+ Table privileges are cached in the table list for GRANT checking.
+ This functions assumes that table list used and
+ thd->lex->query_tables_own_last value correspond to each other
+ (the latter should be either 0 or point to next_global member
+ of one of elements of this table list).
+
+ RETURN VALUE
+ FALSE - OK
+ TRUE - Access denied
*/
bool
@@ -7068,14 +7086,28 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
+ TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last;
DBUG_ENTER("multi_delete_precheck");
/* sql_yacc guarantees that tables and aux_tables are not zero */
DBUG_ASSERT(aux_tables != 0);
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
- check_table_access(thd,SELECT_ACL, tables,0) ||
- check_table_access(thd,DELETE_ACL, aux_tables,0))
+ check_table_access(thd, SELECT_ACL, tables, 0))
+ DBUG_RETURN(TRUE);
+
+ /*
+ Since aux_tables list is not part of LEX::query_tables list we
+ have to juggle with LEX::query_tables_own_last value to be able
+ call check_table_access() safely.
+ */
+ thd->lex->query_tables_own_last= 0;
+ if (check_table_access(thd, DELETE_ACL, aux_tables, 0))
+ {
+ thd->lex->query_tables_own_last= save_query_tables_own_last;
DBUG_RETURN(TRUE);
+ }
+ thd->lex->query_tables_own_last= save_query_tables_own_last;
+
if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
{
my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,