WL# 3031
Backport of functionality in private 5.2 tree. Added new language to parser, new mysql.servers table and associated code to be used by the federated storage engine to allow central connection information per WL entry. libmysqld/Makefile.am: WL# 3031 Added sql_servers.cc to libmysqld Makefile.am mysql-test/lib/init_db.sql: WL# 3031 Added mysql.servers creation to init_db.sql, which is in turn called by mysql-test-run.pl scripts/mysql_create_system_tables.sh: WL# 3031 Added mysql.servers table creation to script called by non-perl mysql-test-run sql/Makefile.am: WL# 3031 Added sql_servers source and headers to Makefile.am to be built sql/lex.h: WL# 3031 Added tokens needed for SERVERS scheme sql/mysql_priv.h: WL #3031 Added sql_servers.h to mysql_priv.h so mysqld.cc and other code can link with sql_servers code sql/mysqld.cc: WL# 3031 Added servers_free and servers_init to mysqld sql/sql_lex.cc: WL# 3031 Added lex->server_options parameter initialisation sql/sql_lex.h: WL #3031 Added SQLCOM commands needed for sql_server actions sql/sql_parse.cc: WL# 3031 Added switch actions for new SQLCOM sql_server actions sql/sql_yacc.yy: WL #3031 Added tokens needed for sql_servers, CREATE/DROP/ALTER server functionality sql/share/errmsg.txt: WL# 3031 Added two new errors to errormsg.sys storage/federated/ha_federated.cc: WL #3031 Modified federated storage engine to use new connection scheme (servers table) if connection string only specifies connection name vs. complete URL storage/federated/ha_federated.h: WL# 3031 Added new share members needed for connection scheme sql/sql_servers.cc: WL #3031 sql_servers.cc - all methods required for manipulating mysql.servers table to work with federated new connection scheme (CREATE/ALTER/DROP SERVER ...) sql/sql_servers.h: WL #3031 New header file for sql_servers functionality mysql-test/r/federated_server.result: WL #3031 New test results for testing new connection scheme sql/sql_yacc.yy.bak: WL #3031 Added tokens and definitions required for new CREATE/ALTER/DROP SERVER for sql_servers functionality. See WL for details. mysql-test/t/federated_server.test: WL #3031 New test for testing CREATE/ALTER/DROP SERVER, as well as testing that federated works with both tradition connection scheme as well as new connection scheme.
This commit is contained in:
parent
46fd7deccb
commit
4e72191ce9
@ -72,7 +72,8 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
|
||||
event_queue.cc event_db_repository.cc \
|
||||
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
|
||||
sql_tablespace.cc \
|
||||
rpl_injector.cc my_user.c partition_info.cc
|
||||
rpl_injector.cc my_user.c partition_info.cc \
|
||||
sql_servers.cc
|
||||
|
||||
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
|
||||
libmysqld_a_SOURCES=
|
||||
|
@ -114,6 +114,20 @@ REPLACE INTO user VALUES ('127.0.0.1' ,'root','','Y','Y','Y','Y','Y','Y','Y','Y
|
||||
INSERT INTO user (host,user) VALUES ('localhost','');
|
||||
INSERT INTO user (host,user) VALUES ('@HOSTNAME@%','');
|
||||
|
||||
CREATE TABLE servers (
|
||||
Server_name char(64) NOT NULL DEFAULT '',
|
||||
Host char(64) NOT NULL DEFAULT '',
|
||||
Db char(64) NOT NULL DEFAULT '',
|
||||
Username char(64) NOT NULL DEFAULT '',
|
||||
Password char(64) NOT NULL DEFAULT '',
|
||||
Port INT(4) NOT NULL DEFAULT '0',
|
||||
Socket char(64) NOT NULL DEFAULT '',
|
||||
Wrapper char(64) NOT NULL DEFAULT '',
|
||||
Owner char(64) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (Server_name))
|
||||
comment='MySQL Foreign Servers table';
|
||||
|
||||
INSERT INTO servers VALUES ('test','localhost','test','root','', 0,'','mysql','root');
|
||||
|
||||
CREATE TABLE func (
|
||||
name char(64) binary DEFAULT '' NOT NULL,
|
||||
|
112
mysql-test/r/federated_server.result
Normal file
112
mysql-test/r/federated_server.result
Normal file
@ -0,0 +1,112 @@
|
||||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
stop slave;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
CREATE DATABASE federated;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
CREATE DATABASE federated;
|
||||
create database first_db;
|
||||
create database second_db;
|
||||
use first_db;
|
||||
DROP TABLE IF EXISTS first_db.t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE first_db.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
DEFAULT CHARSET=latin1;
|
||||
use second_db;
|
||||
DROP TABLE IF EXISTS second_db.t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE second_db.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
DEFAULT CHARSET=latin1;
|
||||
drop server if exists 'server_one';
|
||||
create server 'server_one' foreign data wrapper 'mysql' options
|
||||
(HOST '127.0.0.1',
|
||||
DATABASE 'first_db',
|
||||
USER 'root',
|
||||
PASSWORD '',
|
||||
PORT 9308,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
drop server if exists 'server_two';
|
||||
create server 'server_two' foreign data wrapper 'mysql' options
|
||||
(HOST '127.0.0.1',
|
||||
DATABASE 'second_db',
|
||||
USER 'root',
|
||||
PASSWORD '',
|
||||
PORT 9308,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
select * from mysql.servers;
|
||||
Server_name Host Db Username Password Port Socket Wrapper Owner
|
||||
test localhost test root 0 mysql root
|
||||
server_one 127.0.0.1 first_db root 9308 mysql root
|
||||
server_two 127.0.0.1 second_db root 9308 mysql root
|
||||
DROP TABLE IF EXISTS federated.old;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 'old'
|
||||
CREATE TABLE federated.old (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:9308/first_db/t1';
|
||||
INSERT INTO federated.old (id, name) values (1, 'federated.old url');
|
||||
SELECT * FROM federated.old;
|
||||
id name
|
||||
1 federated.old url
|
||||
DROP TABLE IF EXISTS federated.old2;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 'old2'
|
||||
CREATE TABLE federated.old2 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:9308/second_db/t1';
|
||||
INSERT INTO federated.old2 (id, name) values (1, 'federated.old2 url');
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='server_one';
|
||||
INSERT INTO federated.t1 (id, name) values (1, 'server_one, new scheme');
|
||||
SELECT * FROM federated.t1;
|
||||
id name
|
||||
1 federated.old url
|
||||
1 server_one, new scheme
|
||||
ALTER SERVER 'server_one' options(DATABASE 'second_db');
|
||||
flush tables;
|
||||
INSERT INTO federated.t1 (id, name) values (1, 'server_two, new scheme');
|
||||
SELECT * FROM federated.t1;
|
||||
id name
|
||||
1 federated.old2 url
|
||||
1 server_two, new scheme
|
||||
drop table federated.t1;
|
||||
drop server 'server_one';
|
||||
drop server 'server_two';
|
||||
select * from mysql.servers;
|
||||
Server_name Host Db Username Password Port Socket Wrapper Owner
|
||||
test localhost test root 0 mysql root
|
||||
drop table first_db.t1;
|
||||
drop table second_db.t1;
|
||||
drop database first_db;
|
||||
drop database second_db;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE IF EXISTS federated;
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
DROP DATABASE IF EXISTS federated;
|
103
mysql-test/t/federated_server.test
Normal file
103
mysql-test/t/federated_server.test
Normal file
@ -0,0 +1,103 @@
|
||||
# should work with embedded server after mysqltest is fixed
|
||||
-- source include/not_embedded.inc
|
||||
source include/federated.inc;
|
||||
|
||||
connection slave;
|
||||
create database first_db;
|
||||
create database second_db;
|
||||
|
||||
use first_db;
|
||||
|
||||
DROP TABLE IF EXISTS first_db.t1;
|
||||
CREATE TABLE first_db.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
DEFAULT CHARSET=latin1;
|
||||
|
||||
use second_db;
|
||||
DROP TABLE IF EXISTS second_db.t1;
|
||||
CREATE TABLE second_db.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
DEFAULT CHARSET=latin1;
|
||||
|
||||
connection master;
|
||||
|
||||
drop server if exists 'server_one';
|
||||
eval create server 'server_one' foreign data wrapper 'mysql' options
|
||||
(HOST '127.0.0.1',
|
||||
DATABASE 'first_db',
|
||||
USER 'root',
|
||||
PASSWORD '',
|
||||
PORT $SLAVE_MYPORT,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
|
||||
drop server if exists 'server_two';
|
||||
eval create server 'server_two' foreign data wrapper 'mysql' options
|
||||
(HOST '127.0.0.1',
|
||||
DATABASE 'second_db',
|
||||
USER 'root',
|
||||
PASSWORD '',
|
||||
PORT $SLAVE_MYPORT,
|
||||
SOCKET '',
|
||||
OWNER 'root');
|
||||
|
||||
select * from mysql.servers;
|
||||
|
||||
DROP TABLE IF EXISTS federated.old;
|
||||
eval CREATE TABLE federated.old (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/first_db/t1';
|
||||
|
||||
INSERT INTO federated.old (id, name) values (1, 'federated.old url');
|
||||
|
||||
SELECT * FROM federated.old;
|
||||
|
||||
DROP TABLE IF EXISTS federated.old2;
|
||||
eval CREATE TABLE federated.old2 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/second_db/t1';
|
||||
|
||||
INSERT INTO federated.old2 (id, name) values (1, 'federated.old2 url');
|
||||
|
||||
DROP TABLE IF EXISTS federated.t1;
|
||||
CREATE TABLE federated.t1 (
|
||||
`id` int(20) NOT NULL,
|
||||
`name` varchar(64) NOT NULL default ''
|
||||
)
|
||||
ENGINE="FEDERATED" DEFAULT CHARSET=latin1
|
||||
CONNECTION='server_one';
|
||||
|
||||
INSERT INTO federated.t1 (id, name) values (1, 'server_one, new scheme');
|
||||
|
||||
SELECT * FROM federated.t1;
|
||||
|
||||
ALTER SERVER 'server_one' options(DATABASE 'second_db');
|
||||
|
||||
flush tables;
|
||||
|
||||
INSERT INTO federated.t1 (id, name) values (1, 'server_two, new scheme');
|
||||
SELECT * FROM federated.t1;
|
||||
|
||||
drop table federated.t1;
|
||||
|
||||
drop server 'server_one';
|
||||
drop server 'server_two';
|
||||
select * from mysql.servers;
|
||||
|
||||
connection slave;
|
||||
drop table first_db.t1;
|
||||
drop table second_db.t1;
|
||||
drop database first_db;
|
||||
drop database second_db;
|
||||
|
||||
source include/federated_cleanup.inc;
|
@ -192,6 +192,33 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for old tables
|
||||
if test ! -f $mdata/servers.frm
|
||||
then
|
||||
if test "$1" = "verbose" ; then
|
||||
echo "Preparing servers table" 1>&2;
|
||||
fi
|
||||
|
||||
c_d="$c_d
|
||||
|
||||
CREATE TABLE servers ("
|
||||
c_d="$c_d Server_name char(64) NOT NULL,"
|
||||
c_d="$c_d Hostname char(64) NOT NULL,"
|
||||
c_d="$c_d Db char(64) NOT NULL,"
|
||||
c_d="$c_d Username char(64) NOT NULL,"
|
||||
c_d="$c_d Passwd char(64) NOT NULL,"
|
||||
c_d="$c_d Portnum INT(4),"
|
||||
c_d="$c_d Sock char(64),"
|
||||
c_d="$c_d Scheme char(64) NOT NULL,"
|
||||
c_d="$c_d Owner char(64) NOT NULL,"
|
||||
c_d="$c_d PRIMARY KEY (Server_name));"
|
||||
|
||||
i_d="INSERT INTO servers VALUES
|
||||
('test','localhost','test','root','', 0,
|
||||
'','mysql','root');
|
||||
"
|
||||
fi
|
||||
|
||||
if test ! -f $mdata/func.frm
|
||||
then
|
||||
if test "$1" = "verbose" ; then
|
||||
|
@ -68,7 +68,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
|
||||
event_db_repository.h event_queue.h \
|
||||
sql_plugin.h authors.h sql_partition.h event_data_objects.h \
|
||||
partition_info.h partition_element.h event_scheduler.h \
|
||||
contributors.h
|
||||
contributors.h sql_servers.h
|
||||
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
||||
item.cc item_sum.cc item_buff.cc item_func.cc \
|
||||
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
|
||||
@ -106,7 +106,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
||||
event_scheduler.cc event_data_objects.cc \
|
||||
event_queue.cc event_db_repository.cc events.cc \
|
||||
sql_plugin.cc sql_binlog.cc \
|
||||
sql_builtin.cc sql_tablespace.cc partition_info.cc
|
||||
sql_builtin.cc sql_tablespace.cc partition_info.cc \
|
||||
sql_servers.cc
|
||||
|
||||
|
||||
gen_lex_hash_SOURCES = gen_lex_hash.cc
|
||||
|
@ -229,6 +229,7 @@ static SYMBOL symbols[] = {
|
||||
{ "HAVING", SYM(HAVING)},
|
||||
{ "HELP", SYM(HELP_SYM)},
|
||||
{ "HIGH_PRIORITY", SYM(HIGH_PRIORITY)},
|
||||
{ "HOST", SYM(HOST_SYM)},
|
||||
{ "HOSTS", SYM(HOSTS_SYM)},
|
||||
{ "HOUR", SYM(HOUR_SYM)},
|
||||
{ "HOUR_MICROSECOND", SYM(HOUR_MICROSECOND_SYM)},
|
||||
@ -368,6 +369,7 @@ static SYMBOL symbols[] = {
|
||||
{ "ONE_SHOT", SYM(ONE_SHOT_SYM)},
|
||||
{ "OPEN", SYM(OPEN_SYM)},
|
||||
{ "OPTIMIZE", SYM(OPTIMIZE)},
|
||||
{ "OPTIONS", SYM(OPTIONS_SYM)},
|
||||
{ "OPTION", SYM(OPTION)},
|
||||
{ "OPTIONALLY", SYM(OPTIONALLY)},
|
||||
{ "OR", SYM(OR_SYM)},
|
||||
@ -375,6 +377,7 @@ static SYMBOL symbols[] = {
|
||||
{ "OUT", SYM(OUT_SYM)},
|
||||
{ "OUTER", SYM(OUTER)},
|
||||
{ "OUTFILE", SYM(OUTFILE)},
|
||||
{ "OWNER", SYM(OWNER_SYM)},
|
||||
{ "PACK_KEYS", SYM(PACK_KEYS_SYM)},
|
||||
{ "PARSER", SYM(PARSER_SYM)},
|
||||
{ "PARTIAL", SYM(PARTIAL)},
|
||||
@ -387,6 +390,7 @@ static SYMBOL symbols[] = {
|
||||
{ "PLUGINS", SYM(PLUGINS_SYM)},
|
||||
{ "POINT", SYM(POINT_SYM)},
|
||||
{ "POLYGON", SYM(POLYGON)},
|
||||
{ "PORT", SYM(PORT_SYM)},
|
||||
{ "PRECISION", SYM(PRECISION)},
|
||||
{ "PREPARE", SYM(PREPARE_SYM)},
|
||||
{ "PRESERVE", SYM(PRESERVE_SYM)},
|
||||
@ -456,6 +460,7 @@ static SYMBOL symbols[] = {
|
||||
{ "SERIAL", SYM(SERIAL_SYM)},
|
||||
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM)},
|
||||
{ "SESSION", SYM(SESSION_SYM)},
|
||||
{ "SERVER", SYM(SERVER_SYM)},
|
||||
{ "SET", SYM(SET)},
|
||||
{ "SHARE", SYM(SHARE_SYM)},
|
||||
{ "SHOW", SYM(SHOW)},
|
||||
@ -465,6 +470,7 @@ static SYMBOL symbols[] = {
|
||||
{ "SLAVE", SYM(SLAVE)},
|
||||
{ "SNAPSHOT", SYM(SNAPSHOT_SYM)},
|
||||
{ "SMALLINT", SYM(SMALLINT)},
|
||||
{ "SOCKET", SYM(SOCKET_SYM)},
|
||||
{ "SOME", SYM(ANY_SYM)},
|
||||
{ "SONAME", SYM(SONAME_SYM)},
|
||||
{ "SOUNDS", SYM(SOUNDS_SYM)},
|
||||
@ -569,6 +575,7 @@ static SYMBOL symbols[] = {
|
||||
{ "VIEW", SYM(VIEW_SYM)},
|
||||
{ "WITH", SYM(WITH)},
|
||||
{ "WORK", SYM(WORK_SYM)},
|
||||
{ "WRAPPER", SYM(WRAPPER_SYM)},
|
||||
{ "WRITE", SYM(WRITE_SYM)},
|
||||
{ "X509", SYM(X509_SYM)},
|
||||
{ "XOR", SYM(XOR)},
|
||||
|
@ -624,6 +624,7 @@ Item *negate_expression(THD *thd, Item *expr);
|
||||
#include "sql_acl.h"
|
||||
#include "tztime.h"
|
||||
#ifdef MYSQL_SERVER
|
||||
#include "sql_servers.h"
|
||||
#include "opt_range.h"
|
||||
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
|
@ -1174,6 +1174,7 @@ void clean_up(bool print_message)
|
||||
my_tz_free();
|
||||
my_database_names_free();
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
servers_free(1);
|
||||
acl_free(1);
|
||||
grant_free();
|
||||
#endif
|
||||
@ -3638,6 +3639,9 @@ we force server id to 2, but this MySQL server will not act as a slave.");
|
||||
if (!opt_noacl)
|
||||
(void) grant_init();
|
||||
|
||||
if (!opt_bootstrap)
|
||||
servers_init(0);
|
||||
|
||||
if (!opt_noacl)
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
|
@ -5607,6 +5607,8 @@ ER_SP_RECURSION_LIMIT
|
||||
ER_SP_PROC_TABLE_CORRUPT
|
||||
eng "Failed to load routine %-.64s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)"
|
||||
ger "Routine %-64s konnte nicht geladen werden. Die Tabelle mysql.proc fehlt, ist beschädigt, oder enthält fehlerhaften Daten (interner Code: %d)"
|
||||
ER_FOREIGN_SERVER_EXISTS
|
||||
eng "The foreign server, %s, you are trying to create already exists."
|
||||
ER_SP_WRONG_NAME 42000
|
||||
eng "Incorrect routine name '%-.64s'"
|
||||
ger "Ungültiger Routinenname '%-.64s'"
|
||||
@ -5847,6 +5849,9 @@ ER_BINLOG_ROW_WRONG_TABLE_DEF
|
||||
ER_BINLOG_ROW_RBR_TO_SBR
|
||||
eng "Slave running with --log-slave-updates must use row-based binary logging to be able to replicate row-based binary log events"
|
||||
ger "Slave, die mit --log-slave-updates laufen, müssen zeilenbasiertes Loggen verwenden, um zeilenbasierte Binärlog-Ereignisse loggen zu können"
|
||||
ER_FOREIGN_SERVER_DOESNT_EXIST
|
||||
eng "The foreign server name you are trying to reference does not exist. Data source error: %-.64s"
|
||||
ger "Die externe Verbindung, auf die Sie zugreifen wollen, existiert nicht. Datenquellenfehlermeldung: %-.64s"
|
||||
ER_EVENT_ALREADY_EXISTS
|
||||
eng "Event '%-.64s' already exists"
|
||||
ger "Event '%-.64s' existiert bereits"
|
||||
|
@ -184,6 +184,21 @@ void lex_start(THD *thd, const uchar *buf, uint length)
|
||||
lex->nest_level=0 ;
|
||||
lex->allow_sum_func= 0;
|
||||
lex->in_sum_func= NULL;
|
||||
/*
|
||||
ok, there must be a better solution for this, long-term
|
||||
I tried "bzero" in the sql_yacc.yy code, but that for
|
||||
some reason made the values zero, even if they were set
|
||||
*/
|
||||
lex->server_options.server_name= 0;
|
||||
lex->server_options.server_name_length= 0;
|
||||
lex->server_options.host= 0;
|
||||
lex->server_options.db= 0;
|
||||
lex->server_options.username= 0;
|
||||
lex->server_options.password= 0;
|
||||
lex->server_options.scheme= 0;
|
||||
lex->server_options.socket= 0;
|
||||
lex->server_options.owner= 0;
|
||||
lex->server_options.port= -1;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,7 @@ enum enum_sql_command {
|
||||
SQLCOM_SHOW_AUTHORS, SQLCOM_BINLOG_BASE64_EVENT,
|
||||
SQLCOM_SHOW_PLUGINS,
|
||||
SQLCOM_SHOW_CONTRIBUTORS,
|
||||
SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER,
|
||||
SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
|
||||
SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
|
||||
|
||||
@ -174,6 +175,14 @@ enum enum_drop_mode
|
||||
|
||||
typedef List<Item> List_item;
|
||||
|
||||
/* SERVERS CACHE CHANGES */
|
||||
typedef struct st_lex_server_options
|
||||
{
|
||||
long port;
|
||||
uint server_name_length;
|
||||
char *server_name, *host, *db, *username, *password, *scheme, *socket, *owner;
|
||||
} LEX_SERVER_OPTIONS;
|
||||
|
||||
typedef struct st_lex_master_info
|
||||
{
|
||||
char *host, *user, *password, *log_file_name;
|
||||
@ -979,6 +988,7 @@ typedef struct st_lex : public Query_tables_list
|
||||
HA_CREATE_INFO create_info;
|
||||
KEY_CREATE_INFO key_create_info;
|
||||
LEX_MASTER_INFO mi; // used by CHANGE MASTER
|
||||
LEX_SERVER_OPTIONS server_options;
|
||||
USER_RESOURCES mqh;
|
||||
ulong type;
|
||||
/*
|
||||
|
@ -5183,6 +5183,58 @@ end_with_restore_list:
|
||||
#endif /* EMBEDDED_LIBRARY */
|
||||
break;
|
||||
}
|
||||
case SQLCOM_CREATE_SERVER:
|
||||
{
|
||||
int error;
|
||||
LEX *lex= thd->lex;
|
||||
DBUG_PRINT("info", ("case SQLCOM_CREATE_SERVER"));
|
||||
if ((error= create_server(thd, &lex->server_options)))
|
||||
{
|
||||
DBUG_PRINT("info", ("problem creating server",
|
||||
lex->server_options.server_name));
|
||||
my_error(error, MYF(0), lex->server_options.server_name);
|
||||
break;
|
||||
}
|
||||
send_ok(thd, 1);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_ALTER_SERVER:
|
||||
{
|
||||
int error;
|
||||
LEX *lex= thd->lex;
|
||||
DBUG_PRINT("info", ("case SQLCOM_ALTER_SERVER"));
|
||||
if ((error= alter_server(thd, &lex->server_options)))
|
||||
{
|
||||
DBUG_PRINT("info", ("problem altering server",
|
||||
lex->server_options.server_name));
|
||||
my_error(error, MYF(0), lex->server_options.server_name);
|
||||
break;
|
||||
}
|
||||
send_ok(thd, 1);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_DROP_SERVER:
|
||||
{
|
||||
int err_code;
|
||||
LEX *lex= thd->lex;
|
||||
DBUG_PRINT("info", ("case SQLCOM_DROP_SERVER"));
|
||||
if ((err_code= drop_server(thd, &lex->server_options)))
|
||||
{
|
||||
if (! lex->drop_if_exists && err_code == ER_FOREIGN_SERVER_EXISTS)
|
||||
{
|
||||
DBUG_PRINT("info", ("problem dropping server %s",
|
||||
lex->server_options.server_name));
|
||||
my_error(err_code, MYF(0), lex->server_options.server_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_ok(thd, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
send_ok(thd, 1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
DBUG_ASSERT(0); /* Impossible */
|
||||
|
1238
sql/sql_servers.cc
Normal file
1238
sql/sql_servers.cc
Normal file
File diff suppressed because it is too large
Load Diff
66
sql/sql_servers.h
Normal file
66
sql/sql_servers.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include "slave.h" // for tables_ok(), rpl_filter
|
||||
|
||||
/* structs */
|
||||
typedef struct st_federated_server
|
||||
{
|
||||
char *server_name;
|
||||
long port;
|
||||
uint server_name_length;
|
||||
char *db, *scheme, *username, *password, *socket, *owner, *host, *sport;
|
||||
} FOREIGN_SERVER;
|
||||
|
||||
/* cache handlers */
|
||||
my_bool servers_init(bool dont_read_server_table);
|
||||
static my_bool servers_load(THD *thd, TABLE_LIST *tables);
|
||||
my_bool servers_reload(THD *thd);
|
||||
my_bool get_server_from_table_to_cache(TABLE *table);
|
||||
void servers_free(bool end=0);
|
||||
|
||||
/* insert functions */
|
||||
int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options);
|
||||
int insert_server(THD *thd, FOREIGN_SERVER *server_options);
|
||||
int insert_server_record(TABLE *table, FOREIGN_SERVER *server);
|
||||
int insert_server_record_into_cache(FOREIGN_SERVER *server);
|
||||
void store_server_fields_for_insert(TABLE *table, FOREIGN_SERVER *server);
|
||||
void store_server_fields_for_insert(TABLE *table,
|
||||
FOREIGN_SERVER *existing,
|
||||
FOREIGN_SERVER *altered);
|
||||
int prepare_server_struct_for_insert(LEX_SERVER_OPTIONS *server_options,
|
||||
FOREIGN_SERVER *server);
|
||||
|
||||
/* drop functions */
|
||||
int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options);
|
||||
int delete_server_record(TABLE *table,
|
||||
char *server_name,
|
||||
int server_name_length);
|
||||
int delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options);
|
||||
|
||||
/* update functions */
|
||||
int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options);
|
||||
int prepare_server_struct_for_update(LEX_SERVER_OPTIONS *server_options,
|
||||
FOREIGN_SERVER *existing,
|
||||
FOREIGN_SERVER *altered);
|
||||
int update_server(THD *thd, FOREIGN_SERVER *existing, FOREIGN_SERVER *altered);
|
||||
int update_server_record(TABLE *table, FOREIGN_SERVER *server);
|
||||
int update_server_record_in_cache(FOREIGN_SERVER *existing,
|
||||
FOREIGN_SERVER *altered);
|
||||
/* utility functions */
|
||||
void merge_server_struct(FOREIGN_SERVER *from, FOREIGN_SERVER *to);
|
||||
FOREIGN_SERVER *get_server_by_name(const char *server_name);
|
||||
my_bool server_exists_in_table(THD *thd, char *server_name);
|
@ -364,6 +364,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token HELP_SYM
|
||||
%token HEX_NUM
|
||||
%token HIGH_PRIORITY
|
||||
%token HOST_SYM
|
||||
%token HOSTS_SYM
|
||||
%token HOUR_MICROSECOND_SYM
|
||||
%token HOUR_MINUTE_SYM
|
||||
@ -506,6 +507,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token ONE_SYM
|
||||
%token OPEN_SYM /* SQL-2003-R */
|
||||
%token OPTIMIZE
|
||||
%token OPTIONS_SYM
|
||||
%token OPTION /* SQL-2003-N */
|
||||
%token OPTIONALLY
|
||||
%token OR2_SYM
|
||||
@ -515,6 +517,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token OUTER
|
||||
%token OUTFILE
|
||||
%token OUT_SYM /* SQL-2003-R */
|
||||
%token OWNER_SYM
|
||||
%token PACK_KEYS_SYM
|
||||
%token PARAM_MARKER
|
||||
%token PARSER_SYM
|
||||
@ -528,6 +531,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token PLUGIN_SYM
|
||||
%token POINT_SYM
|
||||
%token POLYGON
|
||||
%token PORT_SYM
|
||||
%token POSITION_SYM /* SQL-2003-N */
|
||||
%token PRECISION /* SQL-2003-R */
|
||||
%token PREPARE_SYM /* SQL-2003-R */
|
||||
@ -596,6 +600,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token SERIALIZABLE_SYM /* SQL-2003-N */
|
||||
%token SERIAL_SYM
|
||||
%token SESSION_SYM /* SQL-2003-N */
|
||||
%token SERVER_SYM
|
||||
%token SERVER_OPTIONS
|
||||
%token SET /* SQL-2003-R */
|
||||
%token SET_VAR
|
||||
%token SHARE_SYM
|
||||
@ -608,6 +614,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token SLAVE
|
||||
%token SMALLINT /* SQL-2003-R */
|
||||
%token SNAPSHOT_SYM
|
||||
%token SOCKET_SYM
|
||||
%token SONAME_SYM
|
||||
%token SOUNDS_SYM
|
||||
%token SPATIAL_SYM
|
||||
@ -715,6 +722,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
%token WHILE_SYM
|
||||
%token WITH /* SQL-2003-R */
|
||||
%token WORK_SYM /* SQL-2003-N */
|
||||
%token WRAPPER_SYM
|
||||
%token WRITE_SYM /* SQL-2003-N */
|
||||
%token X509_SYM
|
||||
%token XA_SYM
|
||||
@ -910,6 +918,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
view_check_option trigger_tail sp_tail
|
||||
install uninstall partition_entry binlog_base64_event
|
||||
init_key_options key_options key_opts key_opt key_using_alg
|
||||
server_def server_options_list server_option
|
||||
END_OF_INPUT
|
||||
|
||||
%type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt
|
||||
@ -1303,8 +1312,61 @@ create:
|
||||
{
|
||||
Lex->alter_tablespace_info->ts_cmd_type= CREATE_TABLESPACE;
|
||||
}
|
||||
| CREATE server_def
|
||||
{
|
||||
Lex->sql_command= SQLCOM_CREATE_SERVER;
|
||||
}
|
||||
;
|
||||
server_def:
|
||||
SERVER_SYM ident_or_text FOREIGN DATA_SYM WRAPPER_SYM ident_or_text OPTIONS_SYM '(' server_options_list ')'
|
||||
{
|
||||
Lex->server_options.server_name= $2.str;
|
||||
Lex->server_options.server_name_length= $2.length;
|
||||
Lex->server_options.scheme= $6.str;
|
||||
}
|
||||
;
|
||||
|
||||
server_options_list:
|
||||
server_option
|
||||
| server_options_list ',' server_option
|
||||
;
|
||||
|
||||
server_option:
|
||||
USER TEXT_STRING_sys
|
||||
{
|
||||
Lex->server_options.username= $2.str;
|
||||
}
|
||||
|
|
||||
HOST_SYM TEXT_STRING_sys
|
||||
{
|
||||
Lex->server_options.host= $2.str;
|
||||
}
|
||||
|
|
||||
DATABASE TEXT_STRING_sys
|
||||
{
|
||||
Lex->server_options.db= $2.str;
|
||||
}
|
||||
|
|
||||
OWNER_SYM TEXT_STRING_sys
|
||||
{
|
||||
Lex->server_options.owner= $2.str;
|
||||
}
|
||||
|
|
||||
PASSWORD TEXT_STRING_sys
|
||||
{
|
||||
Lex->server_options.password= $2.str;
|
||||
}
|
||||
|
|
||||
SOCKET_SYM TEXT_STRING_sys
|
||||
{
|
||||
Lex->server_options.socket= $2.str;
|
||||
}
|
||||
|
|
||||
PORT_SYM ulong_num
|
||||
{
|
||||
Lex->server_options.port= $2;
|
||||
}
|
||||
;
|
||||
|
||||
event_tail:
|
||||
EVENT_SYM opt_if_not_exists sp_name
|
||||
@ -4832,6 +4894,13 @@ alter:
|
||||
LEX *lex= Lex;
|
||||
lex->alter_tablespace_info->ts_cmd_type= ALTER_ACCESS_MODE_TABLESPACE;
|
||||
}
|
||||
| ALTER SERVER_SYM ident_or_text OPTIONS_SYM '(' server_options_list ')'
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
Lex->sql_command= SQLCOM_ALTER_SERVER;
|
||||
Lex->server_options.server_name= $3.str;
|
||||
Lex->server_options.server_name_length= $3.length;
|
||||
}
|
||||
;
|
||||
|
||||
ev_alter_on_schedule_completion: /* empty */ { $$= 0;}
|
||||
@ -7758,6 +7827,13 @@ drop:
|
||||
LEX *lex= Lex;
|
||||
lex->alter_tablespace_info->ts_cmd_type= DROP_LOGFILE_GROUP;
|
||||
}
|
||||
| DROP SERVER_SYM if_exists ident_or_text
|
||||
{
|
||||
Lex->sql_command = SQLCOM_DROP_SERVER;
|
||||
Lex->drop_if_exists= $3;
|
||||
Lex->server_options.server_name= $4.str;
|
||||
Lex->server_options.server_name_length= $4.length;
|
||||
}
|
||||
;
|
||||
|
||||
table_list:
|
||||
@ -9324,12 +9400,15 @@ keyword:
|
||||
| FLUSH_SYM {}
|
||||
| HANDLER_SYM {}
|
||||
| HELP_SYM {}
|
||||
| HOST_SYM {}
|
||||
| INSTALL_SYM {}
|
||||
| LANGUAGE_SYM {}
|
||||
| NO_SYM {}
|
||||
| OPEN_SYM {}
|
||||
| OWNER_SYM {}
|
||||
| PARSER_SYM {}
|
||||
| PARTITION_SYM {}
|
||||
| PORT_SYM {}
|
||||
| PREPARE_SYM {}
|
||||
| REMOVE_SYM {}
|
||||
| REPAIR {}
|
||||
@ -9338,7 +9417,9 @@ keyword:
|
||||
| ROLLBACK_SYM {}
|
||||
| SAVEPOINT_SYM {}
|
||||
| SECURITY_SYM {}
|
||||
| SERVER_SYM {}
|
||||
| SIGNED_SYM {}
|
||||
| SOCKET_SYM {}
|
||||
| SLAVE {}
|
||||
| SONAME_SYM {}
|
||||
| START_SYM {}
|
||||
@ -9346,6 +9427,8 @@ keyword:
|
||||
| TRUNCATE_SYM {}
|
||||
| UNICODE_SYM {}
|
||||
| UNINSTALL_SYM {}
|
||||
| USER {}
|
||||
| WRAPPER_SYM {}
|
||||
| XA_SYM {}
|
||||
| UPGRADE_SYM {}
|
||||
;
|
||||
|
11279
sql/sql_yacc.yy.bak
Normal file
11279
sql/sql_yacc.yy.bak
Normal file
File diff suppressed because it is too large
Load Diff
@ -381,8 +381,8 @@ static handler *federated_create_handler(handlerton *hton,
|
||||
static byte *federated_get_key(FEDERATED_SHARE *share, uint *length,
|
||||
my_bool not_used __attribute__ ((unused)))
|
||||
{
|
||||
*length= share->connect_string_length;
|
||||
return (byte*) share->scheme;
|
||||
*length= share->share_key_length;
|
||||
return (byte*) share->share_key;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -549,13 +549,14 @@ static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num)
|
||||
int buf_len;
|
||||
DBUG_ENTER("ha_federated parse_url_error");
|
||||
|
||||
if (share->scheme)
|
||||
if (share->connection_string)
|
||||
{
|
||||
DBUG_PRINT("info",
|
||||
("error: parse_url. Returning error code %d freeing share->scheme 0x%lx",
|
||||
error_num, (long) share->scheme));
|
||||
my_free((gptr) share->scheme, MYF(0));
|
||||
share->scheme= 0;
|
||||
("error: parse_url. Returning error code %d \
|
||||
freeing share->connection_string %lx",
|
||||
error_num, share->connection_string));
|
||||
my_free((gptr) share->connection_string, MYF(0));
|
||||
share->connection_string= 0;
|
||||
}
|
||||
buf_len= min(table->s->connect_string.length,
|
||||
FEDERATED_QUERY_BUFFER_SIZE-1);
|
||||
@ -563,6 +564,75 @@ static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num)
|
||||
my_error(error_num, MYF(0), buf);
|
||||
DBUG_RETURN(error_num);
|
||||
}
|
||||
/*
|
||||
retrieve server object which contains server meta-data
|
||||
from the system table given a server's name, set share
|
||||
connection parameter members
|
||||
*/
|
||||
int get_connection(FEDERATED_SHARE *share)
|
||||
{
|
||||
int error_num= ER_FOREIGN_SERVER_DOESNT_EXIST;
|
||||
char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
|
||||
FOREIGN_SERVER *server;
|
||||
MYSQL *mysql_conn;
|
||||
MYSQL_RES *result= 0;
|
||||
MYSQL_ROW row;
|
||||
DBUG_ENTER("ha_federated::get_connection");
|
||||
|
||||
if (!(server=
|
||||
get_server_by_name(share->connection_string)))
|
||||
{
|
||||
DBUG_PRINT("info", ("get_server_by_name returned > 0 error condition!"));
|
||||
/* need to come up with error handling */
|
||||
error_num=1;
|
||||
goto error;
|
||||
}
|
||||
DBUG_PRINT("info", ("get_server_by_name returned server at %lx", server));
|
||||
|
||||
/*
|
||||
Most of these should never be empty strings, error handling will
|
||||
need to be implemented. Also, is this the best way to set the share
|
||||
members? Is there some allocation needed? In running this code, it works
|
||||
except there are errors in the trace file of the share being overrun
|
||||
at the address of the share.
|
||||
*/
|
||||
if (server->server_name)
|
||||
share->server_name= server->server_name;
|
||||
share->server_name_length= server->server_name_length ?
|
||||
server->server_name_length : 0;
|
||||
if (server->username)
|
||||
share->username= server->username;
|
||||
if (server->password)
|
||||
share->password= server->password;
|
||||
if (server->db)
|
||||
share->database= server->db;
|
||||
if (server->sport)
|
||||
share->sport= server->sport;
|
||||
share->port= server->port ? server->port : 0;
|
||||
if (server->host)
|
||||
share->hostname= server->host;
|
||||
if (server->socket)
|
||||
share->socket= server->socket;
|
||||
if (server->scheme)
|
||||
share->scheme= server->scheme;
|
||||
else
|
||||
share->scheme= NULL;
|
||||
|
||||
DBUG_PRINT("info", ("share->username %s", share->username));
|
||||
DBUG_PRINT("info", ("share->password %s", share->password));
|
||||
DBUG_PRINT("info", ("share->hostname %s", share->hostname));
|
||||
DBUG_PRINT("info", ("share->database %s", share->database));
|
||||
DBUG_PRINT("info", ("share->port %d", share->port));
|
||||
DBUG_PRINT("info", ("share->socket %d", share->socket));
|
||||
DBUG_RETURN(0);
|
||||
|
||||
error:
|
||||
my_sprintf(error_buffer,
|
||||
(error_buffer, "server name: '%s' doesn't exist!",
|
||||
share->connection_string));
|
||||
my_error(error_num, MYF(0), error_buffer);
|
||||
DBUG_RETURN(error_num);
|
||||
}
|
||||
|
||||
/*
|
||||
Parse connection info from table->s->connect_string
|
||||
@ -576,22 +646,39 @@ static int parse_url_error(FEDERATED_SHARE *share, TABLE *table, int error_num)
|
||||
DESCRIPTION
|
||||
Populates the share with information about the connection
|
||||
to the foreign database that will serve as the data source.
|
||||
This string must be specified (currently) in the "comment" field,
|
||||
This string must be specified (currently) in the "CONNECTION" field,
|
||||
listed in the CREATE TABLE statement.
|
||||
|
||||
This string MUST be in the format of any of these:
|
||||
|
||||
scheme://username:password@hostname:port/database/table
|
||||
scheme://username@hostname/database/table
|
||||
scheme://username@hostname:port/database/table
|
||||
scheme://username:password@hostname/database/table
|
||||
CONNECTION="scheme://username:password@hostname:port/database/table"
|
||||
CONNECTION="scheme://username@hostname/database/table"
|
||||
CONNECTION="scheme://username@hostname:port/database/table"
|
||||
CONNECTION="scheme://username:password@hostname/database/table"
|
||||
|
||||
_OR_
|
||||
|
||||
CONNECTION="connection name"
|
||||
|
||||
|
||||
|
||||
An Example:
|
||||
|
||||
mysql://joe:joespass@192.168.1.111:9308/federated/testtable
|
||||
CREATE TABLE t1 (id int(32))
|
||||
ENGINE="FEDERATED"
|
||||
CONNECTION="mysql://joe:joespass@192.168.1.111:9308/federated/testtable";
|
||||
|
||||
CREATE TABLE t2 (
|
||||
id int(4) NOT NULL auto_increment,
|
||||
name varchar(32) NOT NULL,
|
||||
PRIMARY KEY(id)
|
||||
) ENGINE="FEDERATED" CONNECTION="my_conn";
|
||||
|
||||
***IMPORTANT***
|
||||
Currently, only "mysql://" is supported.
|
||||
Currently, the Federated Storage Engine only supports connecting to another
|
||||
MySQL Database ("scheme" of "mysql"). Connections using JDBC as well as
|
||||
other connectors are in the planning stage.
|
||||
|
||||
|
||||
'password' and 'port' are both optional.
|
||||
|
||||
@ -611,87 +698,124 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
|
||||
|
||||
share->port= 0;
|
||||
share->socket= 0;
|
||||
DBUG_PRINT("info", ("share at %lx", share));
|
||||
DBUG_PRINT("info", ("Length: %d", table->s->connect_string.length));
|
||||
DBUG_PRINT("info", ("String: '%.*s'", table->s->connect_string.length,
|
||||
DBUG_PRINT("info", ("String: '%.*s'", table->s->connect_string.length,
|
||||
table->s->connect_string.str));
|
||||
share->scheme= my_strndup(table->s->connect_string.str,
|
||||
table->s->connect_string.length,
|
||||
MYF(0));
|
||||
share->connection_string= my_strndup((const byte*)table->s->
|
||||
connect_string.str,
|
||||
table->s->connect_string.length,
|
||||
MYF(0));
|
||||
|
||||
share->connect_string_length= table->s->connect_string.length;
|
||||
DBUG_PRINT("info",("parse_url alloced share->scheme 0x%lx", (long) share->scheme));
|
||||
// Add a null for later termination of table name
|
||||
share->connection_string[table->s->connect_string.length]= 0;
|
||||
DBUG_PRINT("info",("parse_url alloced share->scheme %lx",
|
||||
share->connection_string));
|
||||
|
||||
/*
|
||||
remove addition of null terminator and store length
|
||||
for each string in share
|
||||
*/
|
||||
if (!(share->username= strstr(share->scheme, "://")))
|
||||
goto error;
|
||||
share->scheme[share->username - share->scheme]= '\0';
|
||||
|
||||
if (strcmp(share->scheme, "mysql") != 0)
|
||||
goto error;
|
||||
|
||||
share->username+= 3;
|
||||
|
||||
if (!(share->hostname= strchr(share->username, '@')))
|
||||
goto error;
|
||||
|
||||
share->username[share->hostname - share->username]= '\0';
|
||||
share->hostname++;
|
||||
|
||||
if ((share->password= strchr(share->username, ':')))
|
||||
DBUG_PRINT("info",("share->connection_string %s",share->connection_string));
|
||||
/* No delimiters, must be a straight connection name */
|
||||
if ( (!strchr(share->connection_string, '/')) &&
|
||||
(!strchr(share->connection_string, '@')) &&
|
||||
(!strchr(share->connection_string, ';')))
|
||||
{
|
||||
share->username[share->password - share->username]= '\0';
|
||||
share->password++;
|
||||
share->username= share->username;
|
||||
/* make sure there isn't an extra / or @ */
|
||||
if ((strchr(share->password, '/') || strchr(share->hostname, '@')))
|
||||
|
||||
DBUG_PRINT("info",
|
||||
("share->connection_string %s internal format \
|
||||
share->connection_string",
|
||||
share->connection_string, share->connection_string));
|
||||
|
||||
share->parsed= FALSE;
|
||||
if ((error_num= get_connection(share)))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
Found that if the string is:
|
||||
user:@hostname:port/database/table
|
||||
Then password is a null string, so set to NULL
|
||||
connection specifies everything but, resort to
|
||||
expecting remote and foreign table names to match
|
||||
*/
|
||||
if ((share->password[0] == '\0'))
|
||||
share->password= NULL;
|
||||
share->table_name= table->s->table_name.str;
|
||||
share->table_name_length= table->s->table_name.length;
|
||||
share->table_name[share->table_name_length]= '\0';
|
||||
}
|
||||
else
|
||||
share->username= share->username;
|
||||
|
||||
/* make sure there isn't an extra / or @ */
|
||||
if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
|
||||
goto error;
|
||||
|
||||
if (!(share->database= strchr(share->hostname, '/')))
|
||||
goto error;
|
||||
share->hostname[share->database - share->hostname]= '\0';
|
||||
share->database++;
|
||||
|
||||
if ((share->sport= strchr(share->hostname, ':')))
|
||||
{
|
||||
share->hostname[share->sport - share->hostname]= '\0';
|
||||
share->sport++;
|
||||
if (share->sport[0] == '\0')
|
||||
share->sport= NULL;
|
||||
share->parsed= TRUE;
|
||||
// Add a null for later termination of table name
|
||||
share->connection_string[table->s->connect_string.length]= 0;
|
||||
share->scheme= share->connection_string;
|
||||
DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme));
|
||||
|
||||
/*
|
||||
remove addition of null terminator and store length
|
||||
for each string in share
|
||||
*/
|
||||
if (!(share->username= strstr(share->scheme, "://")))
|
||||
goto error;
|
||||
share->scheme[share->username - share->scheme]= '\0';
|
||||
|
||||
if (strcmp(share->scheme, "mysql") != 0)
|
||||
goto error;
|
||||
|
||||
share->username+= 3;
|
||||
|
||||
if (!(share->hostname= strchr(share->username, '@')))
|
||||
goto error;
|
||||
|
||||
share->username[share->hostname - share->username]= '\0';
|
||||
share->hostname++;
|
||||
|
||||
if ((share->password= strchr(share->username, ':')))
|
||||
{
|
||||
share->username[share->password - share->username]= '\0';
|
||||
share->password++;
|
||||
share->username= share->username;
|
||||
/* make sure there isn't an extra / or @ */
|
||||
if ((strchr(share->password, '/') || strchr(share->hostname, '@')))
|
||||
goto error;
|
||||
/*
|
||||
Found that if the string is:
|
||||
user:@hostname:port/db/table
|
||||
Then password is a null string, so set to NULL
|
||||
*/
|
||||
if ((share->password[0] == '\0'))
|
||||
share->password= NULL;
|
||||
}
|
||||
else
|
||||
share->port= atoi(share->sport);
|
||||
share->username= share->username;
|
||||
|
||||
/* make sure there isn't an extra / or @ */
|
||||
if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
|
||||
goto error;
|
||||
|
||||
if (!(share->database= strchr(share->hostname, '/')))
|
||||
goto error;
|
||||
share->hostname[share->database - share->hostname]= '\0';
|
||||
share->database++;
|
||||
|
||||
if ((share->sport= strchr(share->hostname, ':')))
|
||||
{
|
||||
share->hostname[share->sport - share->hostname]= '\0';
|
||||
share->sport++;
|
||||
if (share->sport[0] == '\0')
|
||||
share->sport= NULL;
|
||||
else
|
||||
share->port= atoi(share->sport);
|
||||
}
|
||||
|
||||
if (!(share->table_name= strchr(share->database, '/')))
|
||||
goto error;
|
||||
share->database[share->table_name - share->database]= '\0';
|
||||
share->table_name++;
|
||||
|
||||
share->table_name_length= strlen(share->table_name);
|
||||
|
||||
/* make sure there's not an extra / */
|
||||
if ((strchr(share->table_name, '/')))
|
||||
goto error;
|
||||
|
||||
if (share->hostname[0] == '\0')
|
||||
share->hostname= NULL;
|
||||
|
||||
}
|
||||
|
||||
if (!(share->table_name= strchr(share->database, '/')))
|
||||
goto error;
|
||||
share->database[share->table_name - share->database]= '\0';
|
||||
share->table_name++;
|
||||
|
||||
share->table_name_length= strlen(share->table_name);
|
||||
|
||||
/* make sure there's not an extra / */
|
||||
if ((strchr(share->table_name, '/')))
|
||||
goto error;
|
||||
|
||||
if (share->hostname[0] == '\0')
|
||||
share->hostname= NULL;
|
||||
|
||||
if (!share->port)
|
||||
{
|
||||
if (strcmp(share->hostname, my_localhost) == 0)
|
||||
@ -702,7 +826,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
|
||||
|
||||
DBUG_PRINT("info",
|
||||
("scheme: %s username: %s password: %s \
|
||||
hostname: %s port: %d database: %s tablename: %s",
|
||||
hostname: %s port: %d db: %s tablename: %s",
|
||||
share->scheme, share->username, share->password,
|
||||
share->hostname, share->port, share->database,
|
||||
share->table_name));
|
||||
@ -713,7 +837,6 @@ error:
|
||||
DBUG_RETURN(parse_url_error(share, table, error_num));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** FEDERATED tables
|
||||
*****************************************************************************/
|
||||
@ -1313,14 +1436,16 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
|
||||
|
||||
pthread_mutex_lock(&federated_mutex);
|
||||
|
||||
tmp_share.share_key= table_name;
|
||||
tmp_share.share_key_length= strlen(table_name);
|
||||
if (parse_url(&tmp_share, table, 0))
|
||||
goto error;
|
||||
|
||||
/* TODO: change tmp_share.scheme to LEX_STRING object */
|
||||
if (!(share= (FEDERATED_SHARE *) hash_search(&federated_open_tables,
|
||||
(byte*) tmp_share.scheme,
|
||||
(byte*) tmp_share.share_key,
|
||||
tmp_share.
|
||||
connect_string_length)))
|
||||
share_key_length)))
|
||||
{
|
||||
query.set_charset(system_charset_info);
|
||||
query.append(STRING_WITH_LEN("SELECT "));
|
||||
@ -1387,8 +1512,13 @@ static int free_share(FEDERATED_SHARE *share)
|
||||
if (!--share->use_count)
|
||||
{
|
||||
hash_delete(&federated_open_tables, (byte*) share);
|
||||
my_free((gptr) share->scheme, MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free((gptr) share->socket, MYF(MY_ALLOW_ZERO_PTR));
|
||||
if (share->parsed)
|
||||
my_free((gptr) share->socket, MYF(MY_ALLOW_ZERO_PTR));
|
||||
if (share->connection_string)
|
||||
{
|
||||
my_free((gptr) share->connection_string, MYF(MY_ALLOW_ZERO_PTR));
|
||||
share->connection_string= 0;
|
||||
}
|
||||
thr_lock_delete(&share->lock);
|
||||
VOID(pthread_mutex_destroy(&share->mutex));
|
||||
my_free((gptr) share, MYF(0));
|
||||
@ -2697,7 +2827,7 @@ int ha_federated::create(const char *name, TABLE *table_arg,
|
||||
if (!(retval= parse_url(&tmp_share, table_arg, 1)))
|
||||
retval= check_foreign_data_source(&tmp_share, 1);
|
||||
|
||||
my_free((gptr) tmp_share.scheme, MYF(MY_ALLOW_ZERO_PTR));
|
||||
//my_free((gptr) tmp_share.connection_string, MYF(MY_ALLOW_ZERO_PTR));
|
||||
DBUG_RETURN(retval);
|
||||
|
||||
}
|
||||
|
@ -43,6 +43,9 @@
|
||||
The example implements the minimum of what you will probably need.
|
||||
*/
|
||||
typedef struct st_federated_share {
|
||||
bool parsed;
|
||||
/* this key is unique db/tablename */
|
||||
const char *share_key;
|
||||
/*
|
||||
the primary select query to be used in rnd_init
|
||||
*/
|
||||
@ -50,6 +53,8 @@ typedef struct st_federated_share {
|
||||
/*
|
||||
remote host info, parse_url supplies
|
||||
*/
|
||||
char *server_name;
|
||||
char *connection_string;
|
||||
char *scheme;
|
||||
char *connect_string;
|
||||
char *hostname;
|
||||
@ -60,8 +65,9 @@ typedef struct st_federated_share {
|
||||
char *table;
|
||||
char *socket;
|
||||
char *sport;
|
||||
int share_key_length;
|
||||
ushort port;
|
||||
uint table_name_length, connect_string_length, use_count;
|
||||
uint table_name_length, server_name_length, connect_string_length, use_count;
|
||||
pthread_mutex_t mutex;
|
||||
THR_LOCK lock;
|
||||
} FEDERATED_SHARE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user