summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp-lock.result42
-rw-r--r--mysql-test/r/sp_sync.result107
-rw-r--r--mysql-test/t/disabled.def1
-rw-r--r--mysql-test/t/sp-lock.test62
-rw-r--r--mysql-test/t/sp_sync.test164
-rw-r--r--sql/sql_parse.cc6
6 files changed, 332 insertions, 50 deletions
diff --git a/mysql-test/r/sp-lock.result b/mysql-test/r/sp-lock.result
index e9087f61807..a7823175b3c 100644
--- a/mysql-test/r/sp-lock.result
+++ b/mysql-test/r/sp-lock.result
@@ -693,5 +693,47 @@ set @@session.max_sp_recursion_depth=default;
# --> connection con3
# --> connection default
#
+# SHOW CREATE PROCEDURE p1 called from p1, after p1 was altered
+#
+# We are just covering the existing behaviour with tests. The
+# results are not necessarily correct."
+#
+CREATE PROCEDURE p1()
+BEGIN
+SELECT get_lock("test", 10);
+SHOW CREATE PROCEDURE p1;
+END|
+# Connection default
+SELECT get_lock("test", 10);
+get_lock("test", 10)
+1
+# Connection 2
+# Will halt before executing SHOW CREATE PROCEDURE p1
+# Sending:
+CALL p1();
+# Connection 3
+# Alter p1
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN END;
+# Connection default
+# Resume CALL p1, now with new p1
+SELECT release_lock("test");
+release_lock("test")
+1
+# Connection 2
+# Reaping: CALL p1()
+get_lock("test", 10)
+1
+Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
+p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
+BEGIN
+SELECT get_lock("test", 10);
+SHOW CREATE PROCEDURE p1;
+END latin1 latin1_swedish_ci latin1_swedish_ci
+# Connection 3
+# Connection 2
+# Connection default;
+DROP PROCEDURE p1;
+#
# End of 5.5 tests
#
diff --git a/mysql-test/r/sp_sync.result b/mysql-test/r/sp_sync.result
index afa37e70531..a16babaef67 100644
--- a/mysql-test/r/sp_sync.result
+++ b/mysql-test/r/sp_sync.result
@@ -1,23 +1,94 @@
Tests of syncronization of stored procedure execution.
+SET DEBUG_SYNC= 'RESET';
#
-# Bug#48157: crash in Item_field::used_tables
+# Bug #30977 Concurrent statement using stored function and
+# DROP FUNCTION breaks SBR
#
-CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b;
-CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b;
-CREATE PROCEDURE p1()
-BEGIN
-UPDATE t1 JOIN t2 USING( a, b ) SET t1.b = 1, t2.b = 1;
-END|
-LOCK TABLES t1 WRITE, t2 WRITE;
-SET DEBUG_SYNC = 'multi_update_reopen_tables SIGNAL parked WAIT_FOR go';
+# A stored routine could change after dispatch_command()
+# but before a MDL lock is taken. This must be noticed and the
+# sp cache flushed so the correct version can be loaded.
+#
+# Connection default
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+# Get f1 cached
+SELECT f1();
+f1()
+1
+# Then start executing it again...
+SET DEBUG_SYNC= 'before_execute_sql_command SIGNAL before WAIT_FOR changed';
+# Sending:
+SELECT f1();
+# Connection 2
+SET DEBUG_SYNC= 'now WAIT_FOR before';
+# ... but before f1 is locked, change it.
+DROP FUNCTION f1;
+CREATE FUNCTION f1() RETURNS INT RETURN 2;
+SET DEBUG_SYNC= 'now SIGNAL changed';
+# Connection default
+# We should now get '2' and not '1'.
+# Reaping: SELECT f1()
+f1()
+2
+DROP FUNCTION f1;
+SET DEBUG_SYNC= 'RESET';
+#
+# Field translation items must be cleared in case of back-offs
+# for queries that use Information Schema tables. Otherwise
+# memory allocated in fix_fields() for views may end up referring
+# to freed memory.
+#
+DROP FUNCTION IF EXISTS f1;
+# Connection default
+CREATE FUNCTION f1() RETURNS INT RETURN 0;
+# Connection con2
+SET DEBUG_SYNC= 'after_wait_locked_pname SIGNAL locked WAIT_FOR issued';
+# con2 will now have an x-lock on f1
+# Sending:
+ALTER FUNCTION f1 COMMENT 'comment';
+# Connection default
+SET DEBUG_SYNC= 'now WAIT_FOR locked';
+# This query will block due to the x-lock on f1 and back-off
+SHOW OPEN TABLES WHERE f1()=0;
+# Connection con3
+# Check that the IS query is blocked before releasing the x-lock
+SET DEBUG_SYNC= 'now SIGNAL issued';
+# Connection default
+# Reaping: ALTER FUNCTION f1 COMMENT 'comment'
+DROP FUNCTION f1;
+SET DEBUG_SYNC= 'RESET';
+#
+# Bug #48246 assert in close_thread_table
+#
+CREATE TABLE t1 (a INTEGER);
+CREATE FUNCTION f1(b INTEGER) RETURNS INTEGER RETURN 1;
+CREATE PROCEDURE p1() SELECT COUNT(f1(a)) FROM t1;
+INSERT INTO t1 VALUES(1), (2);
+# Connection 2
+CALL p1();
+COUNT(f1(a))
+2
+# Connection default
+SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR called';
+# Sending:
+CREATE TABLE t1 (a INTEGER);
+# Connection 2
+SET DEBUG_SYNC= 'now WAIT_FOR locked';
+SET DEBUG_SYNC= 'before_open_table_wait_refresh SIGNAL called WAIT_FOR created';
+# This call used to cause an assertion. MDL locking conflict will
+# cause back-off and retry. A variable indicating if a prelocking list
+# exists, used to be not reset properly causing an eventual assert.
+# Sending:
CALL p1();
-DROP TABLE t1, t2;
-SET DEBUG_SYNC = 'now WAIT_FOR parked';
-CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b;
-CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b;
-SET DEBUG_SYNC = 'now SIGNAL go';
-# Without the DEBUG_SYNC supplied in the same patch as this test in the
-# code, this test statement will hang.
-DROP TABLE t1, t2;
+# Connection default
+# Reaping: CREATE TABLE t1 (a INTEGER)
+ERROR 42S01: Table 't1' already exists
+SET DEBUG_SYNC= 'now SIGNAL created';
+# Connection 2
+# Reaping: CALL p1()
+COUNT(f1(a))
+2
+# Connection default
DROP PROCEDURE p1;
-SET DEBUG_SYNC = 'RESET';
+DROP FUNCTION f1;
+DROP TABLE t1;
+SET DEBUG_SYNC= 'RESET';
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index 3b34ef368e1..de7956eb500 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -11,7 +11,6 @@
##############################################################################
kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild.
query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically
-sp_sync : Bug#48157 2010-02-06 5.5-m3 demands a differnt solution
innodb-autoinc : Bug#49267 2009-12-02 test fails on windows because of different case mode
innodb : Bug#49396 2009-12-03 test fails in embedded mode
plugin_load : Bug#42144 2009-12-21 alik plugin_load fails
diff --git a/mysql-test/t/sp-lock.test b/mysql-test/t/sp-lock.test
index 0b31eabb0f1..7297790a886 100644
--- a/mysql-test/t/sp-lock.test
+++ b/mysql-test/t/sp-lock.test
@@ -893,6 +893,68 @@ disconnect con3;
--source include/wait_until_disconnected.inc
--echo # --> connection default
connection default;
+
+
+--echo #
+--echo # SHOW CREATE PROCEDURE p1 called from p1, after p1 was altered
+--echo #
+--echo # We are just covering the existing behaviour with tests. The
+--echo # results are not necessarily correct."
+--echo #
+
+delimiter |;
+CREATE PROCEDURE p1()
+BEGIN
+ SELECT get_lock("test", 10);
+ SHOW CREATE PROCEDURE p1;
+END|
+delimiter ;|
+
+connect (con2, localhost, root);
+connect (con3, localhost, root);
+
+--echo # Connection default
+connection default;
+SELECT get_lock("test", 10);
+
+--echo # Connection 2
+connection con2;
+--echo # Will halt before executing SHOW CREATE PROCEDURE p1
+--echo # Sending:
+--send CALL p1()
+
+--echo # Connection 3
+connection con3;
+let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
+ WHERE state='User lock' and info='SELECT get_lock("test", 10)';
+--source include/wait_condition.inc
+--echo # Alter p1
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN END;
+
+--echo # Connection default
+connection default;
+--echo # Resume CALL p1, now with new p1
+SELECT release_lock("test");
+
+--echo # Connection 2
+connection con2;
+--echo # Reaping: CALL p1()
+--reap
+
+--echo # Connection 3
+connection con3;
+disconnect con3;
+--source include/wait_until_disconnected.inc
+--echo # Connection 2
+connection con2;
+disconnect con2;
+--source include/wait_until_disconnected.inc
+--echo # Connection default;
+connection default;
+DROP PROCEDURE p1;
+
+
--echo #
--echo # End of 5.5 tests
--echo #
diff --git a/mysql-test/t/sp_sync.test b/mysql-test/t/sp_sync.test
index 519a9211206..391298b604a 100644
--- a/mysql-test/t/sp_sync.test
+++ b/mysql-test/t/sp_sync.test
@@ -5,54 +5,156 @@
--source include/have_debug_sync.inc
+# Save the initial number of concurrent sessions.
+--source include/count_sessions.inc
+
+# Clean up resources used in this test case.
+--disable_warnings
+SET DEBUG_SYNC= 'RESET';
+--enable_warnings
+
+--echo #
+--echo # Bug #30977 Concurrent statement using stored function and
+--echo # DROP FUNCTION breaks SBR
--echo #
---echo # Bug#48157: crash in Item_field::used_tables
+--echo # A stored routine could change after dispatch_command()
+--echo # but before a MDL lock is taken. This must be noticed and the
+--echo # sp cache flushed so the correct version can be loaded.
--echo #
-CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b;
-CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b;
+connect (con2, localhost, root);
-DELIMITER |;
+--echo # Connection default
+connection default;
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+--echo # Get f1 cached
+SELECT f1();
+--echo # Then start executing it again...
+SET DEBUG_SYNC= 'before_execute_sql_command SIGNAL before WAIT_FOR changed';
+--echo # Sending:
+--send SELECT f1()
+
+--echo # Connection 2
+connection con2;
+SET DEBUG_SYNC= 'now WAIT_FOR before';
+--echo # ... but before f1 is locked, change it.
+DROP FUNCTION f1;
+CREATE FUNCTION f1() RETURNS INT RETURN 2;
+SET DEBUG_SYNC= 'now SIGNAL changed';
+
+--echo # Connection default
+--echo # We should now get '2' and not '1'.
+connection default;
+--echo # Reaping: SELECT f1()
+--reap
+
+disconnect con2;
+DROP FUNCTION f1;
+SET DEBUG_SYNC= 'RESET';
-CREATE PROCEDURE p1()
-BEGIN
- UPDATE t1 JOIN t2 USING( a, b ) SET t1.b = 1, t2.b = 1;
-END|
+--echo #
+--echo # Field translation items must be cleared in case of back-offs
+--echo # for queries that use Information Schema tables. Otherwise
+--echo # memory allocated in fix_fields() for views may end up referring
+--echo # to freed memory.
+--echo #
-DELIMITER ;|
+--disable_warnings
+DROP FUNCTION IF EXISTS f1;
+--enable_warnings
-connect (con1,localhost,root,,);
-connect (con2,localhost,root,,);
+connect (con2, localhost, root);
+connect (con3, localhost, root);
-connection con1;
-LOCK TABLES t1 WRITE, t2 WRITE;
+--echo # Connection default
+connection default;
+CREATE FUNCTION f1() RETURNS INT RETURN 0;
+--echo # Connection con2
connection con2;
-LET $ID= `select connection_id()`;
-SET DEBUG_SYNC = 'multi_update_reopen_tables SIGNAL parked WAIT_FOR go';
---send CALL p1()
+SET DEBUG_SYNC= 'after_wait_locked_pname SIGNAL locked WAIT_FOR issued';
+--echo # con2 will now have an x-lock on f1
+--echo # Sending:
+--send ALTER FUNCTION f1 COMMENT 'comment'
-connection con1;
-let $wait_condition= SELECT 1 FROM information_schema.processlist WHERE ID = $ID AND
-state = "Waiting for table";
+--echo # Connection default
+connection default;
+SET DEBUG_SYNC= 'now WAIT_FOR locked';
+--disable_result_log
+--echo # This query will block due to the x-lock on f1 and back-off
+--send SHOW OPEN TABLES WHERE f1()=0
+
+--echo # Connection con3
+connection con3;
+let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
+ WHERE state= 'Waiting for table'
+ AND info='SHOW OPEN TABLES WHERE f1()=0';
--source include/wait_condition.inc
-DROP TABLE t1, t2;
-SET DEBUG_SYNC = 'now WAIT_FOR parked';
-CREATE TABLE t1 AS SELECT 1 AS a, 1 AS b;
-CREATE TABLE t2 AS SELECT 1 AS a, 1 AS b;
-SET DEBUG_SYNC = 'now SIGNAL go';
+--echo # Check that the IS query is blocked before releasing the x-lock
+SET DEBUG_SYNC= 'now SIGNAL issued';
-connection con2;
+--echo # Connection default
+connection default;
+--echo # Reaping: ALTER FUNCTION f1 COMMENT 'comment'
--reap
-
-disconnect con1;
+--enable_result_log
+DROP FUNCTION f1;
+SET DEBUG_SYNC= 'RESET';
disconnect con2;
+disconnect con3;
+
+
+--echo #
+--echo # Bug #48246 assert in close_thread_table
+--echo #
+
+CREATE TABLE t1 (a INTEGER);
+CREATE FUNCTION f1(b INTEGER) RETURNS INTEGER RETURN 1;
+CREATE PROCEDURE p1() SELECT COUNT(f1(a)) FROM t1;
+
+INSERT INTO t1 VALUES(1), (2);
+
+--echo # Connection 2
+connect (con2, localhost, root);
+CALL p1();
+
+--echo # Connection default
connection default;
+SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR called';
+--echo # Sending:
+--send CREATE TABLE t1 (a INTEGER)
---echo # Without the DEBUG_SYNC supplied in the same patch as this test in the
---echo # code, this test statement will hang.
-DROP TABLE t1, t2;
+--echo # Connection 2
+connection con2;
+SET DEBUG_SYNC= 'now WAIT_FOR locked';
+SET DEBUG_SYNC= 'before_open_table_wait_refresh SIGNAL called WAIT_FOR created';
+--echo # This call used to cause an assertion. MDL locking conflict will
+--echo # cause back-off and retry. A variable indicating if a prelocking list
+--echo # exists, used to be not reset properly causing an eventual assert.
+--echo # Sending:
+--send CALL p1()
+
+--echo # Connection default
+connection default;
+--echo # Reaping: CREATE TABLE t1 (a INTEGER)
+--error ER_TABLE_EXISTS_ERROR
+--reap
+SET DEBUG_SYNC= 'now SIGNAL created';
+
+--echo # Connection 2
+connection con2;
+--echo # Reaping: CALL p1()
+--reap;
+
+--echo # Connection default
+connection default;
+disconnect con2;
DROP PROCEDURE p1;
+DROP FUNCTION f1;
+DROP TABLE t1;
+SET DEBUG_SYNC= 'RESET';
-SET DEBUG_SYNC = 'RESET';
+# Check that all connections opened by test cases in this file are really
+# gone so execution of other tests won't be affected by their presence.
+--source include/wait_until_count_sessions.inc
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 23e0d8c0d70..06acfab0537 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -31,6 +31,7 @@
#include "transaction.h"
#include "sql_audit.h"
#include "sql_prepare.h"
+#include "debug_sync.h"
#include "probes_mysql.h"
#include "set_var.h"
@@ -2115,6 +2116,11 @@ mysql_execute_command(THD *thd)
if (thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE))
goto error;
+#ifndef DBUG_OFF
+ if (lex->sql_command != SQLCOM_SET_OPTION)
+ DEBUG_SYNC(thd,"before_execute_sql_command");
+#endif
+
switch (lex->sql_command) {
case SQLCOM_SHOW_EVENTS: