# At a local mysql-6.0 repository of davi
2746 Davi Arnaut 2009-03-23
Bug#989: If DROP TABLE while there's an active transaction, wrong binlog order
WL#4284: Transactional DDL locking
After some discussions with stakeholders it has been decided that
metadata locks acquired during a PREPARE statement must be released
once the statement is prepared even if it is prepared within a multi
statement transaction.
@ mysql-test/r/ps.result
Add test case result.
@ mysql-test/t/ps.test
Add test case.
@ sql/sql_prepare.cc
Release metdata locks acquired while the prepared statement is being
checked.
modified:
mysql-test/r/ps.result
mysql-test/t/ps.test
sql/sql_prepare.cc
=== modified file 'mysql-test/r/ps.result'
--- a/mysql-test/r/ps.result 2009-03-18 12:49:07 +0000
+++ b/mysql-test/r/ps.result 2009-03-23 18:17:10 +0000
@@ -3096,6 +3096,16 @@ EXECUTE stmt1;
ERROR 42S01: Table 't1' already exists
DEALLOCATE PREPARE stmt1;
DROP TABLE t1;
+#
+# WL#4284: Transactional DDL locking
+#
+# Test that metadata locks taken during prepare are released.
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT);
+BEGIN;
+PREPARE stmt1 FROM "SELECT * FROM t1";
+DROP TABLE t1;
# End of WL#4435.
=== modified file 'mysql-test/t/ps.test'
--- a/mysql-test/t/ps.test 2009-03-18 12:49:07 +0000
+++ b/mysql-test/t/ps.test 2009-03-23 18:17:10 +0000
@@ -3212,6 +3212,25 @@ EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
DROP TABLE t1;
+--echo #
+--echo # WL#4284: Transactional DDL locking
+--echo #
+--echo # Test that metadata locks taken during prepare are released.
+--echo #
+
+connect(con1,localhost,root,,);
+connection default;
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TABLE t1 (a INT);
+connection con1;
+BEGIN;
+PREPARE stmt1 FROM "SELECT * FROM t1";
+connection default;
+DROP TABLE t1;
+disconnect con1;
+
#
# Additional cleanup.
#
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2009-03-18 12:49:07 +0000
+++ b/sql/sql_prepare.cc 2009-03-23 18:17:10 +0000
@@ -3147,6 +3147,7 @@ bool Prepared_statement::prepare(const c
bool error;
Statement stmt_backup;
Query_arena *old_stmt_arena;
+ MDL_ticket *mdl_savepoint= NULL;
DBUG_ENTER("Prepared_statement::prepare");
/*
If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql.
@@ -3205,6 +3206,13 @@ bool Prepared_statement::prepare(const c
*/
DBUG_ASSERT(thd->change_list.is_empty());
+ /*
+ Marker used to release metadata locks acquired while the prepared
+ statement is being checked.
+ */
+ if (thd->in_multi_stmt_transaction())
+ mdl_savepoint= thd->mdl_context.mdl_savepoint();
+
/*
The only case where we should have items in the thd->free_list is
after stmt->set_params_from_vars(), which may in some cases create
@@ -3228,6 +3236,15 @@ bool Prepared_statement::prepare(const c
lex_end(lex);
cleanup_stmt();
+ /*
+ If not inside a multi-statement transaction, the metadata locks have
+ already been released and the rollback_to_savepoint is a nop.
+ Otherwise, release acquired locks -- a NULL mdl_savepoint means that
+ all locks are going to be released or that the transaction didn't
+ own any locks.
+ */
+ if (!thd->locked_tables_mode)
+ thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
thd->restore_backup_statement(this, &stmt_backup);
thd->stmt_arena= old_stmt_arena;
Attachment: [text/bzr-bundle] bzr/davi.arnaut@sun.com-20090323181710-svbpqqnuyjh1ejsu.bundle