summaryrefslogtreecommitdiff
path: root/storage/federated
diff options
context:
space:
mode:
authorunknown <patg@govinda.patg.net>2006-12-08 22:30:18 -0500
committerunknown <patg@govinda.patg.net>2006-12-08 22:30:18 -0500
commit00080b90f7dee841732c8e740c580bd35be7f963 (patch)
treed4e2024ed0a048aebabc053293f04f67c25d5a55 /storage/federated
parent9e82f299e526ceafd0deb105f0487681406b1be8 (diff)
parent715e63ae98d12d7b4121f3499739e9852a37907b (diff)
downloadmariadb-git-00080b90f7dee841732c8e740c580bd35be7f963.tar.gz
Merge pgalbraith@bk-internal.mysql.com:/home/bk/mysql-5.1-arch
into govinda.patg.net:/home/patg/mysql-build/mysql-5.1-arch-wl3031-merge mysql-test/lib/init_db.sql: Auto merged mysql-test/r/1st.result: Auto merged mysql-test/r/connect.result: Auto merged mysql-test/r/information_schema.result: Auto merged mysql-test/r/mysql.result: Auto merged mysql-test/r/mysqlcheck.result: Auto merged mysql-test/r/show_check.result: Auto merged mysql-test/r/system_mysql_db.result: Auto merged scripts/mysql_create_system_tables.sh: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/share/errmsg.txt: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged storage/federated/ha_federated.cc: Auto merged mysql-test/r/sp.result: WL# 3031 More fun with error codes. These error codes vary in the result files because new error codes have been added mysql-test/r/sp_gis.result: WL# 3031 More fun with error codes. These error codes vary in the result files because new error codes have been added
Diffstat (limited to 'storage/federated')
-rw-r--r--storage/federated/ha_federated.cc310
-rw-r--r--storage/federated/ha_federated.h8
2 files changed, 231 insertions, 87 deletions
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 7330a19b791..397922e6e51 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -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, (long unsigned int) 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,77 @@ 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", (long unsigned int) 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;
+
+ share->port= server->port ? server->port : MYSQL_PORT;
+
+ if (server->host)
+ share->hostname= server->host;
+ if (server->socket)
+ share->socket= server->socket;
+ else if (strcmp(share->hostname, my_localhost) == 0)
+ share->socket= my_strdup(MYSQL_UNIX_ADDR, MYF(0));
+ 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 %s", 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 +648,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 +700,126 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
share->port= 0;
share->socket= 0;
+ DBUG_PRINT("info", ("share at %lx", (long unsigned int) 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->connect_string_length= table->s->connect_string.length;
- DBUG_PRINT("info",("parse_url alloced share->scheme 0x%lx", (long) 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;
+ share->connection_string= my_strndup((const byte*)table->s->
+ connect_string.str,
+ table->s->connect_string.length,
+ MYF(0));
+
+ // 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->connection_string %lx",
+ (long unsigned int) share->connection_string));
+
+ 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, ';')))
+ {
- if (!(share->hostname= strchr(share->username, '@')))
- goto error;
-
- share->username[share->hostname - share->username]= '\0';
- share->hostname++;
+ DBUG_PRINT("info",
+ ("share->connection_string %s internal format \
+ share->connection_string %lx",
+ share->connection_string,
+ (long unsigned int) share->connection_string));
- 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, '@')))
+ 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;
+ {
+ 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",
+ (long unsigned int) share->scheme));
- /* make sure there isn't an extra / or @ */
- if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
- goto error;
+ /*
+ 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 (!(share->database= strchr(share->hostname, '/')))
- goto error;
- share->hostname[share->database - share->hostname]= '\0';
- share->database++;
+ if (strcmp(share->scheme, "mysql") != 0)
+ goto error;
- if ((share->sport= strchr(share->hostname, ':')))
- {
- share->hostname[share->sport - share->hostname]= '\0';
- share->sport++;
- if (share->sport[0] == '\0')
- share->sport= NULL;
+ 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;
- if (!(share->table_name= strchr(share->database, '/')))
- goto error;
- share->database[share->table_name - share->database]= '\0';
- share->table_name++;
+ /* make sure there isn't an extra / or @ */
+ if ((strchr(share->username, '/')) || (strchr(share->hostname, '@')))
+ goto error;
- share->table_name_length= strlen(share->table_name);
-
- /* make sure there's not an extra / */
- if ((strchr(share->table_name, '/')))
- goto error;
+ if (!(share->database= strchr(share->hostname, '/')))
+ goto error;
+ share->hostname[share->database - share->hostname]= '\0';
+ share->database++;
- if (share->hostname[0] == '\0')
- share->hostname= NULL;
+ 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->port)
{
if (strcmp(share->hostname, my_localhost) == 0)
@@ -702,7 +830,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 +841,6 @@ error:
DBUG_RETURN(parse_url_error(share, table, error_num));
}
-
/*****************************************************************************
** FEDERATED tables
*****************************************************************************/
@@ -1313,14 +1440,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 "));
@@ -1367,7 +1496,8 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
error:
pthread_mutex_unlock(&federated_mutex);
- my_free((gptr) tmp_share.scheme, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((gptr) tmp_share.connection_string, MYF(MY_ALLOW_ZERO_PTR));
+ tmp_share.connection_string= 0;
my_free((gptr) share, MYF(MY_ALLOW_ZERO_PTR));
return NULL;
}
@@ -1387,8 +1517,14 @@ 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 +2833,9 @@ 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));
+ /* free this because strdup created it in parse_url */
+ my_free((gptr) tmp_share.connection_string, MYF(MY_ALLOW_ZERO_PTR));
+ tmp_share.connection_string= 0;
DBUG_RETURN(retval);
}
diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h
index d1b485d63e2..63399e71bcd 100644
--- a/storage/federated/ha_federated.h
+++ b/storage/federated/ha_federated.h
@@ -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;