summaryrefslogtreecommitdiff
path: root/storage/federated
diff options
context:
space:
mode:
authorunknown <istruewing@chilla.local>2007-03-28 16:57:08 +0200
committerunknown <istruewing@chilla.local>2007-03-28 16:57:08 +0200
commit74519b983535c4b87d916f5ee9f8749a7102c7e2 (patch)
treec2b36b7f679b07fb2f46dabe5c0301204531c5b8 /storage/federated
parent8f93150d20e9af978c43deb4f90cc21457bd29db (diff)
parent548aad2578670f1ad9af2efa38f9a4d63f535810 (diff)
downloadmariadb-git-74519b983535c4b87d916f5ee9f8749a7102c7e2.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-engines
into chilla.local:/home/mydev/mysql-5.1-axmrg sql/mysql_priv.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_servers.h: Auto merged storage/federated/ha_federated.cc: Auto merged storage/heap/ha_heap.cc: Auto merged storage/myisam/ha_myisam.cc: Auto merged sql/sql_servers.cc: Manual merge
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 441c1785e74..aa7184268f5 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
+
*/
@@ -546,42 +585,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
@@ -590,29 +626,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));
@@ -635,6 +664,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
@@ -684,7 +714,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 ?
@@ -698,20 +728,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",
@@ -720,17 +749,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
{
@@ -816,7 +879,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;
}
@@ -1420,22 +1483,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 */
@@ -1456,24 +1523,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));
@@ -1482,17 +1542,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);
}
@@ -1504,23 +1565,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);
@@ -1589,6 +1643,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,
@@ -2831,15 +2887,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;