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,
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
......
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