diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index 6d31d01d154..b04a5fb0a3e 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -50,14 +50,6 @@ Field Type Null Key Default Extra a int(11) YES NULL unlock tables; drop table t1; -CREATE DATABASE mysqltest_1; -FLUSH TABLES WITH READ LOCK; - DROP DATABASE mysqltest_1; -DROP DATABASE mysqltest_1; -ERROR HY000: Can't execute the query because you have a conflicting read lock -UNLOCK TABLES; -DROP DATABASE mysqltest_1; -ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist use mysql; LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; FLUSH TABLES; @@ -74,3 +66,11 @@ Select_priv N use test; use test; +CREATE DATABASE mysqltest_1; +FLUSH TABLES WITH READ LOCK; + DROP DATABASE mysqltest_1; +DROP DATABASE mysqltest_1; +ERROR HY000: Can't execute the query because you have a conflicting read lock +UNLOCK TABLES; +DROP DATABASE mysqltest_1; +ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 7fc65f52214..d0577d6f2f3 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -128,6 +128,36 @@ unlock tables; drop table t1; # +# Bug#16986 - Deadlock condition with MyISAM tables +# +connection locker; +use mysql; +LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; +FLUSH TABLES; +--sleep 1 +# +connection reader; +use mysql; +#NOTE: This must be a multi-table select, otherwise the deadlock will not occur +send SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1; +--sleep 1 +# +connection locker; +# Make test case independent from earlier grants. +--replace_result "Table is already up to date" "OK" +OPTIMIZE TABLES columns_priv, db, host, user; +UNLOCK TABLES; +# +connection reader; +reap; +use test; +# +connection locker; +use test; +# +connection default; + +# End of 5.0 tests # Bug#19815 - CREATE/RENAME/DROP DATABASE can deadlock on a global read lock # connect (con1,localhost,root,,); @@ -161,33 +191,3 @@ disconnect con2; --error ER_DB_DROP_EXISTS DROP DATABASE mysqltest_1; -# Bug#16986 - Deadlock condition with MyISAM tables -# -connection locker; -use mysql; -LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; -FLUSH TABLES; ---sleep 1 -# -connection reader; -use mysql; -#NOTE: This must be a multi-table select, otherwise the deadlock will not occur -send SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1; ---sleep 1 -# -connection locker; -# Make test case independent from earlier grants. ---replace_result "Table is already up to date" "OK" -OPTIMIZE TABLES columns_priv, db, host, user; -UNLOCK TABLES; -# -connection reader; -reap; -use test; -# -connection locker; -use test; -# -connection default; - -# End of 5.0 tests diff --git a/sql/handler.cc b/sql/handler.cc index 81c42f9da15..47bcf1caba1 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -68,14 +68,14 @@ ulong total_ha_2pc= 0; /* size of savepoint storage area (see ha_init) */ ulong savepoint_alloc_size= 0; -struct show_table_alias_st sys_table_aliases[]= +static const LEX_STRING sys_table_aliases[]= { - {"INNOBASE", DB_TYPE_INNODB}, - {"NDB", DB_TYPE_NDBCLUSTER}, - {"BDB", DB_TYPE_BERKELEY_DB}, - {"HEAP", DB_TYPE_HEAP}, - {"MERGE", DB_TYPE_MRG_MYISAM}, - {NullS, DB_TYPE_UNKNOWN} + {(char*)STRING_WITH_LEN("INNOBASE")}, {(char*)STRING_WITH_LEN("INNODB")}, + {(char*)STRING_WITH_LEN("NDB")}, {(char*)STRING_WITH_LEN("NDBCLUSTER")}, + {(char*)STRING_WITH_LEN("BDB")}, {(char*)STRING_WITH_LEN("BERKELEYDB")}, + {(char*)STRING_WITH_LEN("HEAP")}, {(char*)STRING_WITH_LEN("MEMORY")}, + {(char*)STRING_WITH_LEN("MERGE")}, {(char*)STRING_WITH_LEN("MRG_MYISAM")}, + {NullS, 0} }; const char *ha_row_type[] = { @@ -91,15 +91,50 @@ TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"", static TYPELIB known_extensions= {0,"known_exts", NULL, NULL}; uint known_extensions_id= 0; -handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name) + +/* + Return the default storage engine handlerton for thread + + SYNOPSIS + ha_default_handlerton(thd) + thd current thread + + RETURN + pointer to handlerton +*/ + +handlerton *ha_default_handlerton(THD *thd) { - show_table_alias_st *table_alias; + return (thd->variables.table_type != NULL) ? + thd->variables.table_type : + (global_system_variables.table_type != NULL ? + global_system_variables.table_type : &myisam_hton); +} + + +/* + Return the storage engine handlerton for the supplied name + + SYNOPSIS + ha_resolve_by_name(thd, name) + thd current thread + name name of storage engine + + RETURN + pointer to handlerton +*/ + +handlerton *ha_resolve_by_name(THD *thd, const LEX_STRING *name) +{ + const LEX_STRING *table_alias; st_plugin_int *plugin; - if (thd && !my_strnncoll(&my_charset_latin1, +redo: + /* my_strnncoll is a macro and gcc doesn't do early expansion of macro */ + if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1, (const uchar *)name->str, name->length, - (const uchar *)"DEFAULT", 7)) - return ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT); + (const uchar *)STRING_WITH_LEN("DEFAULT"), 0)) + return ha_default_handlerton(thd); if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN))) { @@ -112,13 +147,15 @@ handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name) /* We check for the historical aliases. */ - for (table_alias= sys_table_aliases; table_alias->type; table_alias++) + for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2) { if (!my_strnncoll(&my_charset_latin1, (const uchar *)name->str, name->length, - (const uchar *)table_alias->alias, - strlen(table_alias->alias))) - return ha_resolve_by_legacy_type(thd, table_alias->type); + (const uchar *)table_alias->str, table_alias->length)) + { + name= table_alias + 1; + goto redo; + } } return NULL; @@ -130,20 +167,20 @@ const char *ha_get_storage_engine(enum legacy_db_type db_type) switch (db_type) { case DB_TYPE_DEFAULT: return "DEFAULT"; - case DB_TYPE_UNKNOWN: - return "UNKNOWN"; default: if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT && installed_htons[db_type]) return hton2plugin[installed_htons[db_type]->slot]->name.str; - return "*NONE*"; + /* fall through */ + case DB_TYPE_UNKNOWN: + return "UNKNOWN"; } } static handler *create_default(TABLE_SHARE *table, MEM_ROOT *mem_root) { - handlerton *hton=ha_resolve_by_legacy_type(current_thd, DB_TYPE_DEFAULT); + handlerton *hton= ha_default_handlerton(current_thd); return (hton && hton->create) ? hton->create(table, mem_root) : NULL; } @@ -152,10 +189,7 @@ handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type) { switch (db_type) { case DB_TYPE_DEFAULT: - return (thd->variables.table_type != NULL) ? - thd->variables.table_type : - (global_system_variables.table_type != NULL ? - global_system_variables.table_type : &myisam_hton); + return ha_default_handlerton(thd); case DB_TYPE_UNKNOWN: return NULL; default: @@ -196,7 +230,7 @@ handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type, break; } - return ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT); + return ha_default_handlerton(thd); } /* ha_checktype */ diff --git a/sql/handler.h b/sql/handler.h index f459d52fdeb..52843b78266 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -667,10 +667,6 @@ struct handlerton struct handler_iterator *fill_this_in); }; -struct show_table_alias_st { - const char *alias; - enum legacy_db_type type; -}; /* Possible flags of a handlerton */ #define HTON_NO_FLAGS 0 @@ -1545,7 +1541,8 @@ extern ulong total_ha, total_ha_2pc; #define ha_rollback(thd) (ha_rollback_trans((thd), TRUE)) /* lookups */ -handlerton *ha_resolve_by_name(THD *thd, LEX_STRING *name); +handlerton *ha_default_handlerton(THD *thd); +handlerton *ha_resolve_by_name(THD *thd, const LEX_STRING *name); handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type); const char *ha_get_storage_engine(enum legacy_db_type db_type); handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index dda2fbc3588..851c3111a79 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4984,11 +4984,12 @@ Disable with --skip-bdb (will save memory).", (gptr*) &default_collation_name, (gptr*) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-storage-engine", OPT_STORAGE_ENGINE, - "Set the default storage engine (table type) for tables.", 0, 0, + "Set the default storage engine (table type) for tables.", + (gptr*)&default_storage_engine_str, (gptr*)&default_storage_engine_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-table-type", OPT_STORAGE_ENGINE, "(deprecated) Use --default-storage-engine.", - (gptr*)default_storage_engine_str, (gptr*)default_storage_engine_str, + (gptr*)&default_storage_engine_str, (gptr*)&default_storage_engine_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.", (gptr*) &default_tz_name, (gptr*) &default_tz_name, diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index c15b484f448..f7205470abd 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -23,7 +23,7 @@ extern struct st_mysql_plugin *mysqld_builtins[]; char *opt_plugin_dir_ptr; char opt_plugin_dir[FN_REFLEN]; -LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]= +const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]= { { (char *)STRING_WITH_LEN("UDF") }, { (char *)STRING_WITH_LEN("STORAGE ENGINE") }, @@ -63,7 +63,7 @@ static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; static rw_lock_t THR_LOCK_plugin; static bool initialized= 0; -static struct st_plugin_dl *plugin_dl_find(LEX_STRING *dl) +static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *dl) { uint i; DBUG_ENTER("plugin_dl_find"); @@ -112,7 +112,7 @@ static inline void free_plugin_mem(struct st_plugin_dl *p) my_free((gptr)p->plugins, MYF(MY_ALLOW_ZERO_PTR)); } -static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) +static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) { #ifdef HAVE_DLOPEN char dlpath[FN_REFLEN]; @@ -294,7 +294,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report) } -static void plugin_dl_del(LEX_STRING *dl) +static void plugin_dl_del(const LEX_STRING *dl) { #ifdef HAVE_DLOPEN uint i; @@ -322,7 +322,7 @@ static void plugin_dl_del(LEX_STRING *dl) } -static struct st_plugin_int *plugin_find_internal(LEX_STRING *name, int type) +static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int type) { uint i; DBUG_ENTER("plugin_find_internal"); @@ -345,7 +345,7 @@ static struct st_plugin_int *plugin_find_internal(LEX_STRING *name, int type) } -my_bool plugin_is_ready(LEX_STRING *name, int type) +my_bool plugin_is_ready(const LEX_STRING *name, int type) { my_bool rc= FALSE; struct st_plugin_int *plugin; @@ -359,7 +359,7 @@ my_bool plugin_is_ready(LEX_STRING *name, int type) } -struct st_plugin_int *plugin_lock(LEX_STRING *name, int type) +struct st_plugin_int *plugin_lock(const LEX_STRING *name, int type) { struct st_plugin_int *rc; DBUG_ENTER("plugin_lock"); @@ -396,7 +396,7 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin) struct st_plugin_int *)); } -static my_bool plugin_add(LEX_STRING *name, LEX_STRING *dl, int report) +static my_bool plugin_add(const LEX_STRING *name, const LEX_STRING *dl, int report) { struct st_plugin_int tmp; struct st_mysql_plugin *plugin; @@ -479,7 +479,7 @@ err: } -static void plugin_del(LEX_STRING *name) +static void plugin_del(const LEX_STRING *name) { uint i; struct st_plugin_int *plugin; @@ -811,7 +811,7 @@ void plugin_free(void) } -my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl) +my_bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl) { TABLE_LIST tables; TABLE *table; @@ -866,7 +866,7 @@ err: } -my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name) +my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) { TABLE *table; TABLE_LIST tables; diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index b013beaba1f..df7c9a39495 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -66,15 +66,15 @@ typedef int (*plugin_type_init)(struct st_plugin_int *); extern char *opt_plugin_dir_ptr; extern char opt_plugin_dir[FN_REFLEN]; -extern LEX_STRING plugin_type_names[]; +extern const LEX_STRING plugin_type_names[]; extern int plugin_init(void); extern void plugin_load(void); extern void plugin_free(void); -extern my_bool plugin_is_ready(LEX_STRING *name, int type); -extern st_plugin_int *plugin_lock(LEX_STRING *name, int type); +extern my_bool plugin_is_ready(const LEX_STRING *name, int type); +extern st_plugin_int *plugin_lock(const LEX_STRING *name, int type); extern void plugin_unlock(struct st_plugin_int *plugin); -extern my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl); -extern my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name); +extern my_bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl); +extern my_bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name); extern my_bool plugin_register_builtin(struct st_mysql_plugin *plugin); diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index 94318a67575..13dfb491af4 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -30,7 +30,7 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) */ if (hton == NULL || hton->state != SHOW_OPTION_YES) { - hton= ha_resolve_by_legacy_type(thd, DB_TYPE_DEFAULT); + hton= ha_default_handlerton(thd); if (ts_info->storage_engine != 0) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_WARN_USING_OTHER_HANDLER,