diff options
Diffstat (limited to 'sql/sql_db.cc')
-rw-r--r-- | sql/sql_db.cc | 166 |
1 files changed, 100 insertions, 66 deletions
diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 6c8c384e544..f626b4e6112 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -62,6 +62,8 @@ static void mysql_change_db_impl(THD *thd, LEX_STRING *new_db_name, ulong new_db_access, CHARSET_INFO *new_db_charset); +static bool mysql_rm_db_internal(THD *thd, char *db, + bool if_exists, bool silent); /* Database options hash */ @@ -233,7 +235,7 @@ void my_dbopt_cleanup(void) 1 on error. */ -static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create) +static my_bool get_dbopt(const char *dbname, Schema_specification_st *create) { my_dbopt_t *opt; uint length; @@ -264,7 +266,7 @@ static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create) 1 on error. */ -static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create) +static my_bool put_dbopt(const char *dbname, Schema_specification_st *create) { my_dbopt_t *opt; uint length; @@ -333,7 +335,8 @@ static void del_dbopt(const char *path) 1 Could not create file or write to it. Error sent through my_error() */ -static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) +static bool write_db_opt(THD *thd, const char *path, + Schema_specification_st *create) { register File file; char buf[256]; // Should be enough for one option @@ -379,7 +382,7 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) */ -bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) +bool load_db_opt(THD *thd, const char *path, Schema_specification_st *create) { File file; char buf[256]; @@ -427,7 +430,7 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) get_charset_by_name(pos+1, MYF(0)))) { sql_print_error("Error while loading database options: '%s':",path); - sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1); + sql_print_error(ER_THD(thd, ER_UNKNOWN_CHARACTER_SET),pos+1); create->default_table_charset= default_charset_info; } } @@ -437,7 +440,7 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) MYF(0)))) { sql_print_error("Error while loading database options: '%s':",path); - sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1); + sql_print_error(ER_THD(thd, ER_UNKNOWN_COLLATION),pos+1); create->default_table_charset= default_charset_info; } } @@ -491,7 +494,7 @@ err1: */ bool load_db_opt_by_name(THD *thd, const char *db_name, - HA_CREATE_INFO *db_create_info) + Schema_specification_st *db_create_info) { char db_opt_path[FN_REFLEN + 1]; @@ -518,7 +521,7 @@ bool load_db_opt_by_name(THD *thd, const char *db_name, CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name) { - HA_CREATE_INFO db_info; + Schema_specification_st db_info; if (thd->db != NULL && strcmp(db_name, thd->db) == 0) return thd->db_charset; @@ -541,10 +544,11 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name) Create a database SYNOPSIS - mysql_create_db() + mysql_create_db_iternal() thd Thread handler db Name of database to create Function assumes that this is already validated. + options DDL options, e.g. IF NOT EXISTS create_info Database create options (like character set) silent Used by replication when internally creating a database. In this case the entry should not be logged. @@ -561,14 +565,14 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name) */ -int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, - bool silent) +static int +mysql_create_db_internal(THD *thd, char *db, + const DDL_options_st &options, + Schema_specification_st *create_info, + bool silent) { char path[FN_REFLEN+16]; - long result= 1; - int error= 0; MY_STAT stat_info; - uint create_options= create_info ? create_info->options : 0; uint path_len; DBUG_ENTER("mysql_create_db"); @@ -596,32 +600,46 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, path_len= build_table_filename(path, sizeof(path) - 1, db, "", "", 0); path[path_len-1]= 0; // Remove last '/' from path - if (mysql_file_stat(key_file_misc, path, &stat_info, MYF(0))) + long affected_rows= 1; + if (!mysql_file_stat(key_file_misc, path, &stat_info, MYF(0))) { - if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS)) + // The database directory does not exist, or my_file_stat() failed + if (my_errno != ENOENT) { - my_error(ER_DB_CREATE_EXISTS, MYF(0), db); - error= -1; - goto exit; + my_error(EE_STAT, MYF(0), path, my_errno); + DBUG_RETURN(1); } + } + else if (options.or_replace()) + { + if (mysql_rm_db_internal(thd, db, 0, true)) // Removing the old database + DBUG_RETURN(1); + /* + Reset the diagnostics m_status. + It might be set ot DA_OK in mysql_rm_db. + */ + thd->get_stmt_da()->reset_diagnostics_area(); + affected_rows= 2; + } + else if (options.if_not_exists()) + { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db); - error= 0; + ER_DB_CREATE_EXISTS, ER_THD(thd, ER_DB_CREATE_EXISTS), + db); + affected_rows= 0; goto not_silent; } else { - if (my_errno != ENOENT) - { - my_error(EE_STAT, MYF(0), path, my_errno); - goto exit; - } - if (my_mkdir(path,0777,MYF(0)) < 0) - { - my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno); - error= -1; - goto exit; - } + my_error(ER_DB_CREATE_EXISTS, MYF(0), db); + DBUG_RETURN(-1); + } + + + if (my_mkdir(path, 0777, MYF(0)) < 0) + { + my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno); + DBUG_RETURN(-1); } path[path_len-1]= FN_LIBCHAR; @@ -634,10 +652,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, */ path[path_len]= 0; if (rmdir(path) >= 0) - { - error= -1; - goto exit; - } + DBUG_RETURN(-1); /* We come here when we managed to create the database, but not the option file. In this case it's best to just continue as if nothing has @@ -656,10 +671,6 @@ not_silent: query_length= thd->query_length(); DBUG_ASSERT(query); - ha_binlog_log_query(thd, 0, LOGCOM_CREATE_DB, - query, query_length, - db, ""); - if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, TRUE); @@ -691,22 +702,20 @@ not_silent: metadata lock on the schema */ if (mysql_bin_log.write(&qinfo)) - { - error= -1; - goto exit; - } + DBUG_RETURN(-1); } - my_ok(thd, result); + my_ok(thd, affected_rows); } -exit: - DBUG_RETURN(error); + DBUG_RETURN(0); } /* db-name is already validated when we come here */ -bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) +static bool +mysql_alter_db_internal(THD *thd, const char *db, + Schema_specification_st *create_info) { char path[FN_REFLEN+16]; long result=1; @@ -735,10 +744,6 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) thd->variables.collation_database= thd->db_charset; } - ha_binlog_log_query(thd, 0, LOGCOM_ALTER_DB, - thd->query(), thd->query_length(), - db, ""); - if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, TRUE); @@ -766,6 +771,31 @@ exit: } +int mysql_create_db(THD *thd, char *db, + const DDL_options_st &options, + const Schema_specification_st *create_info) +{ + /* + As mysql_create_db_internal() may modify Db_create_info structure passed + to it, we need to use a copy to make execution prepared statement- safe. + */ + Schema_specification_st tmp(*create_info); + return mysql_create_db_internal(thd, db, options, &tmp, false); +} + + +bool mysql_alter_db(THD *thd, const char *db, + const Schema_specification_st *create_info) +{ + /* + As mysql_alter_db_internal() may modify Db_create_info structure passed + to it, we need to use a copy to make execution prepared statement- safe. + */ + Schema_specification_st tmp(*create_info); + return mysql_alter_db_internal(thd, db, &tmp); +} + + /** Drop all tables, routines and events in a database and the database itself. @@ -781,7 +811,8 @@ exit: @retval true Error */ -bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) +static bool +mysql_rm_db_internal(THD *thd,char *db, bool if_exists, bool silent) { ulong deleted_tables= 0; bool error= true, rm_mysql_schema; @@ -835,7 +866,8 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) else { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db); + ER_DB_DROP_EXISTS, ER_THD(thd, ER_DB_DROP_EXISTS), + db); error= false; goto update_binlog; } @@ -897,11 +929,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) should be dropped while the database is being cleaned, but in the event that a change in the code to remove other objects is made, these drops should still not be logged. - - Notice that the binary log have to be enabled over the call to - ha_drop_database(), since NDB otherwise detects the binary log - as disabled and will not log the drop database statement on any - other connected server. */ ha_drop_database(path); @@ -1030,6 +1057,12 @@ exit: } +bool mysql_rm_db(THD *thd,char *db, bool if_exists) +{ + return mysql_rm_db_internal(thd, db, if_exists, false); +} + + static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp, char *dbname, const char *path, @@ -1446,7 +1479,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) } else { - my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); + my_message(ER_NO_DB_ERROR, ER_THD(thd, ER_NO_DB_ERROR), MYF(0)); DBUG_RETURN(TRUE); } @@ -1521,7 +1554,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) sctx->priv_user, sctx->priv_host, new_db_file_name.str); - general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), + general_log_print(thd, COM_INIT_DB, ER_THD(thd, ER_DBACCESS_DENIED_ERROR), sctx->priv_user, sctx->priv_host, new_db_file_name.str); my_free(new_db_file_name.str); DBUG_RETURN(TRUE); @@ -1537,7 +1570,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) /* Throw a warning and free new_db_file_name. */ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR), + ER_BAD_DB_ERROR, ER_THD(thd, ER_BAD_DB_ERROR), new_db_file_name.str); my_free(new_db_file_name.str); @@ -1632,7 +1665,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) int error= 0, change_to_newdb= 0; char path[FN_REFLEN+16]; uint length; - HA_CREATE_INFO create_info; + Schema_specification_st create_info; MY_DIR *dirp; TABLE_LIST *table_list; SELECT_LEX *sl= thd->lex->current_select; @@ -1680,7 +1713,8 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) } /* Step1: Create the new database */ - if ((error= mysql_create_db(thd, new_db.str, &create_info, 1))) + if ((error= mysql_create_db_internal(thd, new_db.str, + DDL_options(), &create_info, 1))) goto exit; /* Step2: Move tables to the new database */ @@ -1704,7 +1738,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) table_str.length= filename_to_tablename(file->name, tname, sizeof(tname)-1); - table_str.str= (char*) sql_memdup(tname, table_str.length + 1); + table_str.str= (char*) thd->memdup(tname, table_str.length + 1); Table_ident *old_ident= new Table_ident(thd, *old_db, table_str, 0); Table_ident *new_ident= new Table_ident(thd, new_db, table_str, 0); if (!old_ident || !new_ident || @@ -1804,7 +1838,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) to execute them again. mysql_rm_db() also "unuses" if we drop the current database. */ - error= mysql_rm_db(thd, old_db->str, 0, 1); + error= mysql_rm_db_internal(thd, old_db->str, 0, true); /* Step8: logging */ if (mysql_bin_log.is_open()) |