mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-7280 DATABASE: CREATE OR REPLACE
This commit is contained in:
29
mysql-test/r/create_drop_binlog.result
Normal file
29
mysql-test/r/create_drop_binlog.result
Normal file
@ -0,0 +1,29 @@
|
||||
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;
|
40
mysql-test/r/create_drop_db.result
Normal file
40
mysql-test/r/create_drop_db.result
Normal file
@ -0,0 +1,40 @@
|
||||
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
|
43
mysql-test/suite/rpl/r/rpl_create_drop_db.result
Normal file
43
mysql-test/suite/rpl/r/rpl_create_drop_db.result
Normal file
@ -0,0 +1,43 @@
|
||||
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
|
33
mysql-test/suite/rpl/t/rpl_create_drop_db.test
Normal file
33
mysql-test/suite/rpl/t/rpl_create_drop_db.test
Normal file
@ -0,0 +1,33 @@
|
||||
--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
|
20
mysql-test/t/create_drop_binlog.test
Normal file
20
mysql-test/t/create_drop_binlog.test
Normal file
@ -0,0 +1,20 @@
|
||||
--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;
|
32
mysql-test/t/create_drop_db.test
Normal file
32
mysql-test/t/create_drop_db.test
Normal file
@ -0,0 +1,32 @@
|
||||
# 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
|
123
sql/sql_db.cc
123
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())
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user