Commit d6aaa5fd authored by Konstantin Osipov's avatar Konstantin Osipov

Merge.

parents 736db89a fcae9927
...@@ -219,3 +219,34 @@ flush tables with read lock;; ...@@ -219,3 +219,34 @@ flush tables with read lock;;
connection: default connection: default
flush tables; flush tables;
drop table t1; drop table t1;
#
# Bug#47249 assert in MDL_global_lock::is_lock_type_compatible
#
DROP TABLE IF EXISTS t1;
DROP VIEW IF EXISTS v1;
#
# Test 1: LOCK TABLES v1 WRITE, t1 READ;
#
CREATE TABLE t1 ( f1 integer );
CREATE VIEW v1 AS SELECT f1 FROM t1 ;
# Connection 2
LOCK TABLES v1 WRITE, t1 READ;
FLUSH TABLE t1;
# Connection 1
LOCK TABLES t1 WRITE;
FLUSH TABLE t1;
DROP TABLE t1;
DROP VIEW v1;
#
# Test 2: LOCK TABLES t1 WRITE, v1 READ;
#
CREATE TABLE t1 ( f1 integer );
CREATE VIEW v1 AS SELECT f1 FROM t1 ;
# Connection 2
LOCK TABLES t1 WRITE, v1 READ;
FLUSH TABLE t1;
# Connection 1
LOCK TABLES t1 WRITE;
FLUSH TABLE t1;
DROP TABLE t1;
DROP VIEW v1;
...@@ -664,5 +664,63 @@ connection flush; ...@@ -664,5 +664,63 @@ connection flush;
--reap --reap
connection default; connection default;
disconnect flush; disconnect flush;
--echo #
--echo # Bug#47249 assert in MDL_global_lock::is_lock_type_compatible
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
DROP VIEW IF EXISTS v1;
--enable_warnings
--echo #
--echo # Test 1: LOCK TABLES v1 WRITE, t1 READ;
--echo #
CREATE TABLE t1 ( f1 integer );
CREATE VIEW v1 AS SELECT f1 FROM t1 ;
--echo # Connection 2
connect (con2,localhost,root);
LOCK TABLES v1 WRITE, t1 READ;
FLUSH TABLE t1;
disconnect con2;
--source include/wait_until_disconnected.inc
--echo # Connection 1
connection default;
LOCK TABLES t1 WRITE;
FLUSH TABLE t1; # Assertion happened here
# Cleanup
DROP TABLE t1;
DROP VIEW v1;
--echo #
--echo # Test 2: LOCK TABLES t1 WRITE, v1 READ;
--echo #
CREATE TABLE t1 ( f1 integer );
CREATE VIEW v1 AS SELECT f1 FROM t1 ;
--echo # Connection 2
connect (con2,localhost,root);
LOCK TABLES t1 WRITE, v1 READ;
FLUSH TABLE t1;
disconnect con2;
--source include/wait_until_disconnected.inc
--echo # Connection 1
connection default;
LOCK TABLES t1 WRITE;
FLUSH TABLE t1; # Assertion happened here
# Cleanup
DROP TABLE t1;
DROP VIEW v1;
# Wait till all disconnects are completed # Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc --source include/wait_until_count_sessions.inc
...@@ -1005,6 +1005,9 @@ MDL_ticket::upgrade_shared_lock_to_exclusive() ...@@ -1005,6 +1005,9 @@ MDL_ticket::upgrade_shared_lock_to_exclusive()
if (m_type == MDL_EXCLUSIVE) if (m_type == MDL_EXCLUSIVE)
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
/* Only allow upgrades from MDL_SHARED_UPGRADABLE */
DBUG_ASSERT(m_type == MDL_SHARED_UPGRADABLE);
pthread_mutex_lock(&LOCK_mdl); pthread_mutex_lock(&LOCK_mdl);
old_msg= MDL_ENTER_COND(thd, mysys_var); old_msg= MDL_ENTER_COND(thd, mysys_var);
......
...@@ -254,6 +254,10 @@ public: ...@@ -254,6 +254,10 @@ public:
mdl_cached_object_release_hook release_hook); mdl_cached_object_release_hook release_hook);
const MDL_context *get_ctx() const { return m_ctx; } const MDL_context *get_ctx() const { return m_ctx; }
bool is_shared() const { return m_type < MDL_EXCLUSIVE; } bool is_shared() const { return m_type < MDL_EXCLUSIVE; }
bool is_upgradable_or_exclusive() const
{
return m_type == MDL_SHARED_UPGRADABLE || m_type == MDL_EXCLUSIVE;
}
bool upgrade_shared_lock_to_exclusive(); bool upgrade_shared_lock_to_exclusive();
void downgrade_exclusive_lock(); void downgrade_exclusive_lock();
private: private:
......
...@@ -130,6 +130,8 @@ static bool tdc_wait_for_old_versions(THD *thd, ...@@ -130,6 +130,8 @@ static bool tdc_wait_for_old_versions(THD *thd,
static bool static bool
has_write_table_with_auto_increment(TABLE_LIST *tables); has_write_table_with_auto_increment(TABLE_LIST *tables);
TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db,
const char *table_name);
uint cached_open_tables(void) uint cached_open_tables(void)
{ {
...@@ -999,7 +1001,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, ...@@ -999,7 +1001,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
table_list= table_list->next_global) table_list= table_list->next_global)
{ {
/* A check that the table was locked for write is done by the caller. */ /* A check that the table was locked for write is done by the caller. */
TABLE *table= find_locked_table(thd->open_tables, table_list->db, TABLE *table= find_table_for_mdl_upgrade(thd->open_tables, table_list->db,
table_list->table_name); table_list->table_name);
/* May return NULL if this table has already been closed via an alias. */ /* May return NULL if this table has already been closed via an alias. */
...@@ -2942,6 +2944,34 @@ TABLE *find_write_locked_table(TABLE *list, const char *db, const char *table_na ...@@ -2942,6 +2944,34 @@ TABLE *find_write_locked_table(TABLE *list, const char *db, const char *table_na
} }
/**
Find instance of TABLE with MDL_SHARED_UPGRADABLE or
MDL_EXCLUSIVE lock from the list of open tables.
@param list List of TABLE objects to be searched
@param db Database name.
@param table_name Name of table.
@return Pointer to MDL_SHARED_UPGRADABLE or MDL_EXCLUSIVE
TABLE instance, NULL otherwise.
*/
TABLE *find_table_for_mdl_upgrade(TABLE *list, const char *db,
const char *table_name)
{
TABLE *tab= find_locked_table(list, db, table_name);
while (tab != NULL)
{
if (tab->mdl_ticket != NULL &&
tab->mdl_ticket->is_upgradable_or_exclusive())
return tab;
tab= find_locked_table(tab->next, db, table_name);
}
return NULL;
}
/*********************************************************************** /***********************************************************************
class Locked_tables_list implementation. Declared in sql_class.h class Locked_tables_list implementation. Declared in sql_class.h
************************************************************************/ ************************************************************************/
......
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