summaryrefslogtreecommitdiff
path: root/sql/sql_servers.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_servers.cc')
-rw-r--r--sql/sql_servers.cc256
1 files changed, 130 insertions, 126 deletions
diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc
index dad7ab152ed..0138c3e5a3b 100644
--- a/sql/sql_servers.cc
+++ b/sql/sql_servers.cc
@@ -33,12 +33,12 @@
currently running transactions etc will not be disrupted.
*/
+#include <my_global.h>
#include "sql_priv.h"
#include "sql_servers.h"
#include "unireg.h"
#include "sql_base.h" // close_mysql_tables
#include "records.h" // init_read_record, end_read_record
-#include "hash_filo.h"
#include <m_ctype.h>
#include <stdarg.h>
#include "sp_head.h"
@@ -64,9 +64,7 @@ static int insert_server_record_into_cache(FOREIGN_SERVER *server);
static FOREIGN_SERVER *
prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options);
/* drop functions */
-static int delete_server_record(TABLE *table,
- char *server_name,
- size_t server_name_length);
+static int delete_server_record(TABLE *table, LEX_STRING *name);
static int delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options);
/* update functions */
@@ -81,8 +79,6 @@ static int update_server_record_in_cache(FOREIGN_SERVER *existing,
/* utility functions */
static void merge_server_struct(FOREIGN_SERVER *from, FOREIGN_SERVER *to);
-
-
static uchar *servers_cache_get_key(FOREIGN_SERVER *server, size_t *length,
my_bool not_used __attribute__((unused)))
{
@@ -158,7 +154,7 @@ bool servers_init(bool dont_read_servers_table)
}
/* Initialize the mem root for data */
- init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
+ init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC));
if (dont_read_servers_table)
goto end;
@@ -177,8 +173,6 @@ bool servers_init(bool dont_read_servers_table)
*/
return_val= servers_reload(thd);
delete thd;
- /* Remember that we don't have a THD */
- my_pthread_setspecific_ptr(THR_THD, 0);
end:
DBUG_RETURN(return_val);
@@ -209,7 +203,7 @@ static bool servers_load(THD *thd, TABLE_LIST *tables)
my_hash_reset(&servers_cache);
free_root(&mem, MYF(0));
- init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
+ init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
if (init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0,
FALSE))
@@ -265,9 +259,9 @@ bool servers_reload(THD *thd)
Execution might have been interrupted; only print the error message
if an error condition has been raised.
*/
- if (thd->stmt_da->is_error())
+ if (thd->get_stmt_da()->is_error())
sql_print_error("Can't open and lock privilege tables: %s",
- thd->stmt_da->message());
+ thd->get_stmt_da()->message());
return_val= FALSE;
goto end;
}
@@ -587,8 +581,8 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
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'
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
- returned, the servers cache mutex locked, then delete_server_record is
+ deleted. The mysql.servers table is opened via open_ltable,
+ a table object returned, then delete_server_record is
called with this table object and LEX_SERVER_OPTIONS server_name and
server_name_length passed, containing the name of the server to be
dropped/deleted, then delete_server_record_in_cache is called to delete
@@ -599,22 +593,18 @@ int insert_server_record(TABLE *table, FOREIGN_SERVER *server)
> 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;
TABLE_LIST tables;
TABLE *table;
- LEX_STRING name= { server_options->server_name,
- server_options->server_name_length };
- DBUG_ENTER("drop_server");
+ DBUG_ENTER("drop_server_internal");
DBUG_PRINT("info", ("server name server->server_name %s",
- server_options->server_name));
+ server_options->server_name.str));
tables.init_one_table("mysql", 5, "servers", 7, "servers", TL_WRITE);
- mysql_rwlock_wrlock(&THR_LOCK_servers);
-
/* hit the memory hit first */
if ((error= delete_server_record_in_cache(server_options)))
goto end;
@@ -625,23 +615,34 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
goto end;
}
- error= delete_server_record(table, name.str, name.length);
+ error= delete_server_record(table, &server_options->server_name);
/* close the servers table before we call closed_cached_connection_tables */
close_mysql_tables(thd);
- if (close_cached_connection_tables(thd, &name))
+ if (close_cached_connection_tables(thd, &server_options->server_name))
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_ERROR, "Server connection in use");
}
end:
- mysql_rwlock_unlock(&THR_LOCK_servers);
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
@@ -667,19 +668,19 @@ delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options)
FOREIGN_SERVER *server;
DBUG_ENTER("delete_server_record_in_cache");
- DBUG_PRINT("info",("trying to obtain server name %s length %d",
- server_options->server_name,
- server_options->server_name_length));
+ DBUG_PRINT("info",("trying to obtain server name %s length %zu",
+ server_options->server_name.str,
+ server_options->server_name.length));
if (!(server= (FOREIGN_SERVER *)
my_hash_search(&servers_cache,
- (uchar*) server_options->server_name,
- server_options->server_name_length)))
+ (uchar*) server_options->server_name.str,
+ server_options->server_name.length)))
{
- DBUG_PRINT("info", ("server_name %s length %d not found!",
- server_options->server_name,
- server_options->server_name_length));
+ DBUG_PRINT("info", ("server_name %s length %zu not found!",
+ server_options->server_name.str,
+ server_options->server_name.length));
goto end;
}
/*
@@ -938,8 +939,7 @@ end:
*/
static int
-delete_server_record(TABLE *table,
- char *server_name, size_t server_name_length)
+delete_server_record(TABLE *table, LEX_STRING *name)
{
int error;
DBUG_ENTER("delete_server_record");
@@ -947,7 +947,7 @@ delete_server_record(TABLE *table,
table->use_all_columns();
/* set the field that's the PK to the value we're looking for */
- table->field[0]->store(server_name, server_name_length, system_charset_info);
+ table->field[0]->store(name->str, name->length, system_charset_info);
if ((error= table->file->ha_index_read_idx_map(table->record[0], 0,
(uchar *)table->field[0]->ptr,
@@ -990,15 +990,31 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
DBUG_ENTER("create_server");
DBUG_PRINT("info", ("server_options->server_name %s",
- server_options->server_name));
+ server_options->server_name.str));
mysql_rwlock_wrlock(&THR_LOCK_servers);
/* hit the memory first */
- if (my_hash_search(&servers_cache, (uchar*) server_options->server_name,
- server_options->server_name_length))
- goto end;
-
+ if (my_hash_search(&servers_cache, (uchar*) server_options->server_name.str,
+ server_options->server_name.length))
+ {
+ if (thd->lex->create_info.or_replace())
+ {
+ if ((error= drop_server_internal(thd, server_options)))
+ 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_THD(thd, 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)))
{
@@ -1014,6 +1030,16 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
end:
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);
}
@@ -1035,33 +1061,28 @@ end:
int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options)
{
int error= ER_FOREIGN_SERVER_DOESNT_EXIST;
- FOREIGN_SERVER *altered, *existing;
- LEX_STRING name= { server_options->server_name,
- server_options->server_name_length };
+ FOREIGN_SERVER altered, *existing;
DBUG_ENTER("alter_server");
DBUG_PRINT("info", ("server_options->server_name %s",
- server_options->server_name));
+ server_options->server_name.str));
mysql_rwlock_wrlock(&THR_LOCK_servers);
if (!(existing= (FOREIGN_SERVER *) my_hash_search(&servers_cache,
- (uchar*) name.str,
- name.length)))
+ (uchar*) server_options->server_name.str,
+ server_options->server_name.length)))
goto end;
- altered= (FOREIGN_SERVER *)alloc_root(&mem,
- sizeof(FOREIGN_SERVER));
+ prepare_server_struct_for_update(server_options, existing, &altered);
- prepare_server_struct_for_update(server_options, existing, altered);
-
- error= update_server(thd, existing, altered);
+ error= update_server(thd, existing, &altered);
/* close the servers table before we call closed_cached_connection_tables */
close_mysql_tables(thd);
- if (close_cached_connection_tables(thd, &name))
+ if (close_cached_connection_tables(thd, &server_options->server_name))
{
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_ERROR, "Server connection in use");
}
@@ -1090,49 +1111,49 @@ end:
static FOREIGN_SERVER *
prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options)
{
- char *unset_ptr= (char*)"";
FOREIGN_SERVER *server;
+ ulong default_port= 0;
DBUG_ENTER("prepare_server_struct");
if (!(server= (FOREIGN_SERVER *)alloc_root(&mem, sizeof(FOREIGN_SERVER))))
DBUG_RETURN(NULL); /* purecov: inspected */
- /* these two MUST be set */
- if (!(server->server_name= strdup_root(&mem, server_options->server_name)))
- DBUG_RETURN(NULL); /* purecov: inspected */
- server->server_name_length= server_options->server_name_length;
+#define SET_SERVER_OR_RETURN(X, DEFAULT) \
+ do { \
+ if (!(server->X= server_options->X.str ? \
+ strmake_root(&mem, server_options->X.str, \
+ server_options->X.length) : "")) \
+ DBUG_RETURN(NULL); \
+ } while(0)
- if (!(server->host= server_options->host ?
- strdup_root(&mem, server_options->host) : unset_ptr))
- DBUG_RETURN(NULL); /* purecov: inspected */
+ /* name and scheme are always set (the parser guarantees it) */
+ SET_SERVER_OR_RETURN(server_name, NULL);
+ SET_SERVER_OR_RETURN(scheme, NULL);
- if (!(server->db= server_options->db ?
- strdup_root(&mem, server_options->db) : unset_ptr))
- DBUG_RETURN(NULL); /* purecov: inspected */
+ /* scheme-specific checks */
+ if (!strcasecmp(server->scheme, "mysql"))
+ {
+ default_port= MYSQL_PORT;
+ if (!server_options->host.str && !server_options->socket.str)
+ {
+ my_error(ER_CANT_CREATE_FEDERATED_TABLE, MYF(0),
+ "either HOST or SOCKET must be set");
+ DBUG_RETURN(NULL);
+ }
+ }
- if (!(server->username= server_options->username ?
- strdup_root(&mem, server_options->username) : unset_ptr))
- DBUG_RETURN(NULL); /* purecov: inspected */
+ SET_SERVER_OR_RETURN(host, "");
+ SET_SERVER_OR_RETURN(db, "");
+ SET_SERVER_OR_RETURN(username, "");
+ SET_SERVER_OR_RETURN(password, "");
+ SET_SERVER_OR_RETURN(socket, "");
+ SET_SERVER_OR_RETURN(owner, "");
- if (!(server->password= server_options->password ?
- strdup_root(&mem, server_options->password) : unset_ptr))
- DBUG_RETURN(NULL); /* purecov: inspected */
+ server->server_name_length= server_options->server_name.length;
- /* set to 0 if not specified */
+ /* set to default_port if not specified */
server->port= server_options->port > -1 ?
- server_options->port : 0;
-
- if (!(server->socket= server_options->socket ?
- strdup_root(&mem, server_options->socket) : unset_ptr))
- DBUG_RETURN(NULL); /* purecov: inspected */
-
- if (!(server->scheme= server_options->scheme ?
- strdup_root(&mem, server_options->scheme) : unset_ptr))
- DBUG_RETURN(NULL); /* purecov: inspected */
-
- if (!(server->owner= server_options->owner ?
- strdup_root(&mem, server_options->owner) : unset_ptr))
- DBUG_RETURN(NULL); /* purecov: inspected */
+ server_options->port : default_port;
DBUG_RETURN(server);
}
@@ -1157,8 +1178,8 @@ prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
{
DBUG_ENTER("prepare_server_struct_for_update");
- altered->server_name= strdup_root(&mem, server_options->server_name);
- altered->server_name_length= server_options->server_name_length;
+ altered->server_name= existing->server_name;
+ altered->server_name_length= existing->server_name_length;
DBUG_PRINT("info", ("existing name %s altered name %s",
existing->server_name, altered->server_name));
@@ -1166,23 +1187,21 @@ prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
The logic here is this: is this value set AND is it different
than the existing value?
*/
- altered->host=
- (server_options->host && (strcmp(server_options->host, existing->host))) ?
- strdup_root(&mem, server_options->host) : 0;
-
- altered->db=
- (server_options->db && (strcmp(server_options->db, existing->db))) ?
- strdup_root(&mem, server_options->db) : 0;
-
- altered->username=
- (server_options->username &&
- (strcmp(server_options->username, existing->username))) ?
- strdup_root(&mem, server_options->username) : 0;
-
- altered->password=
- (server_options->password &&
- (strcmp(server_options->password, existing->password))) ?
- strdup_root(&mem, server_options->password) : 0;
+#define SET_ALTERED(X) \
+ do { \
+ altered->X= \
+ (server_options->X.str && strcmp(server_options->X.str, existing->X)) \
+ ? strmake_root(&mem, server_options->X.str, server_options->X.length) \
+ : 0; \
+ } while(0)
+
+ SET_ALTERED(host);
+ SET_ALTERED(db);
+ SET_ALTERED(username);
+ SET_ALTERED(password);
+ SET_ALTERED(socket);
+ SET_ALTERED(scheme);
+ SET_ALTERED(owner);
/*
port is initialised to -1, so if unset, it will be -1
@@ -1191,21 +1210,6 @@ prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
server_options->port != existing->port) ?
server_options->port : -1;
- altered->socket=
- (server_options->socket &&
- (strcmp(server_options->socket, existing->socket))) ?
- strdup_root(&mem, server_options->socket) : 0;
-
- altered->scheme=
- (server_options->scheme &&
- (strcmp(server_options->scheme, existing->scheme))) ?
- strdup_root(&mem, server_options->scheme) : 0;
-
- altered->owner=
- (server_options->owner &&
- (strcmp(server_options->owner, existing->owner))) ?
- strdup_root(&mem, server_options->owner) : 0;
-
DBUG_VOID_RETURN;
}
@@ -1273,13 +1277,13 @@ static FOREIGN_SERVER *clone_server(MEM_ROOT *mem, const FOREIGN_SERVER *server,
buffer->server_name_length= server->server_name_length;
/* TODO: We need to examine which of these can really be NULL */
- buffer->db= server->db ? strdup_root(mem, server->db) : NULL;
- buffer->scheme= server->scheme ? strdup_root(mem, server->scheme) : NULL;
- buffer->username= server->username? strdup_root(mem, server->username): NULL;
- buffer->password= server->password? strdup_root(mem, server->password): NULL;
- buffer->socket= server->socket ? strdup_root(mem, server->socket) : NULL;
- buffer->owner= server->owner ? strdup_root(mem, server->owner) : NULL;
- buffer->host= server->host ? strdup_root(mem, server->host) : NULL;
+ buffer->db= safe_strdup_root(mem, server->db);
+ buffer->scheme= safe_strdup_root(mem, server->scheme);
+ buffer->username= safe_strdup_root(mem, server->username);
+ buffer->password= safe_strdup_root(mem, server->password);
+ buffer->socket= safe_strdup_root(mem, server->socket);
+ buffer->owner= safe_strdup_root(mem, server->owner);
+ buffer->host= safe_strdup_root(mem, server->host);
DBUG_RETURN(buffer);
}