summaryrefslogtreecommitdiff
path: root/storage/federated
diff options
context:
space:
mode:
authorunknown <acurtis/antony@xiphis.org/ltamd64.xiphis.org>2007-03-24 01:18:19 -0700
committerunknown <acurtis/antony@xiphis.org/ltamd64.xiphis.org>2007-03-24 01:18:19 -0700
commit99c5c28c3cc9eb417f4ca12f606c5abcf6b02a19 (patch)
treef23ab8b69e00d10ca3921fb21bb3cc8904908d19 /storage/federated
parentcb5b56c8efc1752d6768547a6f0517455cdbe7e2 (diff)
downloadmariadb-git-99c5c28c3cc9eb417f4ca12f606c5abcf6b02a19.tar.gz
BUG#26257 New Federated Server Functionality Doesn't support differently named tables
* Modified Federated memory allocation to use MEM_ROOT * Modified sql_servers and federated to allocate share connection parameters to use MEM_ROOT * Modified Federated to allow tablename in addition to server name * Implicit flushing of tables using altered/dropped server name * Added tests to prove new functionality works Contributors to this patch: Patrick Galbraith, Antony Curtis mysql-test/r/federated_server.result: BUG #26257 New Federated Server Functionality Doesn't support differently named tables New test results mysql-test/t/federated_server.test: BUG #26257 New Federated Server Functionality Doesn't support differently named tables New test which ensures that one can use the new 'create server' functionality and have tables point to the correct table, using CONNECTION='server', CONNECTION="server/tablename" and CONNECTION="mysql://...url" sql/mysql_priv.h: BUG #26257 New Federated Server Functionality Doesn't support differently named tables new function: close_cached_connection_tables() sql/sql_base.cc: BUG #26257 New Federated Server Functionality Doesn't support differently named tables new function: close_cached_connection_tables() closes all open tables which match connection string provides functionality to allow flushing of altered/dropped server names. sql/sql_servers.cc: BUG #26257 New Federated Server Functionality Doesn't support differently named tables * Added function clone_server() to allocate a new server for use by get_server_by_name() when creating a federated table * Now using MEM_ROOT allocation (mark and sweep) to account for meta data parameters being allocated properly, particularly with regards to to SERVER object. Also cleans up code allocating share. * Tables using the old definition of server name are now flushed on successful execution of ALTER/DROP SERVER. style: fixed some line-wrapping sql/sql_servers.h: BUG #26257 New Federated Server Functionality Doesn't support differently named tables * change in prototype to get_server_by_name() caller can now provide mem_root which strings will be copied in to. storage/federated/ha_federated.cc: BUG #26257 New Federated Server Functionality Doesn't support differently named tables * Simplified share and share member memory allocaton to use MEM_ROOT * Modified parse_url to parse table names along with server names storage/federated/ha_federated.h: BUG #26257 New Federated Server Functionality Doesn't support differently named tables * Added MEM_ROOT share member
Diffstat (limited to 'storage/federated')
-rw-r--r--storage/federated/ha_federated.cc256
-rw-r--r--storage/federated/ha_federated.h3
2 files changed, 158 insertions, 101 deletions
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 14ffe5da984..e60dc47f48c 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -43,23 +43,55 @@
The create table will simply create the .frm file, and within the
"CREATE TABLE" SQL, there SHALL be any of the following :
- comment=scheme://username:password@hostname:port/database/tablename
- comment=scheme://username@hostname/database/tablename
- comment=scheme://username:password@hostname/database/tablename
- comment=scheme://username:password@hostname/database/tablename
+ connection=scheme://username:password@hostname:port/database/tablename
+ connection=scheme://username@hostname/database/tablename
+ connection=scheme://username:password@hostname/database/tablename
+ connection=scheme://username:password@hostname/database/tablename
+
+ - OR -
+
+ As of 5.1 (See worklog #3031), federated now allows you to use a non-url
+ format, taking advantage of mysql.servers:
+
+ connection="connection_one"
+ connection="connection_one/table_foo"
An example would be:
- comment=mysql://username:password@hostname:port/database/tablename
+ connection=mysql://username:password@hostname:port/database/tablename
- ***IMPORTANT***
+ or, if we had:
+
+ create server 'server_one' foreign data wrapper 'mysql' options
+ (HOST '127.0.0.1',
+ DATABASE 'db1',
+ USER 'root',
+ PASSWORD '',
+ PORT 3306,
+ SOCKET '',
+ OWNER 'root');
+
+ CREATE TABLE federated.t1 (
+ `id` int(20) NOT NULL,
+ `name` varchar(64) NOT NULL default ''
+ )
+ ENGINE="FEDERATED" DEFAULT CHARSET=latin1
+ CONNECTION='server_one';
+
+ So, this will have been the equivalent of
- This is a first release, conceptual release
- Only 'mysql://' is supported at this release.
+ CONNECTION="mysql://root@127.0.0.1:3306/db1/t1"
+ Then, we can also change the server to point to a new schema:
- This comment connection string is necessary for the handler to be
- able to connect to the foreign server.
+ ALTER SERVER 'server_one' options(DATABASE 'db2');
+
+ All subsequent calls will now be against db2.t1! Guess what? You don't
+ have to perform an alter table!
+
+ This connecton="connection string" is necessary for the handler to be
+ able to connect to the foreign server, either by URL, or by server
+ name.
The basic flow is this:
@@ -166,7 +198,7 @@
KEY other_key (other))
ENGINE="FEDERATED"
DEFAULT CHARSET=latin1
- COMMENT='root@127.0.0.1:9306/federated/test_federated';
+ CONNECTION='mysql://root@127.0.0.1:9306/federated/test_federated';
Notice the "COMMENT" and "ENGINE" field? This is where you
respectively set the engine type, "FEDERATED" and foreign
@@ -263,7 +295,7 @@
To run these tests, go into ./mysql-test (based in the directory you
built the server in)
- ./mysql-test-run federatedd
+ ./mysql-test-run federated
To run the test, or if you want to run the test and have debug info:
@@ -311,7 +343,7 @@
-------------
These were the files that were modified or created for this
- Federated handler to work:
+ Federated handler to work, in 5.0:
./configure.in
./sql/Makefile.am
@@ -329,6 +361,13 @@
./sql/ha_federated.cc
./sql/ha_federated.h
+ In 5.1
+
+ my:~/mysql-build/mysql-5.1-bkbits patg$ ls storage/federated/
+ CMakeLists.txt Makefile.in ha_federated.h plug.in
+ Makefile SCCS libfederated.a
+ Makefile.am ha_federated.cc libfederated_a-ha_federated.o
+
*/
@@ -547,42 +586,39 @@ 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->connection_string)
- {
- DBUG_PRINT("info",
- ("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);
strmake(buf, table->s->connect_string.str, buf_len);
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 get_connection(MEM_ROOT *mem_root, FEDERATED_SHARE *share)
{
int error_num= ER_FOREIGN_SERVER_DOESNT_EXIST;
char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
- FOREIGN_SERVER *server;
+ FOREIGN_SERVER *server, server_buffer;
DBUG_ENTER("ha_federated::get_connection");
+ /*
+ get_server_by_name() clones the server if exists and allocates
+ copies of strings in the supplied mem_root
+ */
if (!(server=
- get_server_by_name(share->connection_string)))
+ get_server_by_name(mem_root, share->connection_string, &server_buffer)))
{
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));
+ 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
@@ -591,29 +627,22 @@ int get_connection(FEDERATED_SHARE *share)
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 ? (ushort) 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;
+ share->server_name_length= server->server_name_length;
+ share->server_name= server->server_name;
+ share->username= server->username;
+ share->password= server->password;
+ share->database= server->db;
+#ifndef I_AM_PARANOID
+ share->port= server->port > 0 && server->port < 65536 ?
+#else
+ share->port= server->port > 1023 && server->port < 65536 ?
+#endif
+ (ushort) server->port : MYSQL_PORT;
+ share->hostname= server->host;
+ if (!(share->socket= server->socket) &&
+ !strcmp(share->hostname, my_localhost))
+ share->socket= (char *) MYSQL_UNIX_ADDR;
+ share->scheme= server->scheme;
DBUG_PRINT("info", ("share->username %s", share->username));
DBUG_PRINT("info", ("share->password %s", share->password));
@@ -636,6 +665,7 @@ error:
SYNOPSIS
parse_url()
+ mem_root MEM_ROOT pointer for memory allocation
share pointer to FEDERATED share
table pointer to current TABLE class
table_create_flag determines what error to throw
@@ -685,7 +715,7 @@ error:
*/
-static int parse_url(FEDERATED_SHARE *share, TABLE *table,
+static int parse_url(MEM_ROOT *mem_root, FEDERATED_SHARE *share, TABLE *table,
uint table_create_flag)
{
uint error_num= (table_create_flag ?
@@ -699,20 +729,19 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
DBUG_PRINT("info", ("Length: %d", table->s->connect_string.length));
DBUG_PRINT("info", ("String: '%.*s'", table->s->connect_string.length,
table->s->connect_string.str));
- share->connection_string= my_strndup(table->s->connect_string.str,
- table->s->connect_string.length,
- MYF(0));
+ share->connection_string= strmake_root(mem_root, table->s->connect_string.str,
+ table->s->connect_string.length);
- // 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, ';')))
+ /*
+ No :// or @ in connection string. Must be a straight connection name of
+ either "servername" or "servername/tablename"
+ */
+ if ( (!strstr(share->connection_string, "://") &&
+ (!strchr(share->connection_string, '@'))))
{
DBUG_PRINT("info",
@@ -721,17 +750,51 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
share->connection_string,
(long unsigned int) share->connection_string));
+ /* ok, so we do a little parsing, but not completely! */
share->parsed= FALSE;
- if ((error_num= get_connection(share)))
- goto error;
+ /*
+ If there is a single '/' in the connection string, this means the user is
+ specifying a table name
+ */
+
+ if ((share->table_name= strchr(share->connection_string, '/')))
+ {
+ share->connection_string[share->table_name - share->connection_string]= '\0';
+ share->table_name++;
+ share->table_name_length= strlen(share->table_name);
+ DBUG_PRINT("info",
+ ("internal format, parsed table_name share->connection_string \
+ %s share->table_name %s",
+ share->connection_string, share->table_name));
+
+ /*
+ there better not be any more '/'s !
+ */
+ if (strchr(share->table_name, '/'))
+ goto error;
+
+ }
/*
- connection specifies everything but, resort to
- expecting remote and foreign table names to match
+ otherwise, straight server name, use tablename of federated table
+ as remote table name
*/
- 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
+ {
+ /*
+ connection specifies everything but, resort to
+ expecting remote and foreign table names to match
+ */
+ share->table_name= strmake_root(mem_root, table->s->table_name.str,
+ (share->table_name_length= table->s->table_name.length));
+ DBUG_PRINT("info",
+ ("internal format, default table_name share->connection_string \
+ %s share->table_name %s",
+ share->connection_string, share->table_name));
+ }
+
+ if ((error_num= get_connection(mem_root, share)))
+ goto error;
}
else
{
@@ -817,7 +880,7 @@ Then password is a null string, so set to NULL
if (!share->port)
{
if (strcmp(share->hostname, my_localhost) == 0)
- share->socket= my_strdup(MYSQL_UNIX_ADDR, MYF(0));
+ share->socket= (char *) MYSQL_UNIX_ADDR;
else
share->port= MYSQL_PORT;
}
@@ -1421,22 +1484,26 @@ err:
static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
{
- char *select_query;
char query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
Field **field;
String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
FEDERATED_SHARE *share= NULL, tmp_share;
+ MEM_ROOT mem_root;
+ DBUG_ENTER("ha_federated.cc::get_share");
+
/*
In order to use this string, we must first zero it's length,
or it will contain garbage
*/
query.length(0);
+ init_alloc_root(&mem_root, 256, 0);
+
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))
+ if (parse_url(&mem_root, &tmp_share, table, 0))
goto error;
/* TODO: change tmp_share.scheme to LEX_STRING object */
@@ -1457,24 +1524,17 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
query.length(query.length() - sizeof_trailing_comma);
query.append(STRING_WITH_LEN(" FROM `"));
+ query.append(tmp_share.table_name, tmp_share.table_name_length);
+ query.append(STRING_WITH_LEN("`"));
+ DBUG_PRINT("info", ("calling alloc_root"));
- if (!(share= (FEDERATED_SHARE *)
- my_multi_malloc(MYF(MY_WME),
- &share, sizeof(*share),
- &select_query,
- query.length()+table->s->connect_string.length+1,
- NullS)))
+ if (!(share= (FEDERATED_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) ||
+ !(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length())))
goto error;
- memcpy(share, &tmp_share, sizeof(tmp_share));
-
- share->table_name_length= strlen(share->table_name);
- /* TODO: share->table_name to LEX_STRING object */
- query.append(share->table_name, share->table_name_length);
- query.append(STRING_WITH_LEN("`"));
- share->select_query= select_query;
- strmov(share->select_query, query.ptr());
share->use_count= 0;
+ share->mem_root= mem_root;
+
DBUG_PRINT("info",
("share->select_query %s", share->select_query));
@@ -1483,17 +1543,18 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
thr_lock_init(&share->lock);
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
}
+ else
+ free_root(&mem_root, MYF(0)); /* prevents memory leak */
+
share->use_count++;
pthread_mutex_unlock(&federated_mutex);
- return share;
+ DBUG_RETURN(share);
error:
pthread_mutex_unlock(&federated_mutex);
- 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;
+ free_root(&mem_root, MYF(0));
+ DBUG_RETURN(NULL);
}
@@ -1505,23 +1566,16 @@ error:
static int free_share(FEDERATED_SHARE *share)
{
+ MEM_ROOT mem_root= share->mem_root;
DBUG_ENTER("free_share");
pthread_mutex_lock(&federated_mutex);
if (!--share->use_count)
{
hash_delete(&federated_open_tables, (byte*) share);
- 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));
+ free_root(&mem_root, MYF(0));
}
pthread_mutex_unlock(&federated_mutex);
@@ -1590,6 +1644,8 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
mysql_options(mysql,MYSQL_SET_CHARSET_NAME,
this->table->s->table_charset->csname);
+ DBUG_PRINT("info", ("calling mysql_real_connect hostname %s user %s",
+ share->hostname, share->username));
if (!mysql || !mysql_real_connect(mysql,
share->hostname,
share->username,
@@ -2832,15 +2888,13 @@ int ha_federated::create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info)
{
int retval;
+ THD *thd= current_thd;
FEDERATED_SHARE tmp_share; // Only a temporary share, to test the url
DBUG_ENTER("ha_federated::create");
- if (!(retval= parse_url(&tmp_share, table_arg, 1)))
+ if (!(retval= parse_url(thd->mem_root, &tmp_share, table_arg, 1)))
retval= check_foreign_data_source(&tmp_share, 1);
- /* 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 bbc2b2fe9f8..4d2eefdd986 100644
--- a/storage/federated/ha_federated.h
+++ b/storage/federated/ha_federated.h
@@ -43,6 +43,8 @@
The example implements the minimum of what you will probably need.
*/
typedef struct st_federated_share {
+ MEM_ROOT mem_root;
+
bool parsed;
/* this key is unique db/tablename */
const char *share_key;
@@ -67,6 +69,7 @@ typedef struct st_federated_share {
char *sport;
int share_key_length;
ushort port;
+
uint table_name_length, server_name_length, connect_string_length, use_count;
pthread_mutex_t mutex;
THR_LOCK lock;