mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-34716 Allow arbitrary options in CREATE SERVER
The existing syntax for CREATE SERVER CREATE [OR REPLACE] SERVER [IF NOT EXISTS] server_name FOREIGN DATA WRAPPER wrapper_name OPTIONS (option [, option] ...) option: { HOST character-literal | DATABASE character-literal | USER character-literal | PASSWORD character-literal | SOCKET character-literal | OWNER character-literal | PORT numeric-literal } With this change we have: option: { HOST character-literal | DATABASE character-literal | USER character-literal | PASSWORD character-literal | SOCKET character-literal | OWNER character-literal | PORT numeric-literal | PORT quoted-numerical-literal | identifier character-literal} We store these options as a JSON field in the mysql.servers system table. We retain the restriction that PORT needs to be a number, but also allow it to be a quoted number, so that SHOW CREATE SERVER can be used for dumping. Without an accompanied implementation of SHOW CREATE SERVER, some mysqldump tests will fail. Therefore this commit should be immediately followed by the one implementating SHOW CREATE SERVER, with testing covering both.
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
#include "sp.h"
|
||||
#include "transaction.h"
|
||||
#include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT
|
||||
#include "create_options.h"
|
||||
|
||||
/*
|
||||
We only use 1 mutex to guard the data structures - THR_LOCK_servers.
|
||||
@@ -434,6 +435,42 @@ get_server_from_table_to_cache(TABLE *table)
|
||||
server->scheme= ptr ? ptr : blank;
|
||||
ptr= get_field(&mem, table->field[8]);
|
||||
server->owner= ptr ? ptr : blank;
|
||||
ptr= get_field(&mem, table->field[9]);
|
||||
enum json_types vt;
|
||||
const char *keyname, *keyname_end, *v;
|
||||
int v_len, nkey= 0;
|
||||
engine_option_value *option_list_last;
|
||||
server->option_list= NULL;
|
||||
while ((vt= json_get_object_nkey(ptr, ptr+strlen(ptr), nkey++,
|
||||
&keyname, &keyname_end, &v, &v_len)) != JSV_NOTHING)
|
||||
{
|
||||
if (vt != JSV_STRING)
|
||||
DBUG_RETURN(TRUE);
|
||||
/*
|
||||
We have to make copies here to create "clean" strings and
|
||||
avoid mutating ptr.
|
||||
*/
|
||||
Lex_cstring name= {keyname, keyname_end}, value= {v, v + v_len},
|
||||
name_copy= safe_lexcstrdup_root(&mem, name),
|
||||
value_copy= safe_lexcstrdup_root(&mem, value);
|
||||
engine_option_value *option= new (&mem) engine_option_value(
|
||||
engine_option_value::Name(name_copy),
|
||||
engine_option_value::Value(value_copy), true);
|
||||
option->link(&server->option_list, &option_list_last);
|
||||
if (option->value.length)
|
||||
{
|
||||
LEX_CSTRING *optval= &option->value;
|
||||
char *unescaped= (char *) alloca(optval->length);
|
||||
int len= json_unescape_json(optval->str, optval->str + optval->length,
|
||||
unescaped, unescaped + optval->length);
|
||||
if (len < 0)
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_ASSERT(len <= (int) optval->length);
|
||||
if (len < (int) optval->length)
|
||||
strncpy((char *) optval->str, unescaped, len);
|
||||
optval->length= len;
|
||||
}
|
||||
}
|
||||
DBUG_PRINT("info", ("server->server_name %s", server->server_name));
|
||||
DBUG_PRINT("info", ("server->host %s", server->host));
|
||||
DBUG_PRINT("info", ("server->db %s", server->db));
|
||||
@@ -591,6 +628,30 @@ store_server_fields(TABLE *table, FOREIGN_SERVER *server)
|
||||
if (server->owner)
|
||||
table->field[8]->store(server->owner,
|
||||
(uint) strlen(server->owner), system_charset_info);
|
||||
engine_option_value *option= server->option_list;
|
||||
StringBuffer<1024> json(table->field[9]->charset());
|
||||
json.append('{');
|
||||
while (option)
|
||||
{
|
||||
if (option->value.str)
|
||||
{
|
||||
json.append('"');
|
||||
json.append(option->name.str, option->name.length);
|
||||
json.append('"');
|
||||
json.append({STRING_WITH_LEN(": \"")});
|
||||
int len= json_escape_string(
|
||||
option->value.str, option->value.str + option->value.length,
|
||||
json.c_ptr() + json.length(), json.c_ptr() + json.alloced_length());
|
||||
json.length(json.length() + len);
|
||||
json.append('"');
|
||||
json.append({STRING_WITH_LEN(", ")});
|
||||
}
|
||||
option= option->next;
|
||||
}
|
||||
if (server->option_list)
|
||||
json.length(json.length() - 2);
|
||||
json.append('}');
|
||||
table->field[9]->store(json.ptr(), json.length(), system_charset_info);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1185,6 +1246,23 @@ end:
|
||||
}
|
||||
|
||||
|
||||
static void copy_option_list(MEM_ROOT *mem, FOREIGN_SERVER *server,
|
||||
engine_option_value *option_list)
|
||||
{
|
||||
engine_option_value *option_list_last;
|
||||
server->option_list= NULL;
|
||||
for (engine_option_value *option= option_list; option;
|
||||
option= option->next)
|
||||
{
|
||||
engine_option_value *new_option= new (mem) engine_option_value(option);
|
||||
new_option->name= engine_option_value::Name(
|
||||
safe_lexcstrdup_root(mem, option->name));
|
||||
new_option->value= engine_option_value::Value(
|
||||
safe_lexcstrdup_root(mem, option->value));
|
||||
new_option->link(&server->option_list, &option_list_last);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
SYNOPSIS
|
||||
@@ -1240,6 +1318,7 @@ prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options)
|
||||
SET_SERVER_OR_RETURN(password, "");
|
||||
SET_SERVER_OR_RETURN(socket, "");
|
||||
SET_SERVER_OR_RETURN(owner, "");
|
||||
copy_option_list(&mem, server, server_options->option_list);
|
||||
|
||||
server->server_name_length= server_options->server_name.length;
|
||||
|
||||
@@ -1294,6 +1373,8 @@ prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
|
||||
SET_ALTERED(socket);
|
||||
SET_ALTERED(scheme);
|
||||
SET_ALTERED(owner);
|
||||
merge_engine_options(existing->option_list, server_options->option_list,
|
||||
&altered->option_list, &mem);
|
||||
|
||||
/*
|
||||
port is initialised to -1, so if unset, it will be -1
|
||||
@@ -1355,7 +1436,7 @@ void servers_free(bool end)
|
||||
FOREIGN_SEVER pointer (copy of one supplied FOREIGN_SERVER)
|
||||
*/
|
||||
|
||||
static FOREIGN_SERVER *clone_server(MEM_ROOT *mem, const FOREIGN_SERVER *server,
|
||||
static FOREIGN_SERVER *clone_server(MEM_ROOT *mem, FOREIGN_SERVER *server,
|
||||
FOREIGN_SERVER *buffer)
|
||||
{
|
||||
DBUG_ENTER("sql_server.cc:clone_server");
|
||||
@@ -1376,6 +1457,7 @@ static FOREIGN_SERVER *clone_server(MEM_ROOT *mem, const FOREIGN_SERVER *server,
|
||||
buffer->socket= safe_strdup_root(mem, server->socket);
|
||||
buffer->owner= safe_strdup_root(mem, server->owner);
|
||||
buffer->host= safe_strdup_root(mem, server->host);
|
||||
copy_option_list(mem, buffer, server->option_list);
|
||||
|
||||
DBUG_RETURN(buffer);
|
||||
}
|
||||
|
Reference in New Issue
Block a user