summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Widenius <monty@askmonty.org>2012-05-16 18:44:17 +0300
committerMichael Widenius <monty@askmonty.org>2012-05-16 18:44:17 +0300
commit6d8e329c9a1f1e80bd0e9bc30397aa8349aa7c70 (patch)
treedbb781cd1d0f004e75802a90e34a31353d1de5ae
parentc17bace4f0d05a6852c465513005812e5dc35b6f (diff)
downloadmariadb-git-6d8e329c9a1f1e80bd0e9bc30397aa8349aa7c70.tar.gz
Fixed bug LP:973039 - Assertion `share->in_trans == 0' failed in maria_close on DROP TABLE under LOCK
- 5.5 was missing calls to ha_extra(HA_PREPARE_FOR_DROP | HA_PREPARE_FOR_RENAME); Lost in merge 5.3 -> 5.5 sql/sql_admin.cc: Updated arguments for close_all_tables_for_name sql/sql_base.h: Updated arguments for close_all_tables_for_name sql/sql_partition.cc: Updated arguments for close_all_tables_for_name sql/sql_table.cc: Updated arguments for close_all_tables_for_name Removed test of kill, as we have already called 'ha_extra(HA_PREPARE_FOR_DROP)' and the table may be inconsistent. sql/sql_trigger.cc: Updated arguments for close_all_tables_for_name sql/sql_truncate.cc: For truncate that is done with drop + recreate, signal that the table will be dropped.
-rw-r--r--mysql-test/suite/maria/lock.result10
-rw-r--r--mysql-test/suite/maria/lock.test21
-rw-r--r--sql/sql_admin.cc2
-rw-r--r--sql/sql_base.cc16
-rw-r--r--sql/sql_base.h2
-rw-r--r--sql/sql_partition.cc4
-rw-r--r--sql/sql_table.cc15
-rw-r--r--sql/sql_trigger.cc2
-rw-r--r--sql/sql_truncate.cc2
9 files changed, 51 insertions, 23 deletions
diff --git a/mysql-test/suite/maria/lock.result b/mysql-test/suite/maria/lock.result
new file mode 100644
index 00000000000..606cb5fed4d
--- /dev/null
+++ b/mysql-test/suite/maria/lock.result
@@ -0,0 +1,10 @@
+drop table if exists t1,t2;
+Warnings:
+Note 1051 Unknown table 't1'
+Note 1051 Unknown table 't2'
+CREATE TABLE t1 (i INT) ENGINE=Aria;
+CREATE TABLE t2 (i INT) ENGINE=Aria;
+LOCK TABLE t1 WRITE, t2 WRITE;
+DROP TABLE t1;
+UNLOCK TABLES;
+DROP TABLE t2;
diff --git a/mysql-test/suite/maria/lock.test b/mysql-test/suite/maria/lock.test
new file mode 100644
index 00000000000..564cf965d17
--- /dev/null
+++ b/mysql-test/suite/maria/lock.test
@@ -0,0 +1,21 @@
+#
+# Testing of potential problems in Aria with locking
+#
+
+-- source include/have_maria.inc
+
+drop table if exists t1,t2;
+
+#
+# Test for Bug#973039
+# Assertion `share->in_trans == 0' failed in maria_close on DROP TABLE
+# under LOCK
+#
+
+CREATE TABLE t1 (i INT) ENGINE=Aria;
+CREATE TABLE t2 (i INT) ENGINE=Aria;
+LOCK TABLE t1 WRITE, t2 WRITE;
+# Also fails with FLUSH TABLE t1 and with REPAIR TABLE t1 USE_FRM
+DROP TABLE t1;
+UNLOCK TABLES;
+DROP TABLE t2;
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index f8c602e6482..7d5012f8cdf 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -196,7 +196,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
*/
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
goto end;
- close_all_tables_for_name(thd, table_list->table->s, FALSE);
+ close_all_tables_for_name(thd, table_list->table->s, HA_EXTRA_NORMAL);
table_list->table= 0;
}
/*
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 7a29bea8049..446019ac420 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1116,7 +1116,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
result= TRUE;
goto err_with_reopen;
}
- close_all_tables_for_name(thd, table->s, FALSE);
+ close_all_tables_for_name(thd, table->s, HA_EXTRA_NORMAL);
}
}
@@ -1393,7 +1393,7 @@ static void close_open_tables(THD *thd)
void
close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
- bool remove_from_locked_tables)
+ ha_extra_function extra)
{
char key[MAX_DBKEY_LENGTH];
uint key_length= share->table_cache_key.length;
@@ -1412,19 +1412,17 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
{
thd->locked_tables_list.unlink_from_list(thd,
table->pos_in_locked_tables,
- remove_from_locked_tables);
+ extra != HA_EXTRA_NORMAL);
+ /* Inform handler that there is a drop table or rename going on */
+ if (extra != HA_EXTRA_NORMAL && table->db_stat)
+ table->file->extra(extra);
+
/*
Does nothing if the table is not locked.
This allows one to use this function after a table
has been unlocked, e.g. in partition management.
*/
mysql_lock_remove(thd, thd->lock, table);
-
- /* Inform handler that table will be dropped after close */
-#ifdef MERGE_FOR_MONTY_TO_FIX
- if (remove_from_locked_tables && table->db_stat) /* Not true for partitioned tables. */
- table->file->extra(HA_EXTRA_PREPARE_FOR_DROP);
-#endif
close_thread_table(thd, prev);
}
else
diff --git a/sql/sql_base.h b/sql/sql_base.h
index e602aba98a9..3deb97c9730 100644
--- a/sql/sql_base.h
+++ b/sql/sql_base.h
@@ -289,7 +289,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables,
bool wait_for_refresh, ulong timeout);
bool close_cached_connection_tables(THD *thd, LEX_STRING *connect_string);
void close_all_tables_for_name(THD *thd, TABLE_SHARE *share,
- bool remove_from_locked_tables);
+ ha_extra_function extra);
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
void tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
const char *db, const char *table_name,
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 9ba0569f1e0..00c70c5f973 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -6270,7 +6270,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt)
THD *thd= lpt->thd;
if (lpt->old_table)
- close_all_tables_for_name(thd, lpt->old_table->s, FALSE);
+ close_all_tables_for_name(thd, lpt->old_table->s, HA_EXTRA_NORMAL);
if (lpt->table)
{
/*
@@ -6307,7 +6307,7 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt, bool close_old)
}
if (close_old && lpt->old_table)
{
- close_all_tables_for_name(lpt->thd, lpt->old_table->s, FALSE);
+ close_all_tables_for_name(lpt->thd, lpt->old_table->s, HA_EXTRA_NORMAL);
lpt->old_table= 0;
}
DBUG_RETURN(0);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 51d37be950c..51d1eab14f1 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2126,7 +2126,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
error= -1;
goto err;
}
- close_all_tables_for_name(thd, table->table->s, TRUE);
+ close_all_tables_for_name(thd, table->table->s,
+ HA_EXTRA_PREPARE_FOR_DROP);
table->table= 0;
}
@@ -2134,11 +2135,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db,
table->table_name,
MDL_EXCLUSIVE));
- if (thd->killed)
- {
- error= -1;
- goto err;
- }
+
alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
/* remove .frm file and engine files */
path_length= build_table_filename(path, sizeof(path) - 1, db, alias,
@@ -6188,7 +6185,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/
if (wait_while_table_is_used(thd, table, extra_func))
goto err;
- close_all_tables_for_name(thd, table->s, TRUE);
+ close_all_tables_for_name(thd, table->s, HA_EXTRA_PREPARE_FOR_RENAME);
/*
Then, we want check once again that target table does not exist.
Actually the order of these two steps does not matter since
@@ -6895,7 +6892,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
close_all_tables_for_name(thd, table->s,
- new_name != table_name || new_db != db);
+ new_name != table_name || new_db != db ?
+ HA_EXTRA_PREPARE_FOR_RENAME :
+ HA_EXTRA_NORMAL);
error=0;
table_list->table= table= 0; /* Safety */
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 1ac1d7bbb5e..2eefe7d2c74 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -561,7 +561,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (result)
goto end;
- close_all_tables_for_name(thd, table->s, FALSE);
+ close_all_tables_for_name(thd, table->s, HA_EXTRA_NORMAL);
/*
Reopen the table if we were under LOCK TABLES.
Ignore the return value for now. It's better to
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 67ed608f114..b84a00eb0fc 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -363,7 +363,7 @@ bool Truncate_statement::lock_table(THD *thd, TABLE_LIST *table_ref,
m_ticket_downgrade= table->mdl_ticket;
/* Close if table is going to be recreated. */
if (*hton_can_recreate)
- close_all_tables_for_name(thd, table->s, FALSE);
+ close_all_tables_for_name(thd, table->s, HA_EXTRA_PREPARE_FOR_DROP);
}
else
{