summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_db.cc123
-rw-r--r--sql/sql_db.h6
-rw-r--r--sql/sql_parse.cc4
-rw-r--r--sql/sql_yacc.yy5
4 files changed, 90 insertions, 48 deletions
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index a2f4322d071..24814497600 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 */
@@ -542,7 +544,7 @@ 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.
@@ -563,14 +565,13 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
*/
-int mysql_create_db(THD *thd, char *db,
- const DDL_options_st &options,
- Schema_specification_st *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 path_len;
DBUG_ENTER("mysql_create_db");
@@ -599,32 +600,45 @@ int mysql_create_db(THD *thd, char *db,
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 (!options.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(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;
@@ -637,10 +651,7 @@ int mysql_create_db(THD *thd, char *db,
*/
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
@@ -690,23 +701,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,
- Schema_specification_st *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;
@@ -762,6 +770,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.
@@ -777,7 +810,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;
@@ -1004,6 +1038,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,
@@ -1654,7 +1694,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, DDL_options(), &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 */
@@ -1778,7 +1819,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())
diff --git a/sql/sql_db.h b/sql/sql_db.h
index bdd525779f0..b0d99cc1ba4 100644
--- a/sql/sql_db.h
+++ b/sql/sql_db.h
@@ -22,10 +22,10 @@ class THD;
int mysql_create_db(THD *thd, char *db,
const DDL_options_st &options,
- Schema_specification_st *create, bool silent);
+ const Schema_specification_st *create);
bool mysql_alter_db(THD *thd, const char *db,
- Schema_specification_st *create);
-bool mysql_rm_db(THD *thd, char *db, bool if_exists, bool silent);
+ const Schema_specification_st *create);
+bool mysql_rm_db(THD *thd, char *db, bool if_exists);
bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db);
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
bool force_switch);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 60d721d710e..ae8ab32a7ec 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4301,7 +4301,7 @@ end_with_restore_list:
if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0))
break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
- res= mysql_create_db(thd, lex->name.str, lex->create_info, &create_info, 0);
+ res= mysql_create_db(thd, lex->name.str, lex->create_info, &create_info);
break;
}
case SQLCOM_DROP_DB:
@@ -4333,7 +4333,7 @@ end_with_restore_list:
if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0))
break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL)
- res= mysql_rm_db(thd, lex->name.str, lex->if_exists(), 0);
+ res= mysql_rm_db(thd, lex->name.str, lex->if_exists());
break;
}
case SQLCOM_ALTER_DB_UPGRADE:
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 879697e1507..f9e6c9653f5 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2538,7 +2538,7 @@ create:
MYSQL_YYABORT;
}
opt_index_lock_algorithm { }
- | CREATE DATABASE opt_if_not_exists ident
+ | create_or_replace DATABASE opt_if_not_exists ident
{
Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0;
@@ -2546,7 +2546,8 @@ create:
opt_create_database_options
{
LEX *lex=Lex;
- lex->set_command(SQLCOM_CREATE_DB, $3);
+ if (lex->set_command_with_check(SQLCOM_CREATE_DB, 0, $1 | $3))
+ MYSQL_YYABORT;
lex->name= $4;
}
| create_or_replace