diff options
author | unknown <istruewing@chilla.local> | 2007-03-28 16:57:08 +0200 |
---|---|---|
committer | unknown <istruewing@chilla.local> | 2007-03-28 16:57:08 +0200 |
commit | 74519b983535c4b87d916f5ee9f8749a7102c7e2 (patch) | |
tree | c2b36b7f679b07fb2f46dabe5c0301204531c5b8 /storage/federated | |
parent | 8f93150d20e9af978c43deb4f90cc21457bd29db (diff) | |
parent | 548aad2578670f1ad9af2efa38f9a4d63f535810 (diff) | |
download | mariadb-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.cc | 256 | ||||
-rw-r--r-- | storage/federated/ha_federated.h | 3 |
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; |