Commit dd270e43 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-7280 DATABASE: CREATE OR REPLACE

parent c6d3f805
CREATE OR REPLACE DATABASE d1;
CREATE OR REPLACE DATABASE d1;
DROP DATABASE d1;
CREATE DATABASE IF NOT EXISTS d1;
CREATE DATABASE IF NOT EXISTS d1;
Warnings:
Note 1007 Can't create database 'd1'; database exists
DROP DATABASE IF EXISTS d1;
DROP DATABASE IF EXISTS d1;
Warnings:
Note 1008 Can't drop database 'd1'; database doesn't exist
"Runnig SHOW BINLOG EVENTS"
Log_name Pos Event_type Server_id End_log_pos Info
# # Gtid 1 # GTID #-#-#
# # Query 1 # CREATE OR REPLACE DATABASE d1
# # Gtid 1 # GTID #-#-#
# # Query 1 # CREATE OR REPLACE DATABASE d1
# # Gtid 1 # GTID #-#-#
# # Query 1 # DROP DATABASE d1
# # Gtid 1 # GTID #-#-#
# # Query 1 # CREATE DATABASE IF NOT EXISTS d1
# # Gtid 1 # GTID #-#-#
# # Query 1 # CREATE DATABASE IF NOT EXISTS d1
# # Gtid 1 # GTID #-#-#
# # Query 1 # DROP DATABASE IF EXISTS d1
# # Gtid 1 # GTID #-#-#
# # Query 1 # DROP DATABASE IF EXISTS d1
RESET MASTER;
USE test;
CREATE DATABASE IF NOT EXISTS db1;
affected rows: 1
CREATE DATABASE IF NOT EXISTS db1;
affected rows: 0
Warnings:
Note 1007 Can't create database 'db1'; database exists
CREATE TABLE db1.t1 (a INT);
affected rows: 0
SHOW TABLES IN db1;
Tables_in_db1
t1
affected rows: 1
CREATE OR REPLACE DATABASE db1;
affected rows: 2
SHOW TABLES IN db1;
Tables_in_db1
affected rows: 0
CREATE OR REPLACE DATABASE IF NOT EXISTS db2;
ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS
DROP DATABASE db1;
affected rows: 0
DROP DATABASE IF EXISTS db1;
affected rows: 0
Warnings:
Note 1008 Can't drop database 'db1'; database doesn't exist
DROP DATABASE db1;
ERROR HY000: Can't drop database 'db1'; database doesn't exist
CREATE OR REPLACE DATABASE db1;
affected rows: 1
SHOW TABLES IN db1;
Tables_in_db1
affected rows: 0
CREATE DATABASE db1;
ERROR HY000: Can't create database 'db1'; database exists
DROP DATABASE IF EXISTS db1;
affected rows: 0
DROP DATABASE IF EXISTS db1;
affected rows: 0
Warnings:
Note 1008 Can't drop database 'db1'; database doesn't exist
include/master-slave.inc
[connection master]
CREATE DATABASE db1;
CREATE DATABASE IF NOT EXISTS db1;
Warnings:
Note 1007 Can't create database 'db1'; database exists
CREATE OR REPLACE DATABASE db2;
CREATE OR REPLACE DATABASE db1;
SHOW DATABASES;
Database
db1
db2
information_schema
mtr
mysql
performance_schema
test
CREATE DATABASE db1;
ERROR HY000: Can't create database 'db1'; database exists
DROP DATABASE db3;
ERROR HY000: Can't drop database 'db3'; database doesn't exist
CREATE DATABASE IF NOT EXISTS db3;
SHOW DATABASES;
Database
db1
db2
db3
information_schema
mtr
mysql
performance_schema
test
DROP DATABASE db1;
DROP DATABASE db2;
DROP DATABASE IF EXISTS db3;
SHOW DATABASES;
Database
information_schema
mtr
mysql
performance_schema
test
include/rpl_end.inc
--source include/master-slave.inc
connection master;
CREATE DATABASE db1;
CREATE DATABASE IF NOT EXISTS db1;
CREATE OR REPLACE DATABASE db2;
CREATE OR REPLACE DATABASE db1;
sync_slave_with_master;
SHOW DATABASES;
connection master;
--error ER_DB_CREATE_EXISTS
CREATE DATABASE db1;
--error ER_DB_DROP_EXISTS
DROP DATABASE db3;
CREATE DATABASE IF NOT EXISTS db3;
sync_slave_with_master;
SHOW DATABASES;
connection master;
DROP DATABASE db1;
DROP DATABASE db2;
DROP DATABASE IF EXISTS db3;
sync_slave_with_master;
SHOW DATABASES;
--source include/rpl_end.inc
--source include/have_log_bin.inc
--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1)
--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
CREATE OR REPLACE DATABASE d1;
CREATE OR REPLACE DATABASE d1;
DROP DATABASE d1;
CREATE DATABASE IF NOT EXISTS d1;
CREATE DATABASE IF NOT EXISTS d1;
DROP DATABASE IF EXISTS d1;
DROP DATABASE IF EXISTS d1;
--echo "Runnig SHOW BINLOG EVENTS"
--replace_column 1 # 2 # 5 #
--replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VERSIONS/
--disable_query_log
--eval SHOW BINLOG EVENTS FROM $binlog_start;
--enable_query_log
RESET MASTER;
USE test;
# Enable diisplaying rows affected
--enable_info
CREATE DATABASE IF NOT EXISTS db1;
CREATE DATABASE IF NOT EXISTS db1;
CREATE TABLE db1.t1 (a INT);
SHOW TABLES IN db1;
CREATE OR REPLACE DATABASE db1;
SHOW TABLES IN db1;
--error ER_WRONG_USAGE
CREATE OR REPLACE DATABASE IF NOT EXISTS db2;
DROP DATABASE db1;
DROP DATABASE IF EXISTS db1;
--error ER_DB_DROP_EXISTS
DROP DATABASE db1;
CREATE OR REPLACE DATABASE db1;
SHOW TABLES IN db1;
--error ER_DB_CREATE_EXISTS
CREATE DATABASE db1;
DROP DATABASE IF EXISTS db1;
DROP DATABASE IF EXISTS db1;
--disable_info
...@@ -62,6 +62,8 @@ static void mysql_change_db_impl(THD *thd, ...@@ -62,6 +62,8 @@ static void mysql_change_db_impl(THD *thd,
LEX_STRING *new_db_name, LEX_STRING *new_db_name,
ulong new_db_access, ulong new_db_access,
CHARSET_INFO *new_db_charset); CHARSET_INFO *new_db_charset);
static bool mysql_rm_db_internal(THD *thd, char *db,
bool if_exists, bool silent);
/* Database options hash */ /* Database options hash */
...@@ -542,7 +544,7 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name) ...@@ -542,7 +544,7 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
Create a database Create a database
SYNOPSIS SYNOPSIS
mysql_create_db() mysql_create_db_iternal()
thd Thread handler thd Thread handler
db Name of database to create db Name of database to create
Function assumes that this is already validated. Function assumes that this is already validated.
...@@ -563,14 +565,13 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name) ...@@ -563,14 +565,13 @@ CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
*/ */
int mysql_create_db(THD *thd, char *db, static int
const DDL_options_st &options, mysql_create_db_internal(THD *thd, char *db,
Schema_specification_st *create_info, const DDL_options_st &options,
bool silent) Schema_specification_st *create_info,
bool silent)
{ {
char path[FN_REFLEN+16]; char path[FN_REFLEN+16];
long result= 1;
int error= 0;
MY_STAT stat_info; MY_STAT stat_info;
uint path_len; uint path_len;
DBUG_ENTER("mysql_create_db"); DBUG_ENTER("mysql_create_db");
...@@ -599,32 +600,45 @@ int mysql_create_db(THD *thd, char *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_len= build_table_filename(path, sizeof(path) - 1, db, "", "", 0);
path[path_len-1]= 0; // Remove last '/' from path 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); my_error(EE_STAT, MYF(0), path, my_errno);
error= -1; DBUG_RETURN(1);
goto exit;
} }
}
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, push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db); ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
error= 0; affected_rows= 0;
goto not_silent; goto not_silent;
} }
else else
{ {
if (my_errno != ENOENT) my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
{ DBUG_RETURN(-1);
my_error(EE_STAT, MYF(0), path, my_errno); }
goto exit;
}
if (my_mkdir(path,0777,MYF(0)) < 0) if (my_mkdir(path, 0777, MYF(0)) < 0)
{ {
my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno); my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
error= -1; DBUG_RETURN(-1);
goto exit;
}
} }
path[path_len-1]= FN_LIBCHAR; path[path_len-1]= FN_LIBCHAR;
...@@ -637,10 +651,7 @@ int mysql_create_db(THD *thd, char *db, ...@@ -637,10 +651,7 @@ int mysql_create_db(THD *thd, char *db,
*/ */
path[path_len]= 0; path[path_len]= 0;
if (rmdir(path) >= 0) if (rmdir(path) >= 0)
{ DBUG_RETURN(-1);
error= -1;
goto exit;
}
/* /*
We come here when we managed to create the database, but not the option 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 file. In this case it's best to just continue as if nothing has
...@@ -690,23 +701,20 @@ int mysql_create_db(THD *thd, char *db, ...@@ -690,23 +701,20 @@ int mysql_create_db(THD *thd, char *db,
metadata lock on the schema metadata lock on the schema
*/ */
if (mysql_bin_log.write(&qinfo)) if (mysql_bin_log.write(&qinfo))
{ DBUG_RETURN(-1);
error= -1;
goto exit;
}
} }
my_ok(thd, result); my_ok(thd, affected_rows);
} }
exit: DBUG_RETURN(0);
DBUG_RETURN(error);
} }
/* db-name is already validated when we come here */ /* db-name is already validated when we come here */
bool mysql_alter_db(THD *thd, const char *db, static bool
Schema_specification_st *create_info) mysql_alter_db_internal(THD *thd, const char *db,
Schema_specification_st *create_info)
{ {
char path[FN_REFLEN+16]; char path[FN_REFLEN+16];
long result=1; long result=1;
...@@ -762,6 +770,31 @@ bool mysql_alter_db(THD *thd, const char *db, ...@@ -762,6 +770,31 @@ bool mysql_alter_db(THD *thd, const char *db,
} }
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. Drop all tables, routines and events in a database and the database itself.
...@@ -777,7 +810,8 @@ bool mysql_alter_db(THD *thd, const char *db, ...@@ -777,7 +810,8 @@ bool mysql_alter_db(THD *thd, const char *db,
@retval true Error @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; ulong deleted_tables= 0;
bool error= true; bool error= true;
...@@ -1004,6 +1038,12 @@ bool mysql_rm_db(THD *thd,char *db, bool if_exists, bool silent) ...@@ -1004,6 +1038,12 @@ bool mysql_rm_db(THD *thd,char *db, bool if_exists, bool silent)
} }
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, static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp,
char *dbname, char *dbname,
const char *path, const char *path,
...@@ -1654,7 +1694,8 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) ...@@ -1654,7 +1694,8 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
} }
/* Step1: Create the new database */ /* 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; goto exit;
/* Step2: Move tables to the new database */ /* Step2: Move tables to the new database */
...@@ -1778,7 +1819,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) ...@@ -1778,7 +1819,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
to execute them again. to execute them again.
mysql_rm_db() also "unuses" if we drop the current database. 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 */ /* Step8: logging */
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
......
...@@ -22,10 +22,10 @@ class THD; ...@@ -22,10 +22,10 @@ class THD;
int mysql_create_db(THD *thd, char *db, int mysql_create_db(THD *thd, char *db,
const DDL_options_st &options, 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, bool mysql_alter_db(THD *thd, const char *db,
Schema_specification_st *create); const Schema_specification_st *create);
bool mysql_rm_db(THD *thd, char *db, bool if_exists, bool silent); bool mysql_rm_db(THD *thd, char *db, bool if_exists);
bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db); bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db);
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
bool force_switch); bool force_switch);
......
...@@ -4301,7 +4301,7 @@ mysql_execute_command(THD *thd) ...@@ -4301,7 +4301,7 @@ mysql_execute_command(THD *thd)
if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0)) if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0))
break; break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL) 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; break;
} }
case SQLCOM_DROP_DB: case SQLCOM_DROP_DB:
...@@ -4333,7 +4333,7 @@ mysql_execute_command(THD *thd) ...@@ -4333,7 +4333,7 @@ mysql_execute_command(THD *thd)
if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0)) if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0))
break; break;
WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL) 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; break;
} }
case SQLCOM_ALTER_DB_UPGRADE: case SQLCOM_ALTER_DB_UPGRADE:
......
...@@ -2538,7 +2538,7 @@ create: ...@@ -2538,7 +2538,7 @@ create:
MYSQL_YYABORT; MYSQL_YYABORT;
} }
opt_index_lock_algorithm { } 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.default_table_charset= NULL;
Lex->create_info.used_fields= 0; Lex->create_info.used_fields= 0;
...@@ -2546,7 +2546,8 @@ create: ...@@ -2546,7 +2546,8 @@ create:
opt_create_database_options opt_create_database_options
{ {
LEX *lex=Lex; 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; lex->name= $4;
} }
| create_or_replace | create_or_replace
......
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