Commit 822eb6ca authored by Alexander Barkov's avatar Alexander Barkov

MDEV-7285 SERVER: CREATE OR REPLACE and CREATE IF NOT EXISTS

parent 14cfb0ac
...@@ -27,6 +27,24 @@ Log_name Pos Event_type Server_id End_log_pos Info ...@@ -27,6 +27,24 @@ Log_name Pos Event_type Server_id End_log_pos Info
# # Query 1 # DROP DATABASE IF EXISTS d1 # # Query 1 # DROP DATABASE IF EXISTS d1
RESET MASTER; RESET MASTER;
USE test; USE test;
#
# CREATE SERVER is not logged
#
CREATE OR REPLACE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', HOST 'localhost', DATABASE 'test');
CREATE OR REPLACE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', HOST 'localhost', DATABASE 'test');
DROP SERVER s1;
CREATE SERVER IF NOT EXISTS s1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', HOST 'localhost', DATABASE 'test');
CREATE SERVER IF NOT EXISTS s1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', HOST 'localhost', DATABASE 'test');
Warnings:
Note 1476 The foreign server, s1, you are trying to create already exists.
DROP SERVER IF EXISTS s1;
DROP SERVER IF EXISTS s1;
SHOW BINLOG EVENTS;
Log_name Pos Event_type Server_id End_log_pos Info
# # Format_desc 1 # VER
# # Gtid_list 1 # []
# # Binlog_checkpoint 1 # master-bin.000001
RESET MASTER;
CREATE OR REPLACE VIEW v1 AS SELECT 1; CREATE OR REPLACE VIEW v1 AS SELECT 1;
CREATE OR REPLACE VIEW v1 AS SELECT 1; CREATE OR REPLACE VIEW v1 AS SELECT 1;
DROP VIEW v1; DROP VIEW v1;
......
#
# MDEV-7285 SERVER: CREATE OR REPLACE and CREATE IF NOT EXISTS
#
CREATE SERVER IF NOT EXISTS server1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'user1', HOST 'localhost', DATABASE 'test0');
SELECT server_name, username, db FROM mysql.servers;
server_name username db
server1 user1 test0
CREATE SERVER IF NOT EXISTS server1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'user2', HOST 'localhost', DATABASE 'test1');
Warnings:
Note 1476 The foreign server, server1, you are trying to create already exists.
SELECT server_name, username, db FROM mysql.servers;
server_name username db
server1 user1 test0
CREATE OR REPLACE SERVER server1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'user3', HOST 'localhost', DATABASE 'test2');
SELECT server_name, username, db FROM mysql.servers;
server_name username db
server1 user3 test2
DROP SERVER IF EXISTS server1;
SELECT server_name, username, db FROM mysql.servers;
server_name username db
DROP SERVER IF EXISTS server1;
CREATE SERVER server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test0');
CREATE SERVER server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test1');
ERROR HY000: The foreign server, server_1, you are trying to create already exists.
CREATE SERVER IF NOT EXISTS server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test2');
Warnings:
Note 1476 The foreign server, server_1, you are trying to create already exists.
SELECT server_name, username, db FROM mysql.servers;
server_name username db
server_1 mysqltest_1 test0
CREATE OR REPLACE SERVER IF NOT EXISTS server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test3');
ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS
CREATE OR REPLACE SERVER server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test4');
SELECT server_name, username, db FROM mysql.servers;
server_name username db
server_1 mysqltest_1 test4
DROP SERVER server_1;
...@@ -19,6 +19,22 @@ DROP DATABASE IF EXISTS d1; ...@@ -19,6 +19,22 @@ DROP DATABASE IF EXISTS d1;
RESET MASTER; RESET MASTER;
USE test; USE test;
--echo #
--echo # CREATE SERVER is not logged
--echo #
CREATE OR REPLACE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', HOST 'localhost', DATABASE 'test');
CREATE OR REPLACE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', HOST 'localhost', DATABASE 'test');
DROP SERVER s1;
CREATE SERVER IF NOT EXISTS s1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', HOST 'localhost', DATABASE 'test');
CREATE SERVER IF NOT EXISTS s1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'root', HOST 'localhost', DATABASE 'test');
DROP SERVER IF EXISTS s1;
DROP SERVER IF EXISTS s1;
--replace_column 1 # 2 # 5 #
--replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VER/
SHOW BINLOG EVENTS;
RESET MASTER;
CREATE OR REPLACE VIEW v1 AS SELECT 1; CREATE OR REPLACE VIEW v1 AS SELECT 1;
CREATE OR REPLACE VIEW v1 AS SELECT 1; CREATE OR REPLACE VIEW v1 AS SELECT 1;
......
--echo #
--echo # MDEV-7285 SERVER: CREATE OR REPLACE and CREATE IF NOT EXISTS
--echo #
CREATE SERVER IF NOT EXISTS server1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'user1', HOST 'localhost', DATABASE 'test0');
SELECT server_name, username, db FROM mysql.servers;
CREATE SERVER IF NOT EXISTS server1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'user2', HOST 'localhost', DATABASE 'test1');
SELECT server_name, username, db FROM mysql.servers;
CREATE OR REPLACE SERVER server1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'user3', HOST 'localhost', DATABASE 'test2');
SELECT server_name, username, db FROM mysql.servers;
DROP SERVER IF EXISTS server1;
SELECT server_name, username, db FROM mysql.servers;
DROP SERVER IF EXISTS server1;
CREATE SERVER server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test0');
--error ER_FOREIGN_SERVER_EXISTS
CREATE SERVER server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test1');
CREATE SERVER IF NOT EXISTS server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test2');
SELECT server_name, username, db FROM mysql.servers;
--error ER_WRONG_USAGE
CREATE OR REPLACE SERVER IF NOT EXISTS server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test3');
CREATE OR REPLACE SERVER server_1 FOREIGN DATA WRAPPER mysql OPTIONS (USER 'mysqltest_1', HOST 'localhost', DATABASE 'test4');
SELECT server_name, username, db FROM mysql.servers;
DROP SERVER server_1;
...@@ -5446,21 +5446,13 @@ create_sp_error: ...@@ -5446,21 +5446,13 @@ create_sp_error:
} }
case SQLCOM_CREATE_SERVER: case SQLCOM_CREATE_SERVER:
{ {
int error;
LEX *lex= thd->lex; LEX *lex= thd->lex;
DBUG_PRINT("info", ("case SQLCOM_CREATE_SERVER")); DBUG_PRINT("info", ("case SQLCOM_CREATE_SERVER"));
if (check_global_access(thd, SUPER_ACL)) if (check_global_access(thd, SUPER_ACL))
break; break;
if ((error= create_server(thd, &lex->server_options))) res= create_server(thd, &lex->server_options);
{
DBUG_PRINT("info", ("problem creating server <%s>",
lex->server_options.server_name.str));
my_error(error, MYF(0), lex->server_options.server_name.str);
break;
}
my_ok(thd, 1);
break; break;
} }
case SQLCOM_ALTER_SERVER: case SQLCOM_ALTER_SERVER:
......
...@@ -582,8 +582,8 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server) ...@@ -582,8 +582,8 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
This function takes as its arguments a THD object pointer and a pointer This function takes as its arguments a THD object pointer and a pointer
to a LEX_SERVER_OPTIONS struct from the parser. The member 'server_name' to a LEX_SERVER_OPTIONS struct from the parser. The member 'server_name'
of this LEX_SERVER_OPTIONS struct contains the value of the server to be of this LEX_SERVER_OPTIONS struct contains the value of the server to be
deleted. The mysql.servers table is opened via open_ltable, a table object deleted. The mysql.servers table is opened via open_ltable,
returned, the servers cache mutex locked, then delete_server_record is a table object returned, then delete_server_record is
called with this table object and LEX_SERVER_OPTIONS server_name and called with this table object and LEX_SERVER_OPTIONS server_name and
server_name_length passed, containing the name of the server to be server_name_length passed, containing the name of the server to be
dropped/deleted, then delete_server_record_in_cache is called to delete dropped/deleted, then delete_server_record_in_cache is called to delete
...@@ -594,20 +594,18 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server) ...@@ -594,20 +594,18 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
> 0 - error code > 0 - error code
*/ */
int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options) static int drop_server_internal(THD *thd, LEX_SERVER_OPTIONS *server_options)
{ {
int error; int error;
TABLE_LIST tables; TABLE_LIST tables;
TABLE *table; TABLE *table;
DBUG_ENTER("drop_server"); DBUG_ENTER("drop_server_internal");
DBUG_PRINT("info", ("server name server->server_name %s", DBUG_PRINT("info", ("server name server->server_name %s",
server_options->server_name.str)); server_options->server_name.str));
tables.init_one_table("mysql", 5, "servers", 7, "servers", TL_WRITE); tables.init_one_table("mysql", 5, "servers", 7, "servers", TL_WRITE);
mysql_rwlock_wrlock(&THR_LOCK_servers);
/* hit the memory hit first */ /* hit the memory hit first */
if ((error= delete_server_record_in_cache(server_options))) if ((error= delete_server_record_in_cache(server_options)))
goto end; goto end;
...@@ -630,11 +628,22 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options) ...@@ -630,11 +628,22 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
} }
end: end:
mysql_rwlock_unlock(&THR_LOCK_servers);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/**
Drop a server with servers cache mutex lock.
*/
int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
{
mysql_rwlock_wrlock(&THR_LOCK_servers);
int rc= drop_server_internal(thd, server_options);
mysql_rwlock_unlock(&THR_LOCK_servers);
return rc;
}
/* /*
SYNOPSIS SYNOPSIS
...@@ -989,8 +998,24 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options) ...@@ -989,8 +998,24 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
/* hit the memory first */ /* hit the memory first */
if (my_hash_search(&servers_cache, (uchar*) server_options->server_name.str, if (my_hash_search(&servers_cache, (uchar*) server_options->server_name.str,
server_options->server_name.length)) server_options->server_name.length))
{
if (thd->lex->create_info.or_replace())
{
if ((error= drop_server_internal(thd, server_options)))
goto end; goto end;
}
else if (thd->lex->create_info.if_not_exists())
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_FOREIGN_SERVER_EXISTS,
ER(ER_FOREIGN_SERVER_EXISTS),
server_options->server_name.str);
error= 0;
goto end;
}
else
goto end;
}
if (!(server= prepare_server_struct_for_insert(server_options))) if (!(server= prepare_server_struct_for_insert(server_options)))
{ {
...@@ -1006,6 +1031,16 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options) ...@@ -1006,6 +1031,16 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
end: end:
mysql_rwlock_unlock(&THR_LOCK_servers); mysql_rwlock_unlock(&THR_LOCK_servers);
if (error)
{
DBUG_PRINT("info", ("problem creating server <%s>",
server_options->server_name.str));
my_error(error, MYF(0), server_options->server_name.str);
}
else
my_ok(thd);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
......
...@@ -2584,18 +2584,21 @@ create: ...@@ -2584,18 +2584,21 @@ create:
{ {
Lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE; Lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE;
} }
| CREATE server_def | create_or_replace { Lex->set_command(SQLCOM_CREATE_SERVER, $1); }
{ server_def
Lex->sql_command= SQLCOM_CREATE_SERVER; { }
}
; ;
server_def: server_def:
SERVER_SYM ident_or_text SERVER_SYM opt_if_not_exists ident_or_text
{ Lex->server_options.reset($2); } {
if (Lex->add_create_options_with_check($2))
MYSQL_YYABORT;
Lex->server_options.reset($3);
}
FOREIGN DATA_SYM WRAPPER_SYM ident_or_text FOREIGN DATA_SYM WRAPPER_SYM ident_or_text
OPTIONS_SYM '(' server_options_list ')' OPTIONS_SYM '(' server_options_list ')'
{ Lex->server_options.scheme= $7; } { Lex->server_options.scheme= $8; }
; ;
server_options_list: server_options_list:
......
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