From 6016f23f75de1c35bd8e2a3815aaf70281a1a3a2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 6 Feb 2005 09:40:07 -0800 Subject: [PATCH 01/20] WL# 2094 This patch contains all that my previous patch (1.1814) contained, with the addition of using cli_fetch_lengths for handling binary data (Bar noted this on the review of 1.1814, Guilhem suggested using cli_fetch_lenghts by making available via removal of static in method definition and declaration in mysql.h, but Konstantin had some reservations, but he said to commit the patch using this anyway, and I suppose this can be discussed. I abandoned 1.1814 because Monty made a couple fixes to my code as well as formatting changes, and I thought it would just be easier to hand-edit my changes into a fresh clone and then make a patch. The reason for using cli_fetch_lengths is so that I can correctly get the length of the field I am setting into the field. I was previously using 'strlen' but Bar pointed out this won't correctly get the length of binary data and is also less effecient. Upon testing, it was in fact verified that binary data in a blob table was being inserted correctly, but not being retrieved correctly, all due to not having the correct value for the field: (*field)->store(row[x], strlen(row[x]), &my_charset_bin); was changed to: (*field)->store(row[x], lengths[x], &my_charset_bin); lengths being a unsigned long pointer to the values of the field lengths from a MYSQL_ROW. Since the server doesn't have the function "mysql_fetch_lengths" available, I tried to use "result->lengths", but this isn't set, so I finally successfully used cli_fetch_lenghts, which does give the correct lengths, and now the binary data gets retrieved correctly. I've also run the code through indent-ex and am using Brian's vimrc to ensure correct formatting! This code passes the entire test suite, without any errors or warning on both my workstation and build.mysql.com include/mysql.h: added cli_fetch_lengths to mysql.h in order to use this function in the federated handler mysql-test/r/federated.result: - Moved countries to be created and inserted prior to federated test table - Added a test of inserting binary values into a blob table mysql-test/t/federated.test: - Moved order of countries table creation to prior to test table creation - Test insertion of binary values in a blob table sql-common/client.c: removed 'static' to allow cli_fetch_lengths to be used in the federated handler sql/ha_federated.cc: 1. share->scheme that was created in parse_url was not being freed 2. HASH federated_open_tables was being deleted, but not freed 3. 'result' from mysql_store_result was not being free in several instances 4. Fixed the problem where a table scan was being performed after index_read_idx, which didn't cause a problem because the result set from idx_read_idx was not being freed, but once the result set was properly freed, it broke update_row. Now, I'm using the bool 'scan' to determine if I need to perform a table scan, which it magically is false when the query is an update with an index. 5. Changed all stings containing the query to perform in mysql_real_query calls from string.c_ptr_quick() to string.ptr() per Monty's suggestion (better performance) 6. Fixed various cast/type/truth compile warnings. 7. Removed 'load_conn_info' and just let 'parse_url' handle it. 8. Added the use of cli_fetch_lengths, needed to fix binary values being retrieved from the database in rnd_next/convert_row_to_internal_format 9. Formatting changes by using indent-ex! sql/ha_federated.h: added scan flag, setting defaults for result and scan_flag --- include/mysql.h | 2 + mysql-test/r/federated.result | 26 +- mysql-test/t/federated.test | 33 +- sql-common/client.c | 2 +- sql/ha_federated.cc | 698 +++++++++++++++++++--------------- sql/ha_federated.h | 3 +- 6 files changed, 432 insertions(+), 332 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index b87b865608e..e37cf710817 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -499,6 +499,8 @@ MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset); MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); +void STDCALL cli_fetch_lengths(ulong *to, MYSQL_ROW column, + unsigned int field_count); MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, const char *wild); diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 4ed0b45a4c5..d1ad9921865 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -644,14 +644,19 @@ select * from federated.t1 where fileguts = 'jimbob'; id code fileguts creation_date entered_time 3 DEUEUEUEUEUEUEUEUEU jimbob 2004-04-04 04:04:04 2004-04-04 04:04:04 drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id)); +CREATE TABLE federated.t1 (a BLOB); drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, country_id, other) values ('Kumar', 1, 11111); -insert into federated.t1 (name, country_id, other) values ('Lenz', 2, 22222); -insert into federated.t1 (name, country_id, other) values ('Marizio', 3, 33333); -insert into federated.t1 (name, country_id, other) values ('Monty', 4, 33333); -insert into federated.t1 (name, country_id, other) values ('Sanja', 5, 33333); +CREATE TABLE federated.t1 (a BLOB) ENGINE="FEDERATED" COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +INSERT INTO federated.t1 VALUES (0x00); +INSERT INTO federated.t1 VALUES (0x0001); +INSERT INTO federated.t1 VALUES (0x0100); +SELECT HEX(a) FROM federated.t1; +HEX(a) +00 +0001 +0100 +drop table if exists federated.t1; +CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id)); drop table if exists federated.countries; Warnings: Note 1051 Unknown table 'countries' @@ -661,6 +666,13 @@ insert into federated.countries (country) values ('Germany'); insert into federated.countries (country) values ('Italy'); insert into federated.countries (country) values ('Finland'); insert into federated.countries (country) values ('Ukraine'); +drop table if exists federated.t1; +CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +insert into federated.t1 (name, country_id, other) values ('Kumar', 1, 11111); +insert into federated.t1 (name, country_id, other) values ('Lenz', 2, 22222); +insert into federated.t1 (name, country_id, other) values ('Marizio', 3, 33333); +insert into federated.t1 (name, country_id, other) values ('Monty', 4, 33333); +insert into federated.t1 (name, country_id, other) values ('Sanja', 5, 33333); select federated.t1.*, federated.countries.country from federated.t1 left join federated.countries on federated.t1.country_id = federated.countries.id; id country_id name other country 1 1 Kumar 11111 India diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 413509a0a6a..c634badf04e 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -522,8 +522,22 @@ insert into federated.t1 (code, fileguts, creation_date) values ('ASDFWERQWETWET insert into federated.t1 (code, fileguts, creation_date) values ('DEUEUEUEUEUEUEUEUEU', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2004-04-04 04:04:04'); insert into federated.t1 (code, fileguts, creation_date) values ('DEUEUEUEUEUEUEUEUEU', 'jimbob', '2004-04-04 04:04:04'); select * from federated.t1; -select * from federated.t1 where fileguts = 'jimbob'; # test blob indexes +select * from federated.t1 where fileguts = 'jimbob'; + +# test blob with binary +connection slave; +drop table if exists federated.t1; +CREATE TABLE federated.t1 (a BLOB); + +connection master; +drop table if exists federated.t1; +CREATE TABLE federated.t1 (a BLOB) ENGINE="FEDERATED" COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +INSERT INTO federated.t1 VALUES (0x00); +INSERT INTO federated.t1 VALUES (0x0001); +INSERT INTO federated.t1 VALUES (0x0100); +SELECT HEX(a) FROM federated.t1; + # TODO # @@ -559,15 +573,6 @@ drop table if exists federated.t1; CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id)); connection master; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, country_id, other) values ('Kumar', 1, 11111); -insert into federated.t1 (name, country_id, other) values ('Lenz', 2, 22222); -insert into federated.t1 (name, country_id, other) values ('Marizio', 3, 33333); -insert into federated.t1 (name, country_id, other) values ('Monty', 4, 33333); -insert into federated.t1 (name, country_id, other) values ('Sanja', 5, 33333); - - drop table if exists federated.countries; CREATE TABLE federated.countries ( `id` int(20) NOT NULL auto_increment, `country` varchar(32), primary key (id)); insert into federated.countries (country) values ('India'); @@ -576,6 +581,14 @@ insert into federated.countries (country) values ('Italy'); insert into federated.countries (country) values ('Finland'); insert into federated.countries (country) values ('Ukraine'); +drop table if exists federated.t1; +CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +insert into federated.t1 (name, country_id, other) values ('Kumar', 1, 11111); +insert into federated.t1 (name, country_id, other) values ('Lenz', 2, 22222); +insert into federated.t1 (name, country_id, other) values ('Marizio', 3, 33333); +insert into federated.t1 (name, country_id, other) values ('Monty', 4, 33333); +insert into federated.t1 (name, country_id, other) values ('Sanja', 5, 33333); + select federated.t1.*, federated.countries.country from federated.t1 left join federated.countries on federated.t1.country_id = federated.countries.id; drop table federated.countries; diff --git a/sql-common/client.c b/sql-common/client.c index 9dcf6b3e32c..3d760c73eea 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1121,7 +1121,7 @@ void mysql_read_default_options(struct st_mysql_options *options, else the lengths are calculated from the offset between pointers. **************************************************************************/ -static void cli_fetch_lengths(ulong *to, MYSQL_ROW column, +void cli_fetch_lengths(ulong *to, MYSQL_ROW column, unsigned int field_count) { ulong *prev_length; diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 695c71677c0..eed145203c3 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -343,10 +343,10 @@ ./sql/ha_federated.cc ./sql/ha_federated.h -*/ +*/ #ifdef __GNUC__ -#pragma implementation // gcc: Class implementation +#pragma implementation // gcc: Class implementation #endif #include @@ -355,18 +355,21 @@ #include "ha_federated.h" #define MAX_REMOTE_SIZE IO_SIZE /* Variables for federated share methods */ -static HASH federated_open_tables; // Hash used to track open tables -pthread_mutex_t federated_mutex; // This is the mutex we use to init the hash -static int federated_init= 0; // Variable for checking the init state of hash +static HASH federated_open_tables; // Hash used to track open + // tables +pthread_mutex_t federated_mutex; // This is the mutex we use to + // init the hash +static int federated_init= 0; // Variable for checking the + // init state of hash /* Function we use in the creation of our hash to get key. */ -static byte* federated_get_key(FEDERATED_SHARE *share,uint *length, - my_bool not_used __attribute__((unused))) +static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, + my_bool not_used __attribute__ ((unused))) { *length= share->table_name_length; - return (byte*) share->table_name; + return (byte *) share->table_name; } /* @@ -374,8 +377,9 @@ static byte* federated_get_key(FEDERATED_SHARE *share,uint *length, SYNOPSIS parse_url() - share pointer to FEDERATED share - table pointer to current TABLE class + share pointer to FEDERATED share + table pointer to current TABLE class + table_create_flag determines what error to throw DESCRIPTION populates the share with information about the connection @@ -385,10 +389,10 @@ static byte* federated_get_key(FEDERATED_SHARE *share,uint *length, 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 + scheme://username:password@hostname:port/database/table + scheme://username@hostname/database/table + scheme://username@hostname:port/database/table + scheme://username:password@hostname/database/table An Example: @@ -401,33 +405,34 @@ scheme://username:password@hostname/database/table RETURN VALUE 0 success - -1 failure, wrong string format + 1 failure, wrong string format */ -static int parse_url(FEDERATED_SHARE *share, TABLE *table, uint table_create_flag) +static int parse_url(FEDERATED_SHARE *share, TABLE *table, + uint table_create_flag) { DBUG_ENTER("ha_federated::parse_url"); // This either get set or will remain the same. share->port= 0; - uint error_num= table_create_flag ? ER_CANT_CREATE_TABLE : ER_CONNECT_TO_MASTER ; + uint error_num= table_create_flag ? ER_CANT_CREATE_TABLE : + ER_CONNECT_TO_MASTER; share->scheme= my_strdup(table->s->comment, MYF(0)); - if ((share->username= strstr(share->scheme, "://"))) { - share->scheme[share->username - share->scheme] = '\0'; + share->scheme[share->username - share->scheme]= '\0'; if (strcmp(share->scheme, "mysql") != 0) { DBUG_PRINT("ha_federated::parse_url", ("The federated handler currently only supports connecting\ to a MySQL database!!!\n")); my_error(error_num, MYF(0), - "ERROR: federated handler only supports remote 'mysql://' database"); - DBUG_RETURN(-1); + "ERROR: federated handler only supports remote 'mysql://' database"); + DBUG_RETURN(1); } - share->username+= 3; + share->username += 3; if ((share->hostname= strchr(share->username, '@'))) { @@ -445,14 +450,14 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, uint table_create_fla DBUG_PRINT("ha_federated::parse_url", ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(-1); + "this connection string is not in the correct format!!!\n"); + DBUG_RETURN(1); } /* - Found that if the string is: -user:@hostname:port/database/table -Then password is a null string, so set to NULL - */ + Found that if the string is: + user:@hostname:port/database/table + Then password is a null string, so set to NULL + */ if ((share->password[0] == '\0')) share->password= NULL; } @@ -465,8 +470,8 @@ Then password is a null string, so set to NULL DBUG_PRINT("ha_federated::parse_url", ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(-1); + "this connection string is not in the correct format!!!\n"); + DBUG_RETURN(1); } if ((share->database= strchr(share->hostname, '/'))) @@ -494,8 +499,8 @@ Then password is a null string, so set to NULL DBUG_PRINT("ha_federated::parse_url", ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(-1); + "this connection string is not in the correct format!!!\n"); + DBUG_RETURN(1); } } else @@ -503,8 +508,8 @@ Then password is a null string, so set to NULL DBUG_PRINT("ha_federated::parse_url", ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(-1); + "this connection string is not in the correct format!!!\n"); + DBUG_RETURN(1); } // make sure there's not an extra / if ((strchr(share->table_base_name, '/'))) @@ -512,34 +517,40 @@ Then password is a null string, so set to NULL DBUG_PRINT("ha_federated::parse_url", ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(-1); + "this connection string is not in the correct format!!!\n"); + DBUG_RETURN(1); } if (share->hostname[0] == '\0') share->hostname= NULL; - DBUG_PRINT("ha_federated::parse_url", - ("scheme %s username %s password %s \ - hostname %s port %d database %s tablename %s\n", - share->scheme, share->username, share->password, share->hostname, - share->port, share->database, share->table_base_name)); + if (!share->port) + { + if (strcmp(share->hostname, "localhost") == 0) + share->socket= my_strdup("/tmp/mysql.sock", MYF(0)); + else + share->port= 3306; + } + + DBUG_PRINT("ha_federated::parse_url", + ("scheme %s username %s password %s \ + hostname %s port %d database %s tablename %s\n", share->scheme, share->username, share->password, share->hostname, share->port, share->database, share->table_base_name)); } else { DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); + ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(-1); + "this connection string is not in the correct format!!!\n"); + DBUG_RETURN(1); } } else - { + { DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); + ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(-1); + "this connection string is not in the correct format!!!\n"); + DBUG_RETURN(1); } DBUG_RETURN(0); } @@ -564,24 +575,36 @@ Then password is a null string, so set to NULL */ uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) { - unsigned long len; - int x= 0; + unsigned long *lengths; + unsigned int num_fields; + unsigned int x= 0; + DBUG_ENTER("ha_federated::convert_row_to_internal_format"); - // Question this - memset(record, 0, table->s->null_bytes); + num_fields= mysql_num_fields(result); + lengths= (unsigned long*) my_malloc(num_fields * sizeof(unsigned long), + MYF(0)); + cli_fetch_lengths((unsigned long*) (lengths), row, num_fields); - for (Field **field=table->field; *field ; field++, x++) + memset(record, 0, table->s->null_bytes); + + for (Field ** field= table->field; *field; field++, x++) { - if (!row[x]) + if (!row[x]) + { (*field)->set_null(); + } else /* - changed system_charset_info to default_charset_info because - testing revealed that german text was not being retrieved properly + changed system_charset_info to default_charset_info because + testing revealed that german text was not being retrieved properly */ - (*field)->store(row[x], strlen(row[x]), &my_charset_bin); + DBUG_PRINT("ha_federated::convert_row_to_internal_format", + ("row[%d] %s length %lu", x, row[x], lengths[x])); + (*field)->store(row[x], lengths[x], &my_charset_bin); } + my_free((gptr) lengths, MYF(0)); + lengths= 0; DBUG_RETURN(0); } @@ -595,29 +618,30 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, String tmp; DBUG_ENTER("ha_federated::create_where_from_key"); - for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++) + for (key_part= key_info->key_part; (int) key_length > 0; key_part++) { Field *field= key_part->field; needs_quotes= field->needs_quotes(); //bool needs_quotes= type_quote(field->type()); - DBUG_PRINT("ha_federated::create_where_from_key", ("key name %s type %d", field->field_name, field->type())); + DBUG_PRINT("ha_federated::create_where_from_key", + ("key name %s type %d", field->field_name, field->type())); uint length= key_part->length; - if (second_loop++ && to->append(" AND ",5)) + if (second_loop++ && to->append(" AND ", 5)) DBUG_RETURN(1); - if (to->append('`') || to->append(field->field_name) || - to->append("` ",2)) - DBUG_RETURN(1); // Out of memory + if (to->append('`') || to->append(field->field_name) || to->append("` ", 2)) + DBUG_RETURN(1); // Out of memory if (key_part->null_bit) { if (*key++) { - if (to->append("IS NULL",7)) - DBUG_PRINT("ha_federated::create_where_from_key", ("NULL type %s", to->c_ptr_quick())); - DBUG_RETURN(1); - key_length-= key_part->store_length; - key+= key_part->store_length-1; + if (to->append("IS NULL", 7)) + DBUG_PRINT("ha_federated::create_where_from_key", + ("NULL type %s", to->c_ptr_quick())); + DBUG_RETURN(1); + key_length -= key_part->store_length; + key += key_part->store_length - 1; continue; } key_length--; @@ -630,101 +654,81 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, { /* This is can be threated as a hex string */ Field_bit *field= (Field_bit *) (key_part->field); - char buff[64+2], *ptr; - byte *end= (byte *)(key) + length; + char buff[64 + 2], *ptr; + byte *end= (byte *) (key) + length; - buff[0]='0'; - buff[1]='x'; - for (ptr= buff+2 ; key < end ; key++) + buff[0]= '0'; + buff[1]= 'x'; + for (ptr= buff + 2; key < end; key++) { - uint tmp= (uint) (uchar) *key; - *ptr++=_dig_vec_upper[tmp >> 4]; - *ptr++=_dig_vec_upper[tmp & 15]; + uint tmp= (uint) (uchar) * key; + *ptr++= _dig_vec_upper[tmp >> 4]; + *ptr++= _dig_vec_upper[tmp & 15]; } - if (to->append(buff, (uint) (ptr-buff))) + if (to->append(buff, (uint) (ptr - buff))) DBUG_RETURN(1); - DBUG_PRINT("ha_federated::create_where_from_key", ("bit type %s", to->c_ptr_quick())); - key_length-= length; + DBUG_PRINT("ha_federated::create_where_from_key", + ("bit type %s", to->c_ptr_quick())); + key_length -= length; continue; } if (key_part->key_part_flag & HA_BLOB_PART) { uint blob_length= uint2korr(key); - key+= HA_KEY_BLOB_LENGTH; - key_length-= HA_KEY_BLOB_LENGTH; + key += HA_KEY_BLOB_LENGTH; + key_length -= HA_KEY_BLOB_LENGTH; tmp.set_quick((char*) key, blob_length, &my_charset_bin); if (append_escaped(to, &tmp)) DBUG_RETURN(1); - DBUG_PRINT("ha_federated::create_where_from_key", ("blob type %s", to->c_ptr_quick())); + DBUG_PRINT("ha_federated::create_where_from_key", + ("blob type %s", to->c_ptr_quick())); length= key_part->length; } else if (key_part->key_part_flag & HA_VAR_LENGTH_PART) { length= uint2korr(key); - key+= HA_KEY_BLOB_LENGTH; + key += HA_KEY_BLOB_LENGTH; tmp.set_quick((char*) key, length, &my_charset_bin); if (append_escaped(to, &tmp)) DBUG_RETURN(1); - DBUG_PRINT("ha_federated::create_where_from_key", ("varchar type %s", to->c_ptr_quick())); + DBUG_PRINT("ha_federated::create_where_from_key", + ("varchar type %s", to->c_ptr_quick())); } else { - DBUG_PRINT("ha_federated::create_where_from_key", ("else block, unknown type so far")); + DBUG_PRINT("ha_federated::create_where_from_key", + ("else block, unknown type so far")); char buff[MAX_FIELD_WIDTH]; String str(buff, sizeof(buff), field->charset()), *res; - res= field->val_str(&str, (char *)(key)); + res= field->val_str(&str, (char*) (key)); if (field->result_type() == STRING_RESULT) { if (append_escaped(to, res)) DBUG_RETURN(1); - res= field->val_str(&str, (char *)(key)); + res= field->val_str(&str, (char*) (key)); - DBUG_PRINT("ha_federated::create_where_from_key", ("else block, string type", to->c_ptr_quick())); + DBUG_PRINT("ha_federated::create_where_from_key", + ("else block, string type", to->c_ptr_quick())); } else if (to->append(res->ptr(), res->length())) DBUG_RETURN(1); } if (needs_quotes && to->append("'")) DBUG_RETURN(1); - DBUG_PRINT("ha_federated::create_where_from_key", ("final value for 'to' %s", to->c_ptr_quick())); - key+= length; - key_length-= length; + DBUG_PRINT("ha_federated::create_where_from_key", + ("final value for 'to' %s", to->c_ptr_quick())); + key += length; + key_length -= length; DBUG_RETURN(0); } DBUG_RETURN(1); } -int load_conn_info(FEDERATED_SHARE *share, TABLE *table) -{ - DBUG_ENTER("ha_federated::load_conn_info"); - int retcode; - - retcode= parse_url(share, table, 0); - - if (retcode < 0) - { - DBUG_PRINT("ha_federated::load_conn_info", - ("retcode %d, setting defaults", retcode)); - /* sanity checks to make sure all needed pieces are present */ - if (!share->port) - { - if (strcmp(share->hostname, "localhost") == 0) - share->socket= my_strdup("/tmp/mysql.sock",MYF(0)); - else - share->port= 3306; - } - } - DBUG_PRINT("ha_federated::load_conn_info", - ("returned from retcode %d", retcode)); - - DBUG_RETURN(retcode); -} - /* Example of simple lock controls. The "share" it creates is structure we will pass to each federated handler. Do you have to have one of these? Well, you @@ -742,13 +746,13 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) // share->table_name has the file location - we want the actual table's // name! - table_base_name= (char *)table->s->table_name; - DBUG_PRINT("ha_federated::get_share",("table_name %s", table_base_name)); + table_base_name= (char*) table->s->table_name; + DBUG_PRINT("ha_federated::get_share", ("table_name %s", table_base_name)); /* - So why does this exist? There is no way currently to init a storage engine. - Innodb and BDB both have modifications to the server to allow them to - do this. Since you will not want to do this, this is probably the next - best method. + So why does this exist? There is no way currently to init a storage engine. + Innodb and BDB both have modifications to the server to allow them to + do this. Since you will not want to do this, this is probably the next + best method. */ if (!federated_init) { @@ -757,9 +761,9 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) if (!federated_init) { federated_init++; - VOID(pthread_mutex_init(&federated_mutex,MY_MUTEX_INIT_FAST)); - (void) hash_init(&federated_open_tables,system_charset_info,32,0,0, - (hash_get_key) federated_get_key,0,0); + VOID(pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)); + (void) hash_init(&federated_open_tables, system_charset_info, 32, 0, 0, + (hash_get_key) federated_get_key, 0, 0); } pthread_mutex_unlock(&LOCK_mysql_create_db); } @@ -767,41 +771,43 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) table_name_length= (uint) strlen(table_name); table_base_name_length= (uint) strlen(table_base_name); - if (!(share= (FEDERATED_SHARE*) hash_search(&federated_open_tables, - (byte*) table_name, - table_name_length))) + if (!(share= (FEDERATED_SHARE *) hash_search(&federated_open_tables, + (byte *) table_name, + table_name_length))) { query.set_charset(system_charset_info); query.append("SELECT * FROM "); query.append(table_base_name); - + if (!(share= (FEDERATED_SHARE *) my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), &share, sizeof(*share), - &tmp_table_name, table_name_length+1, - &tmp_table_base_name, table_base_name_length+1, - &select_query, query.length()+1, - NullS))) + &tmp_table_name, table_name_length + 1, + &tmp_table_base_name, table_base_name_length + 1, + &select_query, query.length() + 1, NullS))) { pthread_mutex_unlock(&federated_mutex); return NULL; } - load_conn_info(share, table); + if (parse_url(share, table, 0)) + goto error; + share->use_count= 0; share->table_name_length= table_name_length; share->table_name= tmp_table_name; share->table_base_name_length= table_base_name_length; share->table_base_name= tmp_table_base_name; share->select_query= select_query; - strmov(share->table_name,table_name); - strmov(share->table_base_name,table_base_name); - strmov(share->select_query,query.c_ptr_quick()); - DBUG_PRINT("ha_federated::get_share",("share->select_query %s", share->select_query)); - if (my_hash_insert(&federated_open_tables, (byte*) share)) + strmov(share->table_name, table_name); + strmov(share->table_base_name, table_base_name); + strmov(share->select_query, query.ptr()); + DBUG_PRINT("ha_federated::get_share", + ("share->select_query %s", share->select_query)); + if (my_hash_insert(&federated_open_tables, (byte *) share)) goto error; thr_lock_init(&share->lock); - pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST); + pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); } share->use_count++; pthread_mutex_unlock(&federated_mutex); @@ -813,6 +819,9 @@ error2: pthread_mutex_destroy(&share->mutex); error: pthread_mutex_unlock(&federated_mutex); + hash_delete(&federated_open_tables, (byte *) share); + if (share->scheme) + my_free((gptr) share->scheme, MYF(0)); my_free((gptr) share, MYF(0)); return NULL; @@ -827,9 +836,14 @@ error: static int free_share(FEDERATED_SHARE *share) { pthread_mutex_lock(&federated_mutex); + + if (share->scheme) + my_free((gptr) share->scheme, MYF(0)); + if (!--share->use_count) { - hash_delete(&federated_open_tables, (byte*) share); + hash_delete(&federated_open_tables, (byte *) share); + hash_free(&federated_open_tables); thr_lock_delete(&share->lock); pthread_mutex_destroy(&share->mutex); my_free((gptr) share, MYF(0)); @@ -847,7 +861,13 @@ static int free_share(FEDERATED_SHARE *share) in handler.cc. */ const char **ha_federated::bas_ext() const -{ static const char *ext[]= { NullS }; return ext; } +{ + static const char *ext[]= + { + NullS + }; + return ext; +} /* @@ -867,23 +887,20 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) if (!(share= get_share(name, table))) DBUG_RETURN(1); - thr_lock_data_init(&share->lock,&lock,NULL); + thr_lock_data_init(&share->lock, &lock, NULL); /* Connect to remote database mysql_real_connect() */ - mysql= mysql_init(0); - DBUG_PRINT("ha_federated::open",("hostname %s", share->hostname)); - DBUG_PRINT("ha_federated::open",("username %s", share->username)); - DBUG_PRINT("ha_federated::open",("password %s", share->password)); - DBUG_PRINT("ha_federated::open",("database %s", share->database)); - DBUG_PRINT("ha_federated::open",("port %d", share->port)); + mysql= mysql_init(0); + DBUG_PRINT("ha_federated::open", ("hostname %s", share->hostname)); + DBUG_PRINT("ha_federated::open", ("username %s", share->username)); + DBUG_PRINT("ha_federated::open", ("password %s", share->password)); + DBUG_PRINT("ha_federated::open", ("database %s", share->database)); + DBUG_PRINT("ha_federated::open", ("port %d", share->port)); if (!mysql_real_connect(mysql, - share->hostname, - share->username, - share->password, - share->database, - share->port, - NULL, - 0)) + share->hostname, + share->username, + share->password, + share->database, share->port, NULL, 0)) { my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql)); DBUG_RETURN(ER_CONNECT_TO_MASTER); @@ -905,6 +922,15 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) int ha_federated::close(void) { DBUG_ENTER("ha_federated::close"); + + // free the result set + if (result) + { + DBUG_PRINT("ha_federated::close", + ("mysql_free_result result at address %lx", result)); + mysql_free_result(result); + result= 0; + } /* Disconnect from mysql */ mysql_close(mysql); DBUG_RETURN(free_share(share)); @@ -929,10 +955,12 @@ int ha_federated::close(void) 1 if NULL 0 otherwise */ -inline uint field_in_record_is_null ( - TABLE* table, /* in: MySQL table object */ - Field* field, /* in: MySQL field object */ - char* record) /* in: a row in MySQL format */ +inline uint field_in_record_is_null(TABLE * table, /* in: MySQL table + object */ + Field * field, /* in: MySQL field + object */ + char *record) /* in: a row in MySQL + format */ { int null_offset; DBUG_ENTER("ha_federated::field_in_record_is_null"); @@ -963,11 +991,11 @@ inline uint field_in_record_is_null ( */ int ha_federated::write_row(byte * buf) { - int x= 0, num_fields= 0; + uint x= 0, num_fields= 0; Field **field; ulong current_query_id= 1; ulong tmp_query_id= 1; - int all_fields_have_same_query_id= 1; + uint all_fields_have_same_query_id= 1; char insert_buffer[IO_SIZE]; char values_buffer[IO_SIZE], insert_field_value_buffer[IO_SIZE]; @@ -980,40 +1008,41 @@ int ha_federated::write_row(byte * buf) values_string.length(0); // The actual value of the field, to be added to the values_string String insert_field_value_string(insert_field_value_buffer, - sizeof(insert_field_value_buffer), &my_charset_bin); + sizeof(insert_field_value_buffer), + &my_charset_bin); insert_field_value_string.length(0); DBUG_ENTER("ha_federated::write_row"); /* - I want to use this and the next line, but the repository needs to be - updated to do so + I want to use this and the next line, but the repository needs to be + updated to do so */ - statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); /* - get the current query id - the fields that we add to the insert - statement to send to the remote will not be appended unless they match - this query id + get the current query id - the fields that we add to the insert + statement to send to the remote will not be appended unless they match + this query id */ current_query_id= table->in_use->query_id; DBUG_PRINT("ha_federated::write_row", ("current query id %d", current_query_id)); // start off our string - insert_string.append("INSERT INTO "); + insert_string.append("INSERT INTO "); insert_string.append(share->table_base_name); // start both our field and field values strings insert_string.append(" ("); values_string.append(" VALUES ("); /* - Even if one field is different, all_fields_same_query_id can't remain - 0 if it remains 0, then that means no fields were specified in the query - such as in the case of INSERT INTO table VALUES (val1, val2, valN) + Even if one field is different, all_fields_same_query_id can't remain + 0 if it remains 0, then that means no fields were specified in the query + such as in the case of INSERT INTO table VALUES (val1, val2, valN) */ - for (field= table->field; *field ; field++, x++) + for (field= table->field; *field; field++, x++) { if (x > 0 && tmp_query_id != (*field)->query_id) all_fields_have_same_query_id= 0; @@ -1021,18 +1050,18 @@ int ha_federated::write_row(byte * buf) tmp_query_id= (*field)->query_id; } /* - loop through the field pointer array, add any fields to both the values - list and the fields list that match the current query id + loop through the field pointer array, add any fields to both the values + list and the fields list that match the current query id */ - for (field= table->field; *field ; field++, x++) + for (field= table->field; *field; field++, x++) { DBUG_PRINT("ha_federated::write_row", ("field type %d", (*field)->type())); // if there is a query id and if it's equal to the current query id - if ( ((*field)->query_id && (*field)->query_id == current_query_id ) - || all_fields_have_same_query_id) + if (((*field)->query_id && (*field)->query_id == current_query_id) + || all_fields_have_same_query_id) { num_fields++; - + if ((*field)->is_null()) { DBUG_PRINT("ha_federated::write_row", @@ -1060,30 +1089,28 @@ int ha_federated::write_row(byte * buf) // append commas between both fields and fieldnames insert_string.append(','); values_string.append(','); - DBUG_PRINT("ha_federated::write_row", - ("insert_string %s values_string %s insert_field_value_string %s", - insert_string.c_ptr_quick(), values_string.c_ptr_quick(), - insert_field_value_string.c_ptr_quick())); + DBUG_PRINT("ha_federated::write_row", + ("insert_string %s values_string %s insert_field_value_string %s", + insert_string.c_ptr_quick(), values_string.c_ptr_quick(), + insert_field_value_string.c_ptr_quick())); } } /* - chop of the trailing comma, or if there were no fields, a '(' - So, "INSERT INTO foo (" becomes "INSERT INTO foo " - or, with fields, "INSERT INTO foo (field1, field2," becomes + chop of the trailing comma, or if there were no fields, a '(' + So, "INSERT INTO foo (" becomes "INSERT INTO foo " + or, with fields, "INSERT INTO foo (field1, field2," becomes "INSERT INTO foo (field1, field2" */ insert_string.chop(); - /* - if there were no fields, we don't want to add a closing paren - AND, we don't want to chop off the last char '(' - insert will be "INSERT INTO t1 VALUES ();" + if there were no fields, we don't want to add a closing paren + AND, we don't want to chop off the last char '(' + insert will be "INSERT INTO t1 VALUES ();" */ - DBUG_PRINT("ha_federated::write_row",("x %d num fields %d", - x, num_fields)); + DBUG_PRINT("ha_federated::write_row", ("x %d num fields %d", x, num_fields)); if (num_fields > 0) { // chops off leading commas @@ -1092,18 +1119,17 @@ int ha_federated::write_row(byte * buf) } // we always want to append this, even if there aren't any fields values_string.append(')'); - + // add the values insert_string.append(values_string); - DBUG_PRINT("ha_federated::write_row",("insert query %s", - insert_string.c_ptr_quick())); + DBUG_PRINT("ha_federated::write_row", ("insert query %s", + insert_string.c_ptr_quick())); - if (mysql_real_query(mysql, insert_string.c_ptr_quick(), - insert_string.length())) + if (mysql_real_query(mysql, insert_string.ptr(), insert_string.length())) { - my_error(ER_QUERY_ON_MASTER,MYF(0),mysql_error(mysql)); - DBUG_RETURN(ER_QUERY_ON_MASTER); + my_error(ER_QUERY_ON_MASTER, MYF(0), mysql_error(mysql)); + DBUG_RETURN(ER_QUERY_ON_MASTER); } DBUG_RETURN(0); @@ -1125,22 +1151,21 @@ int ha_federated::write_row(byte * buf) Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc. */ -int ha_federated::update_row( - const byte * old_data, - byte * new_data - ) +int ha_federated::update_row(const byte * old_data, byte * new_data) { - int x= 0; + uint x= 0; uint has_a_primary_key= 0; - int primary_key_field_num; + uint primary_key_field_num; char old_field_value_buffer[IO_SIZE], new_field_value_buffer[IO_SIZE]; char update_buffer[IO_SIZE], where_buffer[IO_SIZE]; // stores the value to be replaced of the field were are updating - String old_field_value(old_field_value_buffer, sizeof(old_field_value_buffer), &my_charset_bin); + String old_field_value(old_field_value_buffer, sizeof(old_field_value_buffer), + &my_charset_bin); old_field_value.length(0); // stores the new value of the field - String new_field_value(new_field_value_buffer, sizeof(new_field_value_buffer), &my_charset_bin); + String new_field_value(new_field_value_buffer, sizeof(new_field_value_buffer), + &my_charset_bin); new_field_value.length(0); // stores the update query String update_string(update_buffer, sizeof(update_buffer), &my_charset_bin); @@ -1153,10 +1178,10 @@ int ha_federated::update_row( has_a_primary_key= table->s->primary_key == 0 ? 1 : 0; - primary_key_field_num= has_a_primary_key ? - table->key_info[table->s->primary_key].key_part->fieldnr -1 : -1; + primary_key_field_num= has_a_primary_key ? + table->key_info[table->s->primary_key].key_part->fieldnr - 1 : -1; if (has_a_primary_key) - DBUG_PRINT("ha_federated::update_row", ("has a primary key")); + DBUG_PRINT("ha_federated::update_row", ("has a primary key")); update_string.append("UPDATE "); update_string.append(share->table_base_name); @@ -1171,19 +1196,19 @@ int ha_federated::update_row( used to create SET field=value and old data is used to create WHERE field=oldvalue */ - - for (Field **field= table->field ; *field ; field++, x++) + + for (Field ** field= table->field; *field; field++, x++) { /* - In all of these tests for 'has_a_primary_key', what I'm trying to - accomplish is to only use the primary key in the WHERE clause if the - table has a primary key, as opposed to a table without a primary key - in which case we have to use all the fields to create a WHERE clause - using the old/current values, as well as adding a LIMIT statement + In all of these tests for 'has_a_primary_key', what I'm trying to + accomplish is to only use the primary key in the WHERE clause if the + table has a primary key, as opposed to a table without a primary key + in which case we have to use all the fields to create a WHERE clause + using the old/current values, as well as adding a LIMIT statement */ - if (has_a_primary_key) + if (has_a_primary_key) { - if (x == primary_key_field_num) + if (x == primary_key_field_num) where_string.append((*field)->field_name); } else @@ -1200,61 +1225,59 @@ int ha_federated::update_row( (*field)->val_str(&new_field_value); (*field)->quote_data(&new_field_value); - if ( has_a_primary_key ) + if (has_a_primary_key) { if (x == primary_key_field_num) where_string.append("="); } - else - if (! field_in_record_is_null(table, *field, (char*) old_data)) - where_string.append("="); + else if (!field_in_record_is_null(table, *field, (char*) old_data)) + where_string.append("="); } - if ( has_a_primary_key) + if (has_a_primary_key) { if (x == primary_key_field_num) { (*field)->val_str(&old_field_value, - (char *)(old_data + (*field)->offset())); + (char*) (old_data + (*field)->offset())); (*field)->quote_data(&old_field_value); where_string.append(old_field_value); } } else { - if (field_in_record_is_null(table, *field, (char*) old_data)) - where_string.append(" IS NULL "); - else - { - (*field)->val_str(&old_field_value, - (char *)(old_data + (*field)->offset())); - (*field)->quote_data(&old_field_value); - where_string.append(old_field_value); - } + if (field_in_record_is_null(table, *field, (char*) old_data)) + where_string.append(" IS NULL "); + else + { + (*field)->val_str(&old_field_value, + (char*) (old_data + (*field)->offset())); + (*field)->quote_data(&old_field_value); + where_string.append(old_field_value); + } } update_string.append(new_field_value); new_field_value.length(0); - if ((uint) x+1 < table->s->fields) + if (x + 1 < table->s->fields) { update_string.append(", "); - if (! has_a_primary_key) + if (!has_a_primary_key) where_string.append(" AND "); } old_field_value.length(0); } update_string.append(" WHERE "); - update_string.append(where_string.c_ptr_quick()); - if (! has_a_primary_key) + update_string.append(where_string.ptr()); + if (!has_a_primary_key) update_string.append(" LIMIT 1"); DBUG_PRINT("ha_federated::update_row", ("Final update query: %s", update_string.c_ptr_quick())); - if (mysql_real_query(mysql, update_string.c_ptr_quick(), - update_string.length())) + if (mysql_real_query(mysql, update_string.ptr(), update_string.length())) { - my_error(ER_QUERY_ON_MASTER,MYF(0),mysql_error(mysql)); - DBUG_RETURN(ER_QUERY_ON_MASTER); + my_error(ER_QUERY_ON_MASTER, MYF(0), mysql_error(mysql)); + DBUG_RETURN(ER_QUERY_ON_MASTER); } @@ -1277,7 +1300,7 @@ int ha_federated::update_row( */ int ha_federated::delete_row(const byte * buf) { - int x= 0; + uint x= 0; char delete_buffer[IO_SIZE]; char data_buffer[IO_SIZE]; @@ -1292,7 +1315,7 @@ int ha_federated::delete_row(const byte * buf) delete_string.append(share->table_base_name); delete_string.append(" WHERE "); - for (Field **field= table->field; *field; field++, x++) + for (Field ** field= table->field; *field; field++, x++) { delete_string.append((*field)->field_name); @@ -1307,22 +1330,21 @@ int ha_federated::delete_row(const byte * buf) (*field)->val_str(&data_string); (*field)->quote_data(&data_string); } - + delete_string.append(data_string); data_string.length(0); - if ((uint) x+1 < table->s->fields) + if (x + 1 < table->s->fields) delete_string.append(" AND "); } delete_string.append(" LIMIT 1"); DBUG_PRINT("ha_federated::delete_row", ("Delete sql: %s", delete_string.c_ptr_quick())); - if ( mysql_real_query(mysql, delete_string.c_ptr_quick(), - delete_string.length())) + if (mysql_real_query(mysql, delete_string.ptr(), delete_string.length())) { - my_error(ER_QUERY_ON_MASTER,MYF(0),mysql_error(mysql)); - DBUG_RETURN(ER_QUERY_ON_MASTER); + my_error(ER_QUERY_ON_MASTER, MYF(0), mysql_error(mysql)); + DBUG_RETURN(ER_QUERY_ON_MASTER); } DBUG_RETURN(0); @@ -1336,9 +1358,9 @@ int ha_federated::delete_row(const byte * buf) a WHERE clause on a non-primary key index, simply calls index_read_idx. */ int ha_federated::index_read(byte * buf, const byte * key, - uint key_len __attribute__((unused)), - enum ha_rkey_function find_flag - __attribute__((unused))) + uint key_len __attribute__ ((unused)), + enum ha_rkey_function find_flag + __attribute__ ((unused))) { DBUG_ENTER("ha_federated::index_read"); DBUG_RETURN(index_read_idx(buf, active_index, key, key_len, find_flag)); @@ -1354,9 +1376,9 @@ int ha_federated::index_read(byte * buf, const byte * key, uses a PRIMARY KEY index. */ int ha_federated::index_read_idx(byte * buf, uint index, const byte * key, - uint key_len __attribute__((unused)), - enum ha_rkey_function find_flag - __attribute__((unused))) + uint key_len __attribute__ ((unused)), + enum ha_rkey_function find_flag + __attribute__ ((unused))) { char index_value[IO_SIZE]; char key_value[IO_SIZE]; @@ -1370,27 +1392,34 @@ int ha_federated::index_read_idx(byte * buf, uint index, const byte * key, sql_query.length(0); DBUG_ENTER("ha_federated::index_read_idx"); - statistic_increment(table->in_use->status_var.ha_read_key_count,&LOCK_status); + statistic_increment(table->in_use->status_var.ha_read_key_count, + &LOCK_status); sql_query.append(share->select_query); sql_query.append(" WHERE "); - keylen= strlen((char *)(key)); + keylen= strlen((char*) (key)); create_where_from_key(&index_string, &table->key_info[index], key, keylen); sql_query.append(index_string); DBUG_PRINT("ha_federated::index_read_idx", - ("current key %d key value %s index_string value %s length %d", index, (char *)(key),index_string.c_ptr_quick(), - index_string.length())); + ("current key %d key value %s index_string value %s length %d", + index, (char*) (key), index_string.c_ptr_quick(), + index_string.length())); DBUG_PRINT("ha_federated::index_read_idx", - ("current position %d sql_query %s", current_position, - sql_query.c_ptr_quick())); + ("current position %d sql_query %s", current_position, + sql_query.c_ptr_quick())); - if (mysql_real_query(mysql, sql_query.c_ptr_quick(), sql_query.length())) + if (result) { - my_error(ER_QUERY_ON_MASTER,MYF(0),mysql_error(mysql)); - DBUG_RETURN(ER_QUERY_ON_MASTER); + mysql_free_result(result); + result= 0; + } + if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length())) + { + my_error(ER_QUERY_ON_MASTER, MYF(0), mysql_error(mysql)); + DBUG_RETURN(ER_QUERY_ON_MASTER); } result= mysql_store_result(mysql); @@ -1403,7 +1432,7 @@ int ha_federated::index_read_idx(byte * buf, uint index, const byte * key, if (mysql_errno(mysql)) { table->status= STATUS_NOT_FOUND; - DBUG_RETURN(mysql_errno(mysql)); + DBUG_RETURN(mysql_errno(mysql)); } DBUG_RETURN(rnd_next(buf)); @@ -1449,23 +1478,54 @@ int ha_federated::rnd_init(bool scan) DBUG_ENTER("ha_federated::rnd_init"); int num_fields, rows; - DBUG_PRINT("ha_federated::rnd_init", - ("share->select_query %s", share->select_query)); - if (mysql_real_query(mysql, share->select_query, strlen(share->select_query))) + /* + This 'scan' flag is incredibly important for this handler to work properly, + especially with updates that are called with indexes, because what happens + without this is index_read_idx gets called, does a query using the + index in a where clause, calls mysql_store_result, which then rnd_init + (from sql_update.cc) is called after this, which would do a + "select * from table" then a mysql_store_result, wiping out the result + set from index_read_idx's query, which causes the subsequent update_row + to update the wrong row! + */ + scan_flag= scan; + if (scan) { - my_error(ER_QUERY_ON_MASTER,MYF(0),mysql_error(mysql)); - DBUG_RETURN(ER_QUERY_ON_MASTER); - } - result= mysql_store_result(mysql); + DBUG_PRINT("ha_federated::rnd_init", + ("share->select_query %s", share->select_query)); + if (result) + { + DBUG_PRINT("ha_federated::rnd_init", + ("mysql_free_result address %lx", result)); + mysql_free_result(result); + result= 0; + } - if (mysql_errno(mysql)) - DBUG_RETURN(mysql_errno(mysql)); + if (mysql_real_query + (mysql, share->select_query, strlen(share->select_query))) + { + my_error(ER_QUERY_ON_MASTER, MYF(0), mysql_error(mysql)); + DBUG_RETURN(ER_QUERY_ON_MASTER); + } + result= mysql_store_result(mysql); + + if (mysql_errno(mysql)) + DBUG_RETURN(mysql_errno(mysql)); + } DBUG_RETURN(0); } int ha_federated::rnd_end() { DBUG_ENTER("ha_federated::rnd_end"); + if (result) + { + DBUG_PRINT("ha_federated::index_end", + ("mysql_free_result address %lx", result)); + mysql_free_result(result); + result= 0; + } + mysql_free_result(result); DBUG_RETURN(index_end()); } @@ -1493,10 +1553,12 @@ int ha_federated::rnd_next(byte *buf) // Fetch a row, insert it back in a row format. current_position= result->data_cursor; - if (! (row= mysql_fetch_row(result))) + DBUG_PRINT("ha_federated::rnd_next", + ("current position %d", current_position)); + if (!(row= mysql_fetch_row(result))) DBUG_RETURN(HA_ERR_END_OF_FILE); - - DBUG_RETURN(convert_row_to_internal_format(buf,row)); + + DBUG_RETURN(convert_row_to_internal_format(buf, row)); } @@ -1517,7 +1579,7 @@ void ha_federated::position(const byte *record) { DBUG_ENTER("ha_federated::position"); //ha_store_ptr Add seek storage - *(MYSQL_ROW_OFFSET *)ref=current_position; // ref is always aligned + *(MYSQL_ROW_OFFSET *) ref= current_position; // ref is always aligned DBUG_VOID_RETURN; } @@ -1535,11 +1597,24 @@ void ha_federated::position(const byte *record) int ha_federated::rnd_pos(byte * buf, byte *pos) { DBUG_ENTER("ha_federated::rnd_pos"); - statistic_increment(table->in_use->status_var.ha_read_rnd_count,&LOCK_status); - memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos is not aligned - result->current_row= 0; - result->data_cursor= current_position; - DBUG_RETURN(rnd_next(buf)); + /* + we do not need to do any of this if there has been a scan performed already, or + if this is an update and index_read_idx already has a result set in which to build + it's update query from + */ + if (scan_flag) + { + statistic_increment(table->in_use->status_var.ha_read_rnd_count, + &LOCK_status); + memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos + // is + // not + // aligned + result->current_row= 0; + result->data_cursor= current_position; + DBUG_RETURN(rnd_next(buf)); + } + DBUG_RETURN(0); } @@ -1590,7 +1665,7 @@ int ha_federated::rnd_pos(byte * buf, byte *pos) void ha_federated::info(uint flag) { DBUG_ENTER("ha_federated::info"); - records= 10000; // Fake! + records= 10000; // Fake! DBUG_VOID_RETURN; } @@ -1618,9 +1693,10 @@ int ha_federated::delete_all_rows() query.append("TRUNCATE "); query.append(share->table_base_name); - if (mysql_real_query(mysql, query.c_ptr_quick(), query.length())) { - my_error(ER_QUERY_ON_MASTER,MYF(0),mysql_error(mysql)); - DBUG_RETURN(ER_QUERY_ON_MASTER); + if (mysql_real_query(mysql, query.ptr(), query.length())) + { + my_error(ER_QUERY_ON_MASTER, MYF(0), mysql_error(mysql)); + DBUG_RETURN(ER_QUERY_ON_MASTER); } DBUG_RETURN(HA_ERR_WRONG_COMMAND); @@ -1657,32 +1733,31 @@ int ha_federated::delete_all_rows() Called from lock.cc by get_lock_data(). */ THR_LOCK_DATA **ha_federated::store_lock(THD *thd, - THR_LOCK_DATA **to, - enum thr_lock_type lock_type) + THR_LOCK_DATA **to, + enum thr_lock_type lock_type) { - if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) + if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { /* - Here is where we get into the guts of a row level lock. - If TL_UNLOCK is set - If we are not doing a LOCK TABLE or DISCARD/IMPORT - TABLESPACE, then allow multiple writers + Here is where we get into the guts of a row level lock. + If TL_UNLOCK is set + If we are not doing a LOCK TABLE or DISCARD/IMPORT + TABLESPACE, then allow multiple writers */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && - lock_type <= TL_WRITE) && !thd->in_lock_tables - && !thd->tablespace_op) + lock_type <= TL_WRITE) && !thd->in_lock_tables && !thd->tablespace_op) lock_type= TL_WRITE_ALLOW_WRITE; /* - In queries of type INSERT INTO t1 SELECT ... FROM t2 ... - MySQL would use the lock TL_READ_NO_INSERT on t2, and that - would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts - to t2. Convert the lock to a normal read lock to allow - concurrent inserts to t2. + In queries of type INSERT INTO t1 SELECT ... FROM t2 ... + MySQL would use the lock TL_READ_NO_INSERT on t2, and that + would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts + to t2. Convert the lock to a normal read lock to allow + concurrent inserts to t2. */ - if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) + if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) lock_type= TL_READ; lock.type= lock_type; @@ -1699,19 +1774,16 @@ THR_LOCK_DATA **ha_federated::store_lock(THD *thd, create tables if they do not exist. */ int ha_federated::create(const char *name, TABLE *table_arg, - HA_CREATE_INFO *create_info) + HA_CREATE_INFO *create_info) { - int retcode; FEDERATED_SHARE tmp; DBUG_ENTER("ha_federated::create"); - retcode= parse_url(&tmp, table_arg, 1); - if (retcode < 0) + if (parse_url(&tmp, table_arg, 1)) { - DBUG_PRINT("ha_federated::create", - ("ERROR: on table creation for %s called parse_url, retcode %d", - create_info->data_file_name, retcode)); + my_error(ER_CANT_CREATE_TABLE, MYF(0)); DBUG_RETURN(ER_CANT_CREATE_TABLE); } + my_free((gptr) tmp.scheme, MYF(0)); DBUG_RETURN(0); } -#endif /* HAVE_FEDERATED_DB */ +#endif /* HAVE_FEDERATED_DB */ diff --git a/sql/ha_federated.h b/sql/ha_federated.h index 56f5e6de4b7..6870a0902e8 100755 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -62,6 +62,7 @@ class ha_federated: public handler FEDERATED_SHARE *share; /* Shared lock info */ MYSQL *mysql; MYSQL_RES *result; + bool scan_flag; uint ref_length; uint fetch_num; // stores the fetch num MYSQL_ROW_OFFSET current_position; // Current position used by ::position() @@ -76,7 +77,7 @@ private: public: ha_federated(TABLE *table): handler(table), - mysql(0), + mysql(0), result(0), scan_flag(0), ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0) { } From bc4301740d12000790457096589edb86679aa9c6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Feb 2005 23:07:10 -0800 Subject: [PATCH 02/20] WL# 2094 Federated Storage Handler This changeset/patch is on top of changesets 1.1814 and 1.1846 (for bugs 8033 and 8065) and now fixes bug 8535. These changes have been built and tested successfully on build.mysql.com handler.cc: Added hooks for federated_db_init() and federated_db_end(), as done with ha_archive_db does, per suggestion by Ingo in code review of patch 1.1846. ha_federated.h: declaration of federated_db_init() and federated_db_end() ha_federated.cc: - Fixed some indentation problems from indent-ex (mainly to do with cases where "variablename += value" - Added federated_db_init() and federated_db_end(), as done with archive, which also handler more elegantly one of the memory leaks from bug 8033 where the federated_mutex was not freed - Removed extrenous debug messages in parse_url() - Fixed bug 8535, caused by NULL being quoted in write_row. This used to work (incorrectly) but a recent change was made in the server that exposed this sql/ha_federated.cc: - Fixed some indentation problems from indent-ex (mainly to do with cases where "variablename += value" - Added federated_db_init() and federated_db_end(), as done with archive, which also handler more elegantly one of the memory leaks from bug 8033 where the federated_mutex was not freed - Removed extrenous debug messages in parse_url() sql/ha_federated.h: declaration of federated_db_init() and federated_db_end() sql/handler.cc: Added hooks for federated_db_init() and federated_db_end(), as done with ha_archive_db does. --- sql/ha_federated.cc | 209 +++++++++++++++++++++++--------------------- sql/ha_federated.h | 3 + sql/handler.cc | 14 +++ 3 files changed, 125 insertions(+), 101 deletions(-) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index eed145203c3..500dcda3e21 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -369,7 +369,50 @@ static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, my_bool not_used __attribute__ ((unused))) { *length= share->table_name_length; - return (byte *) share->table_name; + return (byte*)share->table_name; +} + +/* + Initialize the federated handler. + + SYNOPSIS + federated_db_init() + void + + RETURN + FALSE OK + TRUE Error +*/ + +bool federated_db_init() +{ + federated_init= 1; + VOID(pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)); + return (hash_init(&federated_open_tables, system_charset_info, 32, 0, 0, + (hash_get_key) federated_get_key, 0, 0)); +} + + +/* + Release the federated handler. + + SYNOPSIS + federated_db_end() + void + + RETURN + FALSE OK +*/ + +bool federated_db_end() +{ + if (federated_init) + { + hash_free(&federated_open_tables); + VOID(pthread_mutex_destroy(&federated_mutex)); + } + federated_init= 0; + return FALSE; } /* @@ -425,14 +468,11 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, share->scheme[share->username - share->scheme]= '\0'; if (strcmp(share->scheme, "mysql") != 0) { - DBUG_PRINT("ha_federated::parse_url", - ("The federated handler currently only supports connecting\ - to a MySQL database!!!\n")); my_error(error_num, MYF(0), "ERROR: federated handler only supports remote 'mysql://' database"); DBUG_RETURN(1); } - share->username += 3; + share->username+= 3; if ((share->hostname= strchr(share->username, '@'))) { @@ -447,8 +487,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, // make sure there isn't an extra / or @ if ((strchr(share->password, '/') || strchr(share->hostname, '@'))) { - DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), "this connection string is not in the correct format!!!\n"); DBUG_RETURN(1); @@ -467,8 +505,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, // make sure there isn't an extra / or @ if ((strchr(share->username, '/')) || (strchr(share->hostname, '@'))) { - DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), "this connection string is not in the correct format!!!\n"); DBUG_RETURN(1); @@ -496,8 +532,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, } else { - DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), "this connection string is not in the correct format!!!\n"); DBUG_RETURN(1); @@ -505,8 +539,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, } else { - DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), "this connection string is not in the correct format!!!\n"); DBUG_RETURN(1); @@ -514,8 +546,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, // make sure there's not an extra / if ((strchr(share->table_base_name, '/'))) { - DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), "this connection string is not in the correct format!!!\n"); DBUG_RETURN(1); @@ -533,12 +563,13 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, DBUG_PRINT("ha_federated::parse_url", ("scheme %s username %s password %s \ - hostname %s port %d database %s tablename %s\n", share->scheme, share->username, share->password, share->hostname, share->port, share->database, share->table_base_name)); + hostname %s port %d database %s tablename %s\n", + share->scheme, share->username, share->password, + share->hostname, share->port, share->database, + share->table_base_name)); } else { - DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), "this connection string is not in the correct format!!!\n"); DBUG_RETURN(1); @@ -546,8 +577,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, } else { - DBUG_PRINT("ha_federated::parse_url", - ("this connection string is not in the correct format!!!\n")); my_error(error_num, MYF(0), "this connection string is not in the correct format!!!\n"); DBUG_RETURN(1); @@ -573,35 +602,27 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, RETURN VALUE 0 After fields have had field values stored from record */ -uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) +uint ha_federated::convert_row_to_internal_format(byte* record, MYSQL_ROW row) { - unsigned long *lengths; - unsigned int num_fields; - unsigned int x= 0; + ulong *lengths; + uint num_fields; + uint x= 0; DBUG_ENTER("ha_federated::convert_row_to_internal_format"); num_fields= mysql_num_fields(result); - lengths= (unsigned long*) my_malloc(num_fields * sizeof(unsigned long), + lengths= (ulong*) my_malloc(num_fields * sizeof(ulong), MYF(0)); - cli_fetch_lengths((unsigned long*) (lengths), row, num_fields); + cli_fetch_lengths((ulong*) (lengths), row, num_fields); memset(record, 0, table->s->null_bytes); - for (Field ** field= table->field; *field; field++, x++) + for (Field **field= table->field; *field; field++, x++) { if (!row[x]) - { (*field)->set_null(); - } else - /* - changed system_charset_info to default_charset_info because - testing revealed that german text was not being retrieved properly - */ - DBUG_PRINT("ha_federated::convert_row_to_internal_format", - ("row[%d] %s length %lu", x, row[x], lengths[x])); - (*field)->store(row[x], lengths[x], &my_charset_bin); + (*field)->store(row[x], lengths[x], &my_charset_bin); } my_free((gptr) lengths, MYF(0)); lengths= 0; @@ -637,11 +658,12 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, if (*key++) { if (to->append("IS NULL", 7)) - DBUG_PRINT("ha_federated::create_where_from_key", - ("NULL type %s", to->c_ptr_quick())); - DBUG_RETURN(1); - key_length -= key_part->store_length; - key += key_part->store_length - 1; + DBUG_RETURN(1); + + DBUG_PRINT("ha_federated::create_where_from_key", + ("NULL type %s", to->c_ptr_quick())); + key_length-= key_part->store_length; + key+= key_part->store_length - 1; continue; } key_length--; @@ -655,29 +677,29 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, /* This is can be threated as a hex string */ Field_bit *field= (Field_bit *) (key_part->field); char buff[64 + 2], *ptr; - byte *end= (byte *) (key) + length; + byte *end= (byte*)(key)+length; buff[0]= '0'; buff[1]= 'x'; for (ptr= buff + 2; key < end; key++) { - uint tmp= (uint) (uchar) * key; + uint tmp= (uint)(uchar) *key; *ptr++= _dig_vec_upper[tmp >> 4]; *ptr++= _dig_vec_upper[tmp & 15]; } - if (to->append(buff, (uint) (ptr - buff))) + if (to->append(buff, (uint)(ptr - buff))) DBUG_RETURN(1); DBUG_PRINT("ha_federated::create_where_from_key", ("bit type %s", to->c_ptr_quick())); - key_length -= length; + key_length-= length; continue; } if (key_part->key_part_flag & HA_BLOB_PART) { uint blob_length= uint2korr(key); - key += HA_KEY_BLOB_LENGTH; - key_length -= HA_KEY_BLOB_LENGTH; + key+= HA_KEY_BLOB_LENGTH; + key_length-= HA_KEY_BLOB_LENGTH; tmp.set_quick((char*) key, blob_length, &my_charset_bin); if (append_escaped(to, &tmp)) @@ -690,7 +712,7 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, else if (key_part->key_part_flag & HA_VAR_LENGTH_PART) { length= uint2korr(key); - key += HA_KEY_BLOB_LENGTH; + key+= HA_KEY_BLOB_LENGTH; tmp.set_quick((char*) key, length, &my_charset_bin); if (append_escaped(to, &tmp)) DBUG_RETURN(1); @@ -722,8 +744,8 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, DBUG_RETURN(1); DBUG_PRINT("ha_federated::create_where_from_key", ("final value for 'to' %s", to->c_ptr_quick())); - key += length; - key_length -= length; + key+= length; + key_length-= length; DBUG_RETURN(0); } DBUG_RETURN(1); @@ -744,9 +766,11 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) uint table_name_length, table_base_name_length; char *tmp_table_name, *tmp_table_base_name, *table_base_name, *select_query; - // share->table_name has the file location - we want the actual table's - // name! - table_base_name= (char*) table->s->table_name; + /* + share->table_name has the file location - we want the actual table's + name! + */ + table_base_name= (char*)table->s->table_name; DBUG_PRINT("ha_federated::get_share", ("table_name %s", table_base_name)); /* So why does this exist? There is no way currently to init a storage engine. @@ -754,25 +778,12 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) do this. Since you will not want to do this, this is probably the next best method. */ - if (!federated_init) - { - /* Hijack a mutex for init'ing the storage engine */ - pthread_mutex_lock(&LOCK_mysql_create_db); - if (!federated_init) - { - federated_init++; - VOID(pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)); - (void) hash_init(&federated_open_tables, system_charset_info, 32, 0, 0, - (hash_get_key) federated_get_key, 0, 0); - } - pthread_mutex_unlock(&LOCK_mysql_create_db); - } pthread_mutex_lock(&federated_mutex); table_name_length= (uint) strlen(table_name); table_base_name_length= (uint) strlen(table_base_name); if (!(share= (FEDERATED_SHARE *) hash_search(&federated_open_tables, - (byte *) table_name, + (byte*) table_name, table_name_length))) { query.set_charset(system_charset_info); @@ -804,7 +815,7 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) strmov(share->select_query, query.ptr()); DBUG_PRINT("ha_federated::get_share", ("share->select_query %s", share->select_query)); - if (my_hash_insert(&federated_open_tables, (byte *) share)) + if (my_hash_insert(&federated_open_tables, (byte*) share)) goto error; thr_lock_init(&share->lock); pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); @@ -819,7 +830,6 @@ error2: pthread_mutex_destroy(&share->mutex); error: pthread_mutex_unlock(&federated_mutex); - hash_delete(&federated_open_tables, (byte *) share); if (share->scheme) my_free((gptr) share->scheme, MYF(0)); my_free((gptr) share, MYF(0)); @@ -837,15 +847,14 @@ static int free_share(FEDERATED_SHARE *share) { pthread_mutex_lock(&federated_mutex); - if (share->scheme) - my_free((gptr) share->scheme, MYF(0)); - if (!--share->use_count) { - hash_delete(&federated_open_tables, (byte *) share); - hash_free(&federated_open_tables); + if (share->scheme) + my_free((gptr) share->scheme, MYF(0)); + + hash_delete(&federated_open_tables, (byte*)share); thr_lock_delete(&share->lock); - pthread_mutex_destroy(&share->mutex); + VOID(pthread_mutex_destroy(&share->mutex)); my_free((gptr) share, MYF(0)); } pthread_mutex_unlock(&federated_mutex); @@ -900,7 +909,9 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) share->hostname, share->username, share->password, - share->database, share->port, NULL, 0)) + share->database, + share->port, + share->socket, 0)) { my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql)); DBUG_RETURN(ER_CONNECT_TO_MASTER); @@ -955,12 +966,9 @@ int ha_federated::close(void) 1 if NULL 0 otherwise */ -inline uint field_in_record_is_null(TABLE * table, /* in: MySQL table - object */ - Field * field, /* in: MySQL field - object */ - char *record) /* in: a row in MySQL - format */ +inline uint field_in_record_is_null(TABLE *table, /* in: MySQL table object */ + Field *field, /* in: MySQL field object */ + char *record) /* in: row in MySQL format */ { int null_offset; DBUG_ENTER("ha_federated::field_in_record_is_null"); @@ -968,7 +976,7 @@ inline uint field_in_record_is_null(TABLE * table, /* in: MySQL table if (!field->null_ptr) DBUG_RETURN(0); - null_offset= (uint) ((char*) field->null_ptr - (char*) table->record[0]); + null_offset= (uint) ((char*)field->null_ptr - (char*)table->record[0]); if (record[null_offset] & field->null_bit) DBUG_RETURN(1); @@ -989,7 +997,7 @@ inline uint field_in_record_is_null(TABLE * table, /* in: MySQL table Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc, sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc. */ -int ha_federated::write_row(byte * buf) +int ha_federated::write_row(byte* buf) { uint x= 0, num_fields= 0; Field **field; @@ -1075,13 +1083,12 @@ int ha_federated::write_row(byte * buf) ("current query id %d field is not null query ID %d", current_query_id, (*field)->query_id)); (*field)->val_str(&insert_field_value_string); + // quote these fields if they require it + (*field)->quote_data(&insert_field_value_string); } // append the field name insert_string.append((*field)->field_name); - // quote these fields if they require it - - (*field)->quote_data(&insert_field_value_string); // append the value values_string.append(insert_field_value_string); insert_field_value_string.length(0); @@ -1197,7 +1204,7 @@ int ha_federated::update_row(const byte * old_data, byte * new_data) field=oldvalue */ - for (Field ** field= table->field; *field; field++, x++) + for (Field **field= table->field; *field; field++, x++) { /* In all of these tests for 'has_a_primary_key', what I'm trying to @@ -1268,8 +1275,8 @@ int ha_federated::update_row(const byte * old_data, byte * new_data) old_field_value.length(0); } update_string.append(" WHERE "); - update_string.append(where_string.ptr()); - if (!has_a_primary_key) + update_string.append(where_string.c_ptr_quick()); + if (! has_a_primary_key) update_string.append(" LIMIT 1"); DBUG_PRINT("ha_federated::update_row", ("Final update query: %s", @@ -1315,7 +1322,7 @@ int ha_federated::delete_row(const byte * buf) delete_string.append(share->table_base_name); delete_string.append(" WHERE "); - for (Field ** field= table->field; *field; field++, x++) + for (Field **field= table->field; *field; field++, x++) { delete_string.append((*field)->field_name); @@ -1357,7 +1364,7 @@ int ha_federated::delete_row(const byte * buf) index. This method, which is called in the case of an SQL statement having a WHERE clause on a non-primary key index, simply calls index_read_idx. */ -int ha_federated::index_read(byte * buf, const byte * key, +int ha_federated::index_read(byte* buf, const byte * key, uint key_len __attribute__ ((unused)), enum ha_rkey_function find_flag __attribute__ ((unused))) @@ -1375,7 +1382,7 @@ int ha_federated::index_read(byte * buf, const byte * key, a regular non-primary key index, OR is called DIRECTLY when the WHERE clause uses a PRIMARY KEY index. */ -int ha_federated::index_read_idx(byte * buf, uint index, const byte * key, +int ha_federated::index_read_idx(byte* buf, uint index, const byte * key, uint key_len __attribute__ ((unused)), enum ha_rkey_function find_flag __attribute__ ((unused))) @@ -1454,7 +1461,7 @@ int ha_federated::index_init(uint keynr) /* Used to read forward through the index. */ -int ha_federated::index_next(byte * buf) +int ha_federated::index_next(byte* buf) { DBUG_ENTER("ha_federated::index_next"); DBUG_RETURN(rnd_next(buf)); @@ -1546,7 +1553,7 @@ int ha_federated::index_end(void) Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc, and sql_update.cc. */ -int ha_federated::rnd_next(byte *buf) +int ha_federated::rnd_next(byte* buf) { MYSQL_ROW row; DBUG_ENTER("ha_federated::rnd_next"); @@ -1594,7 +1601,7 @@ void ha_federated::position(const byte *record) Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc. */ -int ha_federated::rnd_pos(byte * buf, byte *pos) +int ha_federated::rnd_pos(byte* buf, byte *pos) { DBUG_ENTER("ha_federated::rnd_pos"); /* @@ -1606,10 +1613,10 @@ int ha_federated::rnd_pos(byte * buf, byte *pos) { statistic_increment(table->in_use->status_var.ha_read_rnd_count, &LOCK_status); - memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos - // is - // not - // aligned + /* + pos is not aligned + */ + memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); result->current_row= 0; result->data_cursor= current_position; DBUG_RETURN(rnd_next(buf)); @@ -1786,4 +1793,4 @@ int ha_federated::create(const char *name, TABLE *table_arg, my_free((gptr) tmp.scheme, MYF(0)); DBUG_RETURN(0); } -#endif /* HAVE_FEDERATED_DB */ +#endif /* HAVE_FEDERATED_DB */ diff --git a/sql/ha_federated.h b/sql/ha_federated.h index 6870a0902e8..04bbf2a56f6 100755 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -174,3 +174,6 @@ public: THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); //required }; + +bool federated_db_init(void); +bool federated_db_end(void); diff --git a/sql/handler.cc b/sql/handler.cc index b4fed363e87..0e92956c366 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -364,6 +364,16 @@ int ha_init() opt_using_transactions=1; } #endif +#ifdef HAVE_FEDERATED_DB + if (have_federated_db == SHOW_OPTION_YES) + { + if (federated_db_init()) + { + have_federated_db= SHOW_OPTION_DISABLED; + error= 1; + } + } +#endif #ifdef HAVE_ARCHIVE_DB if (have_archive_db == SHOW_OPTION_YES) { @@ -405,6 +415,10 @@ int ha_panic(enum ha_panic_function flag) if (have_ndbcluster == SHOW_OPTION_YES) error|=ndbcluster_end(); #endif +#ifdef HAVE_FEDERATED_DB + if (have_federated_db == SHOW_OPTION_YES) + error|= federated_db_end(); +#endif #ifdef HAVE_ARCHIVE_DB if (have_archive_db == SHOW_OPTION_YES) error|= archive_db_end(); From 2041ea1f0e5f011277b5c719fba7ccc96ea03fb7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Feb 2005 16:17:21 -0800 Subject: [PATCH 03/20] WL# 2094, This patch is on top of 1.1814, 1.1846, 1.1856, which contain fixes for bugs 8033, 8065, 8535, 8582 This particular changeset contains style changes per code review suggestions and does not contain bug fixes in of itself. ha_federated.h: standardised code style to conform to internals.texi ha_federated.cc: more code standardisation to conform to internals.texi. - casts - declarations - comments - 80 char width also, append using string1.append(string2) and not string1.append(string2.c_ptr_quick()) sql/ha_federated.cc: more code standardisation to conform to internals.texi. - casts - declarations - comments - 80 char width also, append using string1.append(string2) and not string1.append(string2.c_ptr_quick()) sql/ha_federated.h: standardised code style to conform to internals.texi --- sql/ha_federated.cc | 107 ++++++++++++++++++++++---------------------- sql/ha_federated.h | 12 +++-- 2 files changed, 62 insertions(+), 57 deletions(-) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 500dcda3e21..da62d51c83e 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -369,7 +369,7 @@ static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, my_bool not_used __attribute__ ((unused))) { *length= share->table_name_length; - return (byte*)share->table_name; + return (byte*) share->table_name; } /* @@ -456,7 +456,6 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, { DBUG_ENTER("ha_federated::parse_url"); - // This either get set or will remain the same. share->port= 0; uint error_num= table_create_flag ? ER_CANT_CREATE_TABLE : ER_CONNECT_TO_MASTER; @@ -484,7 +483,9 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, share->username[share->password - share->username]= '\0'; share->password++; share->username= share->username; - // make sure there isn't an extra / or @ + /* + make sure there isn't an extra / or @ + */ if ((strchr(share->password, '/') || strchr(share->hostname, '@'))) { my_error(error_num, MYF(0), @@ -502,7 +503,9 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, else share->username= share->username; - // make sure there isn't an extra / or @ + /* + make sure there isn't an extra / or @ + */ if ((strchr(share->username, '/')) || (strchr(share->hostname, '@'))) { my_error(error_num, MYF(0), @@ -543,7 +546,9 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, "this connection string is not in the correct format!!!\n"); DBUG_RETURN(1); } - // make sure there's not an extra / + /* + make sure there's not an extra / + */ if ((strchr(share->table_base_name, '/'))) { my_error(error_num, MYF(0), @@ -602,7 +607,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, RETURN VALUE 0 After fields have had field values stored from record */ -uint ha_federated::convert_row_to_internal_format(byte* record, MYSQL_ROW row) +uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) { ulong *lengths; uint num_fields; @@ -611,9 +616,8 @@ uint ha_federated::convert_row_to_internal_format(byte* record, MYSQL_ROW row) DBUG_ENTER("ha_federated::convert_row_to_internal_format"); num_fields= mysql_num_fields(result); - lengths= (ulong*) my_malloc(num_fields * sizeof(ulong), - MYF(0)); - cli_fetch_lengths((ulong*) (lengths), row, num_fields); + lengths= (ulong*) my_malloc(num_fields * sizeof(ulong), MYF(0)); + cli_fetch_lengths((ulong*) lengths, row, num_fields); memset(record, 0, table->s->null_bytes); @@ -770,7 +774,7 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) share->table_name has the file location - we want the actual table's name! */ - table_base_name= (char*)table->s->table_name; + table_base_name= (char*) table->s->table_name; DBUG_PRINT("ha_federated::get_share", ("table_name %s", table_base_name)); /* So why does this exist? There is no way currently to init a storage engine. @@ -825,13 +829,11 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) return share; -error2: - thr_lock_delete(&share->lock); - pthread_mutex_destroy(&share->mutex); error: pthread_mutex_unlock(&federated_mutex); if (share->scheme) my_free((gptr) share->scheme, MYF(0)); + VOID(pthread_mutex_destroy(&share->mutex)); my_free((gptr) share, MYF(0)); return NULL; @@ -852,7 +854,7 @@ static int free_share(FEDERATED_SHARE *share) if (share->scheme) my_free((gptr) share->scheme, MYF(0)); - hash_delete(&federated_open_tables, (byte*)share); + hash_delete(&federated_open_tables, (byte*) share); thr_lock_delete(&share->lock); VOID(pthread_mutex_destroy(&share->mutex)); my_free((gptr) share, MYF(0)); @@ -934,7 +936,7 @@ int ha_federated::close(void) { DBUG_ENTER("ha_federated::close"); - // free the result set + /* free the result set */ if (result) { DBUG_PRINT("ha_federated::close", @@ -966,9 +968,9 @@ int ha_federated::close(void) 1 if NULL 0 otherwise */ -inline uint field_in_record_is_null(TABLE *table, /* in: MySQL table object */ - Field *field, /* in: MySQL field object */ - char *record) /* in: row in MySQL format */ +inline uint field_in_record_is_null(TABLE *table, + Field *field, + char *record) { int null_offset; DBUG_ENTER("ha_federated::field_in_record_is_null"); @@ -997,7 +999,7 @@ inline uint field_in_record_is_null(TABLE *table, /* in: MySQL table object */ Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc, sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc. */ -int ha_federated::write_row(byte* buf) +int ha_federated::write_row(byte *buf) { uint x= 0, num_fields= 0; Field **field; @@ -1008,23 +1010,20 @@ int ha_federated::write_row(byte* buf) char insert_buffer[IO_SIZE]; char values_buffer[IO_SIZE], insert_field_value_buffer[IO_SIZE]; - // The main insert query string + /* The main insert query string */ String insert_string(insert_buffer, sizeof(insert_buffer), &my_charset_bin); insert_string.length(0); - // The string containing the values to be added to the insert + /* The string containing the values to be added to the insert */ String values_string(values_buffer, sizeof(values_buffer), &my_charset_bin); values_string.length(0); - // The actual value of the field, to be added to the values_string + /* The actual value of the field, to be added to the values_string */ String insert_field_value_string(insert_field_value_buffer, sizeof(insert_field_value_buffer), &my_charset_bin); insert_field_value_string.length(0); DBUG_ENTER("ha_federated::write_row"); - /* - I want to use this and the next line, but the repository needs to be - updated to do so - */ + statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); @@ -1038,10 +1037,10 @@ int ha_federated::write_row(byte* buf) DBUG_PRINT("ha_federated::write_row", ("current query id %d", current_query_id)); - // start off our string + /* start off our string */ insert_string.append("INSERT INTO "); insert_string.append(share->table_base_name); - // start both our field and field values strings + /* start both our field and field values strings */ insert_string.append(" ("); values_string.append(" VALUES ("); @@ -1083,17 +1082,17 @@ int ha_federated::write_row(byte* buf) ("current query id %d field is not null query ID %d", current_query_id, (*field)->query_id)); (*field)->val_str(&insert_field_value_string); - // quote these fields if they require it + /* quote these fields if they require it */ (*field)->quote_data(&insert_field_value_string); } - // append the field name + /* append the field name */ insert_string.append((*field)->field_name); - // append the value + /* append the value */ values_string.append(insert_field_value_string); insert_field_value_string.length(0); - // append commas between both fields and fieldnames + /* append commas between both fields and fieldnames */ insert_string.append(','); values_string.append(','); DBUG_PRINT("ha_federated::write_row", @@ -1120,14 +1119,14 @@ int ha_federated::write_row(byte* buf) DBUG_PRINT("ha_federated::write_row", ("x %d num fields %d", x, num_fields)); if (num_fields > 0) { - // chops off leading commas + /* chops off leading commas */ values_string.chop(); insert_string.append(')'); } - // we always want to append this, even if there aren't any fields + /* we always want to append this, even if there aren't any fields */ values_string.append(')'); - // add the values + /* add the values */ insert_string.append(values_string); DBUG_PRINT("ha_federated::write_row", ("insert query %s", @@ -1158,7 +1157,7 @@ int ha_federated::write_row(byte* buf) Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc. */ -int ha_federated::update_row(const byte * old_data, byte * new_data) +int ha_federated::update_row(const byte *old_data, byte *new_data) { uint x= 0; uint has_a_primary_key= 0; @@ -1166,18 +1165,20 @@ int ha_federated::update_row(const byte * old_data, byte * new_data) char old_field_value_buffer[IO_SIZE], new_field_value_buffer[IO_SIZE]; char update_buffer[IO_SIZE], where_buffer[IO_SIZE]; - // stores the value to be replaced of the field were are updating + /* + stores the value to be replaced of the field were are updating + */ String old_field_value(old_field_value_buffer, sizeof(old_field_value_buffer), &my_charset_bin); old_field_value.length(0); - // stores the new value of the field + /* stores the new value of the field */ String new_field_value(new_field_value_buffer, sizeof(new_field_value_buffer), &my_charset_bin); new_field_value.length(0); - // stores the update query + /* stores the update query */ String update_string(update_buffer, sizeof(update_buffer), &my_charset_bin); update_string.length(0); - // stores the WHERE clause + /* stores the WHERE clause */ String where_string(where_buffer, sizeof(where_buffer), &my_charset_bin); where_string.length(0); @@ -1275,7 +1276,7 @@ int ha_federated::update_row(const byte * old_data, byte * new_data) old_field_value.length(0); } update_string.append(" WHERE "); - update_string.append(where_string.c_ptr_quick()); + update_string.append(where_string); if (! has_a_primary_key) update_string.append(" LIMIT 1"); @@ -1305,7 +1306,7 @@ int ha_federated::update_row(const byte * old_data, byte * new_data) it is used for removing duplicates while in insert it is used for REPLACE calls. */ -int ha_federated::delete_row(const byte * buf) +int ha_federated::delete_row(const byte *buf) { uint x= 0; char delete_buffer[IO_SIZE]; @@ -1364,7 +1365,7 @@ int ha_federated::delete_row(const byte * buf) index. This method, which is called in the case of an SQL statement having a WHERE clause on a non-primary key index, simply calls index_read_idx. */ -int ha_federated::index_read(byte* buf, const byte * key, +int ha_federated::index_read(byte *buf, const byte *key, uint key_len __attribute__ ((unused)), enum ha_rkey_function find_flag __attribute__ ((unused))) @@ -1382,7 +1383,7 @@ int ha_federated::index_read(byte* buf, const byte * key, a regular non-primary key index, OR is called DIRECTLY when the WHERE clause uses a PRIMARY KEY index. */ -int ha_federated::index_read_idx(byte* buf, uint index, const byte * key, +int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, uint key_len __attribute__ ((unused)), enum ha_rkey_function find_flag __attribute__ ((unused))) @@ -1411,7 +1412,7 @@ int ha_federated::index_read_idx(byte* buf, uint index, const byte * key, DBUG_PRINT("ha_federated::index_read_idx", ("current key %d key value %s index_string value %s length %d", - index, (char*) (key), index_string.c_ptr_quick(), + index, (char*) key, index_string.c_ptr_quick(), index_string.length())); DBUG_PRINT("ha_federated::index_read_idx", @@ -1461,7 +1462,7 @@ int ha_federated::index_init(uint keynr) /* Used to read forward through the index. */ -int ha_federated::index_next(byte* buf) +int ha_federated::index_next(byte *buf) { DBUG_ENTER("ha_federated::index_next"); DBUG_RETURN(rnd_next(buf)); @@ -1553,7 +1554,7 @@ int ha_federated::index_end(void) Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc, and sql_update.cc. */ -int ha_federated::rnd_next(byte* buf) +int ha_federated::rnd_next(byte *buf) { MYSQL_ROW row; DBUG_ENTER("ha_federated::rnd_next"); @@ -1601,7 +1602,7 @@ void ha_federated::position(const byte *record) Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc. */ -int ha_federated::rnd_pos(byte* buf, byte *pos) +int ha_federated::rnd_pos(byte *buf, byte *pos) { DBUG_ENTER("ha_federated::rnd_pos"); /* @@ -1613,10 +1614,8 @@ int ha_federated::rnd_pos(byte* buf, byte *pos) { statistic_increment(table->in_use->status_var.ha_read_rnd_count, &LOCK_status); - /* - pos is not aligned - */ - memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); + memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos + /* is not aligned */ result->current_row= 0; result->data_cursor= current_position; DBUG_RETURN(rnd_next(buf)); @@ -1668,11 +1667,11 @@ int ha_federated::rnd_pos(byte* buf, byte *pos) sql_update.cc */ -// FIX: later version provide better information to the optimizer +/* FIX: later version provide better information to the optimizer */ void ha_federated::info(uint flag) { DBUG_ENTER("ha_federated::info"); - records= 10000; // Fake! + records= 10000; // fix later DBUG_VOID_RETURN; } diff --git a/sql/ha_federated.h b/sql/ha_federated.h index 04bbf2a56f6..e75fd285338 100755 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -73,7 +73,8 @@ private: return errorcode otherwise */ uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row); - bool ha_federated::create_where_from_key(String *to, KEY *key_info, const byte *key, uint key_length); + bool ha_federated::create_where_from_key(String *to, KEY *key_info, + const byte *key, uint key_length); public: ha_federated(TABLE *table): handler(table), @@ -127,11 +128,16 @@ public: /* Called in test_quick_select to determine if indexes should be used. */ - virtual double scan_time() { DBUG_PRINT("ha_federated::scan_time", ("rows %d", records)); return (double)(records*2); } + virtual double scan_time() + { + DBUG_PRINT("ha_federated::scan_time", + ("rows %d", records)); return (double)(records*2); + } /* The next method will never be called if you do not implement indexes. */ - virtual double read_time(uint index, uint ranges, ha_rows rows) { return (double) rows / 20.0+1; } + virtual double read_time(uint index, uint ranges, ha_rows rows) + { return (double) rows / 20.0+1; } /* Everything below are methods that we implment in ha_federated.cc. From 488de6cc3fbf7f69f655c2c7135517fe78f63c85 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 19 Feb 2005 10:45:19 -0800 Subject: [PATCH 04/20] WL# 2094, Federated Storage Handler. This patch fixes bug #8599, HPUX compile errors. Testing on hp3750 shows these fixes fix the compile problems on HPUX, but I have a problem where when I run the tests, the test shows that the tables default to MyISAM! include/mysql.h: HPUX's compiler does not like 'ulong' - the compile fails due to this. sql/ha_federated.h: Serg's recommendation to fix bug #8599 (which is a good fix since it's obviously from when I added the method via cut and paste ;). Also caught some comment style issues. --- include/mysql.h | 2 +- sql/ha_federated.h | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index e37cf710817..828d38f5ec4 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -499,7 +499,7 @@ MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset); MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); -void STDCALL cli_fetch_lengths(ulong *to, MYSQL_ROW column, +void STDCALL cli_fetch_lengths(unsigned long *to, MYSQL_ROW column, unsigned int field_count); MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, diff --git a/sql/ha_federated.h b/sql/ha_federated.h index e75fd285338..28f28f8aa63 100755 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -32,13 +32,16 @@ FEDERATED_SHARE is a structure that will be shared amoung all open handlers The example implements the minimum of what you will probably need. */ -//FIX document typedef struct st_federated_share { char *table_name; char *table_base_name; - // the primary select query to be used in rnd_init + /* + the primary select query to be used in rnd_init + */ char *select_query; - // remote host info, parse_url supplies + /* + remote host info, parse_url supplies + */ char *scheme; char *hostname; char *username; @@ -73,8 +76,8 @@ private: return errorcode otherwise */ uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row); - bool ha_federated::create_where_from_key(String *to, KEY *key_info, - const byte *key, uint key_length); + bool create_where_from_key(String *to, KEY *key_info, + const byte *key, uint key_length); public: ha_federated(TABLE *table): handler(table), From aec302676a839c41e69399bf73091273f1c0b60f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Feb 2005 00:29:57 -0800 Subject: [PATCH 05/20] WL #2094 Federated Storage Handler This is the first changeset of suggested changes recommended in Kostja's review of my patch, 1.1846, which includes only functionality changes. Style changes/Documentation patch to follow. include/mysql.h: removed declaration of cli_fetch_lengths per Kostja's suggestion libmysql/libmysql.c: moved mysql_fetch_lengths to client.c (for server to access) per Kostja's suggestion sql-common/client.c: added back 'static' to function definition, added mysql_fetch_lengths sql/ha_federated.cc: changed to use defines as opposed to hardcoded values sql/ha_federated.h: took out duplicate table_flag, fixed a resolve mistake --- include/mysql.h | 2 -- libmysql/libmysql.c | 19 ------------------- sql-common/client.c | 21 ++++++++++++++++++++- sql/ha_federated.cc | 11 ++++------- sql/ha_federated.h | 7 +++---- 5 files changed, 27 insertions(+), 33 deletions(-) diff --git a/include/mysql.h b/include/mysql.h index 828d38f5ec4..b87b865608e 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -499,8 +499,6 @@ MYSQL_FIELD_OFFSET STDCALL mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET offset); MYSQL_ROW STDCALL mysql_fetch_row(MYSQL_RES *result); unsigned long * STDCALL mysql_fetch_lengths(MYSQL_RES *result); -void STDCALL cli_fetch_lengths(unsigned long *to, MYSQL_ROW column, - unsigned int field_count); MYSQL_FIELD * STDCALL mysql_fetch_field(MYSQL_RES *result); MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table, const char *wild); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 1ef29210c0b..20a000f1e4d 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1115,25 +1115,6 @@ mysql_fetch_field(MYSQL_RES *result) } -/************************************************************************** - Get column lengths of the current row - If one uses mysql_use_result, res->lengths contains the length information, - else the lengths are calculated from the offset between pointers. -**************************************************************************/ - -ulong * STDCALL -mysql_fetch_lengths(MYSQL_RES *res) -{ - MYSQL_ROW column; - - if (!(column=res->current_row)) - return 0; /* Something is wrong */ - if (res->data) - (*res->methods->fetch_lengths)(res->lengths, column, res->field_count); - return res->lengths; -} - - /************************************************************************** Move to a specific row and column **************************************************************************/ diff --git a/sql-common/client.c b/sql-common/client.c index 2e60b8aad24..aece4230fe0 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1121,7 +1121,7 @@ void mysql_read_default_options(struct st_mysql_options *options, else the lengths are calculated from the offset between pointers. **************************************************************************/ -void cli_fetch_lengths(ulong *to, MYSQL_ROW column, +static void cli_fetch_lengths(ulong *to, MYSQL_ROW column, unsigned int field_count) { ulong *prev_length; @@ -2628,6 +2628,25 @@ mysql_fetch_row(MYSQL_RES *res) } +/************************************************************************** + Get column lengths of the current row + If one uses mysql_use_result, res->lengths contains the length information, + else the lengths are calculated from the offset between pointers. +**************************************************************************/ + +ulong * STDCALL +mysql_fetch_lengths(MYSQL_RES *res) +{ + MYSQL_ROW column; + + if (!(column=res->current_row)) + return 0; /* Something is wrong */ + if (res->data) + (*res->methods->fetch_lengths)(res->lengths, column, res->field_count); + return res->lengths; +} + + int STDCALL mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) { diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index ae6cb1f76be..cf704f9f569 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -560,10 +560,10 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, if (!share->port) { - if (strcmp(share->hostname, "localhost") == 0) - share->socket= my_strdup("/tmp/mysql.sock", MYF(0)); + if (strcmp(share->hostname, my_localhost) == 0) + share->socket= my_strdup(MYSQL_UNIX_ADDR, MYF(0)); else - share->port= 3306; + share->port= MYSQL_PORT; } DBUG_PRINT("ha_federated::parse_url", @@ -616,8 +616,7 @@ uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) DBUG_ENTER("ha_federated::convert_row_to_internal_format"); num_fields= mysql_num_fields(result); - lengths= (ulong*) my_malloc(num_fields * sizeof(ulong), MYF(0)); - cli_fetch_lengths((ulong*) lengths, row, num_fields); + lengths= mysql_fetch_lengths(result); memset(record, 0, table->s->null_bytes); @@ -628,8 +627,6 @@ uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) else (*field)->store(row[x], lengths[x], &my_charset_bin); } - my_free((gptr) lengths, MYF(0)); - lengths= 0; DBUG_RETURN(0); } diff --git a/sql/ha_federated.h b/sql/ha_federated.h index f685aa9e3f9..22fc03e9eec 100755 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -76,7 +76,6 @@ private: return errorcode otherwise */ uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row); - bool create_where_from_key(String *to, KEY *key_info, const byte *key, uint key_length); bool create_where_from_key(String *to, KEY *key_info, const byte *key, uint key_length); @@ -106,9 +105,9 @@ public: */ ulong table_flags() const { - return (HA_TABLE_SCAN_ON_INDEX | HA_NOT_EXACT_COUNT | - HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED | HA_AUTO_PART_KEY | - HA_TABLE_SCAN_ON_INDEX | HA_CAN_INDEX_BLOBS); + return (HA_TABLE_SCAN_ON_INDEX | HA_NOT_EXACT_COUNT | + HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED | + HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS); } /* This is a bitmap of flags that says how the storage engine From f6c9db08b6cf5dd243e422dce7a5c7aaf8781c40 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Feb 2005 00:38:29 -0800 Subject: [PATCH 06/20] WL# 2094 Federated Storage Handler Patch #2, all coding style changes per Kostja's review (as requested to keep style changes separate from functionality changes), as well as changes to the test suit to no longer use hard-coded port values in foreign table creation statement mysql-test/r/federated.result: Now using SLAVE_PORT as opposed to hard-coded port value mysql-test/t/federated.test: - changed test to use SLAVE_MYPORT - made all standard SQL uppercase - made test 80 cols, except blob inserts of text sql/ha_federated.cc: - made sure all comments and style changes were according to Kostja's review - combined parse_url error handling into a 'error:' block, took out triple exclamation points. - clarified commented documentation - got rid of all trailing spaces --- mysql-test/r/federated.result | 503 ++++++++++++++++++------------ mysql-test/t/federated.test | 563 +++++++++++++++++++++------------- sql/ha_federated.cc | 478 +++++++++++++++-------------- 3 files changed, 919 insertions(+), 625 deletions(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index d1ad9921865..00c52a53c42 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -5,23 +5,40 @@ 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; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32) NOT NULL default '', `other` int(20) NOT NULL default '0', created datetime default '2004-04-04 04:04:04', PRIMARY KEY (`id`), KEY `name` (`name`), KEY `other_key` (`other`)) DEFAULT CHARSET=latin1; -drop database if exists federated; -create database federated; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32) NOT NULL default '', `other` int(20) NOT NULL default '0', created datetime default '2004-04-04 04:04:04', PRIMARY KEY (`id`), KEY `name` (`name`), KEY `other_key` (`other`)) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, other) values ('First Name', 11111); -insert into federated.t1 (name, other) values ('Second Name', 22222); -insert into federated.t1 (name, other) values ('Third Name', 33333); -insert into federated.t1 (name, other) values ('Fourth Name', 44444); -insert into federated.t1 (name, other) values ('Fifth Name', 55555); -insert into federated.t1 (name, other) values ('Sixth Name', 66666); -insert into federated.t1 (name, other) values ('Seventh Name', 77777); -insert into federated.t1 (name, other) values ('Eigth Name', 88888); -insert into federated.t1 (name, other) values ('Ninth Name', 99999); -insert into federated.t1 (name, other) values ('Tenth Name', 101010); -select * from federated.t1; +DROP DATABASE IF EXISTS federated; +CREATE DATABASE federated; +CREATE TABLE federated.t1 ( +`id` int(20) NOT NULL auto_increment, +`name` varchar(32) NOT NULL default '', +`other` int(20) NOT NULL default '0', +`created` datetime default '2004-04-04 04:04:04', +PRIMARY KEY (`id`), +KEY `name` (`name`), +KEY `other_key` (`other`)) +DEFAULT CHARSET=latin1; +DROP DATABASE IF EXISTS federated; +CREATE DATABASE federated; +CREATE TABLE federated.t1 ( +`id` int(20) NOT NULL auto_increment, +`name` varchar(32) NOT NULL default '', +`other` int(20) NOT NULL default '0', +`created` datetime default '2004-04-04 04:04:04', +PRIMARY KEY (`id`), +KEY `name` (`name`), +KEY `other_key` (`other`)) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 (name, other) VALUES ('First Name', 11111); +INSERT INTO federated.t1 (name, other) VALUES ('Second Name', 22222); +INSERT INTO federated.t1 (name, other) VALUES ('Third Name', 33333); +INSERT INTO federated.t1 (name, other) VALUES ('Fourth Name', 44444); +INSERT INTO federated.t1 (name, other) VALUES ('Fifth Name', 55555); +INSERT INTO federated.t1 (name, other) VALUES ('Sixth Name', 66666); +INSERT INTO federated.t1 (name, other) VALUES ('Seventh Name', 77777); +INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888); +INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999); +INSERT INTO federated.t1 (name, other) VALUES ('Tenth Name', 101010); +SELECT * FROM federated.t1; id name other created 1 First Name 11111 2004-04-04 04:04:04 2 Second Name 22222 2004-04-04 04:04:04 @@ -33,19 +50,19 @@ id name other created 8 Eigth Name 88888 2004-04-04 04:04:04 9 Ninth Name 99999 2004-04-04 04:04:04 10 Tenth Name 101010 2004-04-04 04:04:04 -select * from federated.t1 where id = 5; +SELECT * FROM federated.t1 WHERE id = 5; id name other created 5 Fifth Name 55555 2004-04-04 04:04:04 -select * from federated.t1 where name = 'Sixth Name'; +SELECT * FROM federated.t1 WHERE name = 'Sixth Name'; id name other created 6 Sixth Name 66666 2004-04-04 04:04:04 -select * from federated.t1 where id = 6 and name = 'Sixth Name'; +SELECT * FROM federated.t1 WHERE id = 6 and name = 'Sixth Name'; id name other created 6 Sixth Name 66666 2004-04-04 04:04:04 -select * from federated.t1 where other = 44444; +SELECT * FROM federated.t1 WHERE other = 44444; id name other created 4 Fourth Name 44444 2004-04-04 04:04:04 -select * from federated.t1 where name like '%th%'; +SELECT * FROM federated.t1 WHERE name like '%th%'; id name other created 3 Third Name 33333 2004-04-04 04:04:04 4 Fourth Name 44444 2004-04-04 04:04:04 @@ -55,15 +72,15 @@ id name other created 8 Eigth Name 88888 2004-04-04 04:04:04 9 Ninth Name 99999 2004-04-04 04:04:04 10 Tenth Name 101010 2004-04-04 04:04:04 -update federated.t1 set name = '3rd name' where id = 3; -select * from federated.t1 where name = '3rd name'; +UPDATE federated.t1 SET name = '3rd name' WHERE id = 3; +SELECT * FROM federated.t1 WHERE name = '3rd name'; id name other created 3 3rd name 33333 2004-04-04 04:04:04 -update federated.t1 set name = 'Third name' where name = '3rd name'; -select * from federated.t1 where name = 'Third name'; +UPDATE federated.t1 SET name = 'Third name' WHERE name = '3rd name'; +SELECT * FROM federated.t1 WHERE name = 'Third name'; id name other created 3 Third name 33333 2004-04-04 04:04:04 -select * from federated.t1 order by id DESC; +SELECT * FROM federated.t1 ORDER BY id DESC; id name other created 10 Tenth Name 101010 2004-04-04 04:04:04 9 Ninth Name 99999 2004-04-04 04:04:04 @@ -75,7 +92,7 @@ id name other created 3 Third name 33333 2004-04-04 04:04:04 2 Second Name 22222 2004-04-04 04:04:04 1 First Name 11111 2004-04-04 04:04:04 -select * from federated.t1 order by name; +SELECT * FROM federated.t1 ORDER BY name; id name other created 8 Eigth Name 88888 2004-04-04 04:04:04 5 Fifth Name 55555 2004-04-04 04:04:04 @@ -87,7 +104,7 @@ id name other created 6 Sixth Name 66666 2004-04-04 04:04:04 10 Tenth Name 101010 2004-04-04 04:04:04 3 Third name 33333 2004-04-04 04:04:04 -select * from federated.t1 order by name DESC; +SELECT * FROM federated.t1 ORDER BY name DESC; id name other created 3 Third name 33333 2004-04-04 04:04:04 10 Tenth Name 101010 2004-04-04 04:04:04 @@ -99,7 +116,7 @@ id name other created 1 First Name 11111 2004-04-04 04:04:04 5 Fifth Name 55555 2004-04-04 04:04:04 8 Eigth Name 88888 2004-04-04 04:04:04 -select * from federated.t1 order by name ASC; +SELECT * FROM federated.t1 ORDER BY name ASC; id name other created 8 Eigth Name 88888 2004-04-04 04:04:04 5 Fifth Name 55555 2004-04-04 04:04:04 @@ -111,7 +128,7 @@ id name other created 6 Sixth Name 66666 2004-04-04 04:04:04 10 Tenth Name 101010 2004-04-04 04:04:04 3 Third name 33333 2004-04-04 04:04:04 -select * from federated.t1 group by other; +SELECT * FROM federated.t1 GROUP BY other; id name other created 1 First Name 11111 2004-04-04 04:04:04 2 Second Name 22222 2004-04-04 04:04:04 @@ -123,52 +140,65 @@ id name other created 8 Eigth Name 88888 2004-04-04 04:04:04 9 Ninth Name 99999 2004-04-04 04:04:04 10 Tenth Name 101010 2004-04-04 04:04:04 -delete from federated.t1 where id = 5; -select * from federated.t1 where id = 5; +DELETE FROM federated.t1 WHERE id = 5; +SELECT * FROM federated.t1 WHERE id = 5; id name other created -delete from federated.t1; -select * from federated.t1 where id = 5; +DELETE FROM federated.t1; +SELECT * FROM federated.t1 WHERE id = 5; id name other created -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`) ); -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, other) values ('First Name', 11111); -insert into federated.t1 (name, other) values ('Second Name', NULL); -insert into federated.t1 (name, other) values ('Third Name', 33333); -insert into federated.t1 (name, other) values (NULL, NULL); -insert into federated.t1 (name, other) values ('Fifth Name', 55555); -insert into federated.t1 (name, other) values ('Sixth Name', 66666); -insert into federated.t1 (name) values ('Seventh Name'); -insert into federated.t1 (name, other) values ('Eigth Name', 88888); -insert into federated.t1 (name, other) values ('Ninth Name', 99999); -insert into federated.t1 (other) values ('fee fie foe fum'); -select * from federated.t1 where other IS NULL; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int(20) NOT NULL auto_increment, +`name` varchar(32), +`other` varchar(20), +PRIMARY KEY (`id`) ); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int(20) NOT NULL auto_increment, +`name` varchar(32), +`other` varchar(20), +PRIMARY KEY (`id`) ) +ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 (name, other) VALUES ('First Name', 11111); +INSERT INTO federated.t1 (name, other) VALUES ('Second Name', NULL); +INSERT INTO federated.t1 (name, other) VALUES ('Third Name', 33333); +INSERT INTO federated.t1 (name, other) VALUES (NULL, NULL); +INSERT INTO federated.t1 (name, other) VALUES ('Fifth Name', 55555); +INSERT INTO federated.t1 (name, other) VALUES ('Sixth Name', 66666); +INSERT INTO federated.t1 (name) VALUES ('Seventh Name'); +INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888); +INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999); +INSERT INTO federated.t1 (other) VALUES ('fee fie foe fum'); +SELECT * FROM federated.t1 WHERE other IS NULL; id name other 2 Second Name NULL 4 NULL NULL 7 Seventh Name NULL -select * from federated.t1 where name IS NULL; +SELECT * FROM federated.t1 WHERE name IS NULL; id name other 4 NULL NULL 10 NULL fee fie foe fum -select * from federated.t1 where name IS NULL and other IS NULL; +SELECT * FROM federated.t1 WHERE name IS NULL and other IS NULL; id name other 4 NULL NULL -select * from federated.t1 where name IS NULL or other IS NULL; +SELECT * FROM federated.t1 WHERE name IS NULL or other IS NULL; id name other 2 Second Name NULL 4 NULL NULL 7 Seventh Name NULL 10 NULL fee fie foe fum -update federated.t1 set name = 'Fourth Name', other = 'four four four' where name IS NULL and other IS NULL; -update federated.t1 set other = 'two two two two' where name = 'Second Name'; -update federated.t1 set other = 'seven seven' where name like 'Sec%'; -update federated.t1 set other = 'seven seven' where name = 'Seventh Name'; -update federated.t1 set name = 'Tenth Name' where other like 'fee fie%'; -select * from federated.t1 where name IS NULL or other IS NULL ; +UPDATE federated.t1 +SET name = 'Fourth Name', other = 'four four four' +WHERE name IS NULL AND other IS NULL; +UPDATE federated.t1 SET other = 'two two two two' WHERE name = 'Second Name'; +UPDATE federated.t1 SET other = 'seven seven' WHERE name like 'Sec%'; +UPDATE federated.t1 SET other = 'seven seven' WHERE name = 'Seventh Name'; +UPDATE federated.t1 SET name = 'Tenth Name' WHERE other like 'fee fie%'; +SELECT * FROM federated.t1 WHERE name IS NULL OR other IS NULL ; id name other -select * from federated.t1; +SELECT * FROM federated.t1; id name other 1 First Name 11111 2 Second Name seven seven @@ -180,149 +210,206 @@ id name other 8 Eigth Name 88888 9 Ninth Name 99999 10 Tenth Name fee fie foe fum -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` -varchar(32) NOT NULL DEFAULT '', `other` varchar(20) NOT NULL DEFAULT '', PRIMARY KEY (`id`), key nameoth (name, other) ); -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32) NOT NULL DEFAULT '', `other` varchar(20) NOT NULL DEFAULT '', PRIMARY KEY (`id`), key nameoth (name, other)) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, other) values ('First Name', '1111'); -insert into federated.t1 (name, other) values ('Second Name', '2222'); -insert into federated.t1 (name, other) values ('Third Name', '3333'); -select * from federated.t1 where name = 'Second Name'; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int(20) NOT NULL auto_increment, +`name` varchar(32) NOT NULL DEFAULT '', +`other` varchar(20) NOT NULL DEFAULT '', +PRIMARY KEY (`id`), +KEY nameoth (name, other) ); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int(20) NOT NULL auto_increment, +`name` varchar(32) NOT NULL DEFAULT '', +`other` varchar(20) NOT NULL DEFAULT '', +PRIMARY KEY (`id`), +KEY nameoth (name, other)) +ENGINE="FEDERATED" DEFAULT +CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 (name, other) VALUES ('First Name', '1111'); +INSERT INTO federated.t1 (name, other) VALUES ('Second Name', '2222'); +INSERT INTO federated.t1 (name, other) VALUES ('Third Name', '3333'); +SELECT * FROM federated.t1 WHERE name = 'Second Name'; id name other 2 Second Name 2222 -select * from federated.t1 where other = '2222'; +SELECT * FROM federated.t1 WHERE other = '2222'; id name other 2 Second Name 2222 -select * from federated.t1 where name = 'Third Name'; +SELECT * FROM federated.t1 WHERE name = 'Third Name'; id name other 3 Third Name 3333 -select * from federated.t1 where name = 'Third Name' and other = '3333'; +SELECT * FROM federated.t1 WHERE name = 'Third Name' AND other = '3333'; id name other 3 Third Name 3333 -drop table if exists federated.t1; -CREATE TABLE federated.t1 -(id int NOT NULL auto_increment, -name char(32) NOT NULL DEFAULT '', -bincol binary(4) NOT NULL, -floatval decimal(5,2) NOT NULL DEFAULT 0.0, -other int NOT NULL DEFAULT 0, -primary key(id), -key nameoth(name, other), -key bincol(bincol), -key floatval(floatval)); -drop table if exists federated.t1; -CREATE TABLE federated.t1 -(id int NOT NULL auto_increment, -name char(32) NOT NULL DEFAULT '', -bincol binary(4) NOT NULL, -floatval decimal(5,2) NOT NULL DEFAULT 0.0, -other int NOT NULL DEFAULT 0, -primary key(id), -key nameoth(name,other), -key bincol(bincol), -key floatval(floatval)) -ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, bincol, floatval, other) values ('first', 0x65, 11.11, 1111); -insert into federated.t1 (name, bincol, floatval, other) values ('second', 0x66, 22.22, 2222); -insert into federated.t1 (name, bincol, floatval, other) values ('third', 'g', 22.22, 2222); -select * from federated.t1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int NOT NULL auto_increment, +`name` char(32) NOT NULL DEFAULT '', +`bincol` binary(4) NOT NULL, +`floatval` decimal(5,2) NOT NULL DEFAULT 0.0, +`other` int NOT NULL DEFAULT 0, +PRIMARY KEY (id), +KEY nameoth(name, other), +KEY bincol(bincol), +KEY floatval(floatval)); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int NOT NULL auto_increment, +`name` char(32) NOT NULL DEFAULT '', +`bincol` binary(4) NOT NULL, +`floatval` decimal(5,2) NOT NULL DEFAULT 0.0, +`other` int NOT NULL DEFAULT 0, +PRIMARY KEY (id), +KEY nameoth(name,other), +KEY bincol(bincol), +KEY floatval(floatval)) +ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 (name, bincol, floatval, other) +VALUES ('first', 0x65, 11.11, 1111); +INSERT INTO federated.t1 (name, bincol, floatval, other) +VALUES ('second', 0x66, 22.22, 2222); +INSERT INTO federated.t1 (name, bincol, floatval, other) +VALUES ('third', 'g', 22.22, 2222); +SELECT * FROM federated.t1; id name bincol floatval other 1 first e 11.11 1111 2 second f 22.22 2222 3 third g 22.22 2222 -select * from federated.t1 where name = 'second'; +SELECT * FROM federated.t1 WHERE name = 'second'; id name bincol floatval other 2 second f 22.22 2222 -select * from federated.t1 where bincol= 'f'; +SELECT * FROM federated.t1 WHERE bincol= 'f'; id name bincol floatval other 2 second f 22.22 2222 -select * from federated.t1 where bincol= 0x66; +SELECT * FROM federated.t1 WHERE bincol= 0x66; id name bincol floatval other 2 second f 22.22 2222 -select * from federated.t1 where bincol= 0x67; +SELECT * FROM federated.t1 WHERE bincol= 0x67; id name bincol floatval other 3 third g 22.22 2222 -select * from federated.t1 where bincol= 'g'; +SELECT * FROM federated.t1 WHERE bincol= 'g'; id name bincol floatval other 3 third g 22.22 2222 -select * from federated.t1 where floatval=11.11; +SELECT * FROM federated.t1 WHERE floatval=11.11; id name bincol floatval other 1 first e 11.11 1111 -select * from federated.t1 where name='third'; +SELECT * FROM federated.t1 WHERE name='third'; id name bincol floatval other 3 third g 22.22 2222 -select * from federated.t1 where other=2222; +SELECT * FROM federated.t1 WHERE other=2222; id name bincol floatval other 2 second f 22.22 2222 3 third g 22.22 2222 -select * from federated.t1 where name='third' and other=2222; +SELECT * FROM federated.t1 WHERE name='third' and other=2222; id name bincol floatval other 3 third g 22.22 2222 -drop table if exists federated.t1; -CREATE TABLE federated.t1 (id int, name varchar(32), floatval float, other int) DEFAULT CHARSET=latin1; -drop table if exists federated.t1; -CREATE TABLE federated.t1 (id int, name varchar(32), floatval float, other int) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 values (NULL, NULL, NULL, NULL); -insert into federated.t1 values (); -insert into federated.t1 (id) values (1); -insert into federated.t1 (name, floatval, other) values ('foo', 33.33333332, NULL); -insert into federated.t1 (name, floatval, other) values (0, 00.3333, NULL); -select * from federated.t1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int, +`name` varchar(32), +`floatval` float, +`other` int) +DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int, +`name` varchar(32), +`floatval` float, +`other` int) +ENGINE="FEDERATED" +DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 values (NULL, NULL, NULL, NULL); +INSERT INTO federated.t1 values (); +INSERT INTO federated.t1 (id) VALUES (1); +INSERT INTO federated.t1 (name, floatval, other) +VALUES ('foo', 33.33333332, NULL); +INSERT INTO federated.t1 (name, floatval, other) +VALUES (0, 00.3333, NULL); +SELECT * FROM federated.t1; id name floatval other NULL NULL NULL NULL NULL NULL NULL NULL 1 NULL NULL NULL NULL foo 33.3333 NULL NULL 0 0.3333 NULL -select count(*) from federated.t1 where id IS NULL and name IS NULL and floatval IS NULL and other IS NULL; +SELECT count(*) FROM federated.t1 +WHERE id IS NULL +AND name IS NULL +AND floatval IS NULL +AND other IS NULL; count(*) 2 -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( blurb_id int NOT NULL DEFAULT 0, blurb text default '', primary key(blurb_id)) DEFAULT CHARSET=latin1; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( blurb_id int NOT NULL DEFAULT 0, blurb text default '', primary key(blurb_id)) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`blurb_id` int NOT NULL DEFAULT 0, +`blurb` text default '', +PRIMARY KEY (blurb_id)) +DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`blurb_id` int NOT NULL DEFAULT 0, +`blurb` text default '', +PRIMARY KEY (blurb_id)) +ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; INSERT INTO federated.t1 VALUES (1, " MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values."); INSERT INTO federated.t1 VALUES (2, "All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE."); INSERT INTO federated.t1 VALUES (3, " A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. "); INSERT INTO federated.t1 VALUES(4, "Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:"); -select * from federated.t1; +SELECT * FROM federated.t1; blurb_id blurb 1 MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values. 2 All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE. 3 A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. 4 Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt: -drop table if exists federated.t1; -create table federated.t1 (a int not null, b int not null, c int not null, primary key (a),key(b)); -drop table if exists federated.t1; -create table federated.t1 (a int not null, b int not null, c int not null, primary key (a),key(b)) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 values (3,3,3),(1,1,1),(2,2,2),(4,4,4); -explain select * from federated.t1 order by a; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`a` int NOT NULL, +`b` int NOT NULL, +`c` int NOT NULL, +PRIMARY KEY (a),key(b)); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`a` int NOT NULL, +`b` int NOT NULL, +`c` int NOT NULL, +PRIMARY KEY (a), +KEY (b)) +ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 VALUES (3,3,3),(1,1,1),(2,2,2),(4,4,4); +EXPLAIN SELECT * FROM federated.t1 ORDER BY a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 Using filesort -explain select * from federated.t1 order by b; +EXPLAIN SELECT * FROM federated.t1 ORDER BY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 Using filesort -explain select * from federated.t1 order by c; +EXPLAIN SELECT * FROM federated.t1 ORDER BY c; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 Using filesort -explain select a from federated.t1 order by a; +EXPLAIN SELECT a FROM federated.t1 ORDER BY a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 Using filesort -explain select b from federated.t1 order by b; +EXPLAIN SELECT b FROM federated.t1 ORDER BY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 Using filesort -explain select a,b from federated.t1 order by b; +EXPLAIN SELECT a,b FROM federated.t1 ORDER BY b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 Using filesort -explain select a,b from federated.t1; +EXPLAIN SELECT a,b FROM federated.t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 -explain select a,b,c from federated.t1; +EXPLAIN SELECT a,b,c FROM federated.t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 -drop table if exists federated.t1; -create table federated.t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17 int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int, i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34 @@ -447,10 +534,11 @@ int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982 int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990 int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998 int, i999 int, i1000 int, b blob) row_format=dynamic; -drop table if exists federated.t1; -create table federated.t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 -int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17 -int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int, +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 +(i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 +int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, +i17 int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int, i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34 int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int, i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51 @@ -572,8 +660,13 @@ int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974 int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982 int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990 int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998 -int, i999 int, i1000 int, b blob) row_format=dynamic ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +int, i999 int, i1000 int, b blob) +row_format=dynamic +ENGINE="FEDERATED" +DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 +values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -612,41 +705,54 @@ insert into federated.t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "PatrickG"); -update federated.t1 set b=repeat('a',256); -update federated.t1 set i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0, i10=0; -select * from federated.t1 where i9=0 and i10=0; +UPDATE federated.t1 SET b=repeat('a',256); +UPDATE federated.t1 SET i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0, i10=0; +SELECT * FROM federated.t1 WHERE i9=0 and i10=0; i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30 i31 i32 i33 i34 i35 i36 i37 i38 i39 i40 i41 i42 i43 i44 i45 i46 i47 i48 i49 i50 i51 i52 i53 i54 i55 i56 i57 i58 i59 i60 i61 i62 i63 i64 i65 i66 i67 i68 i69 i70 i71 i72 i73 i74 i75 i76 i77 i78 i79 i80 i81 i82 i83 i84 i85 i86 i87 i88 i89 i90 i91 i92 i93 i94 i95 i96 i97 i98 i99 i100 i101 i102 i103 i104 i105 i106 i107 i108 i109 i110 i111 i112 i113 i114 i115 i116 i117 i118 i119 i120 i121 i122 i123 i124 i125 i126 i127 i128 i129 i130 i131 i132 i133 i134 i135 i136 i137 i138 i139 i140 i141 i142 i143 i144 i145 i146 i147 i148 i149 i150 i151 i152 i153 i154 i155 i156 i157 i158 i159 i160 i161 i162 i163 i164 i165 i166 i167 i168 i169 i170 i171 i172 i173 i174 i175 i176 i177 i178 i179 i180 i181 i182 i183 i184 i185 i186 i187 i188 i189 i190 i191 i192 i193 i194 i195 i196 i197 i198 i199 i200 i201 i202 i203 i204 i205 i206 i207 i208 i209 i210 i211 i212 i213 i214 i215 i216 i217 i218 i219 i220 i221 i222 i223 i224 i225 i226 i227 i228 i229 i230 i231 i232 i233 i234 i235 i236 i237 i238 i239 i240 i241 i242 i243 i244 i245 i246 i247 i248 i249 i250 i251 i252 i253 i254 i255 i256 i257 i258 i259 i260 i261 i262 i263 i264 i265 i266 i267 i268 i269 i270 i271 i272 i273 i274 i275 i276 i277 i278 i279 i280 i281 i282 i283 i284 i285 i286 i287 i288 i289 i290 i291 i292 i293 i294 i295 i296 i297 i298 i299 i300 i301 i302 i303 i304 i305 i306 i307 i308 i309 i310 i311 i312 i313 i314 i315 i316 i317 i318 i319 i320 i321 i322 i323 i324 i325 i326 i327 i328 i329 i330 i331 i332 i333 i334 i335 i336 i337 i338 i339 i340 i341 i342 i343 i344 i345 i346 i347 i348 i349 i350 i351 i352 i353 i354 i355 i356 i357 i358 i359 i360 i361 i362 i363 i364 i365 i366 i367 i368 i369 i370 i371 i372 i373 i374 i375 i376 i377 i378 i379 i380 i381 i382 i383 i384 i385 i386 i387 i388 i389 i390 i391 i392 i393 i394 i395 i396 i397 i398 i399 i400 i401 i402 i403 i404 i405 i406 i407 i408 i409 i410 i411 i412 i413 i414 i415 i416 i417 i418 i419 i420 i421 i422 i423 i424 i425 i426 i427 i428 i429 i430 i431 i432 i433 i434 i435 i436 i437 i438 i439 i440 i441 i442 i443 i444 i445 i446 i447 i448 i449 i450 i451 i452 i453 i454 i455 i456 i457 i458 i459 i460 i461 i462 i463 i464 i465 i466 i467 i468 i469 i470 i471 i472 i473 i474 i475 i476 i477 i478 i479 i480 i481 i482 i483 i484 i485 i486 i487 i488 i489 i490 i491 i492 i493 i494 i495 i496 i497 i498 i499 i500 i501 i502 i503 i504 i505 i506 i507 i508 i509 i510 i511 i512 i513 i514 i515 i516 i517 i518 i519 i520 i521 i522 i523 i524 i525 i526 i527 i528 i529 i530 i531 i532 i533 i534 i535 i536 i537 i538 i539 i540 i541 i542 i543 i544 i545 i546 i547 i548 i549 i550 i551 i552 i553 i554 i555 i556 i557 i558 i559 i560 i561 i562 i563 i564 i565 i566 i567 i568 i569 i570 i571 i572 i573 i574 i575 i576 i577 i578 i579 i580 i581 i582 i583 i584 i585 i586 i587 i588 i589 i590 i591 i592 i593 i594 i595 i596 i597 i598 i599 i600 i601 i602 i603 i604 i605 i606 i607 i608 i609 i610 i611 i612 i613 i614 i615 i616 i617 i618 i619 i620 i621 i622 i623 i624 i625 i626 i627 i628 i629 i630 i631 i632 i633 i634 i635 i636 i637 i638 i639 i640 i641 i642 i643 i644 i645 i646 i647 i648 i649 i650 i651 i652 i653 i654 i655 i656 i657 i658 i659 i660 i661 i662 i663 i664 i665 i666 i667 i668 i669 i670 i671 i672 i673 i674 i675 i676 i677 i678 i679 i680 i681 i682 i683 i684 i685 i686 i687 i688 i689 i690 i691 i692 i693 i694 i695 i696 i697 i698 i699 i700 i701 i702 i703 i704 i705 i706 i707 i708 i709 i710 i711 i712 i713 i714 i715 i716 i717 i718 i719 i720 i721 i722 i723 i724 i725 i726 i727 i728 i729 i730 i731 i732 i733 i734 i735 i736 i737 i738 i739 i740 i741 i742 i743 i744 i745 i746 i747 i748 i749 i750 i751 i752 i753 i754 i755 i756 i757 i758 i759 i760 i761 i762 i763 i764 i765 i766 i767 i768 i769 i770 i771 i772 i773 i774 i775 i776 i777 i778 i779 i780 i781 i782 i783 i784 i785 i786 i787 i788 i789 i790 i791 i792 i793 i794 i795 i796 i797 i798 i799 i800 i801 i802 i803 i804 i805 i806 i807 i808 i809 i810 i811 i812 i813 i814 i815 i816 i817 i818 i819 i820 i821 i822 i823 i824 i825 i826 i827 i828 i829 i830 i831 i832 i833 i834 i835 i836 i837 i838 i839 i840 i841 i842 i843 i844 i845 i846 i847 i848 i849 i850 i851 i852 i853 i854 i855 i856 i857 i858 i859 i860 i861 i862 i863 i864 i865 i866 i867 i868 i869 i870 i871 i872 i873 i874 i875 i876 i877 i878 i879 i880 i881 i882 i883 i884 i885 i886 i887 i888 i889 i890 i891 i892 i893 i894 i895 i896 i897 i898 i899 i900 i901 i902 i903 i904 i905 i906 i907 i908 i909 i910 i911 i912 i913 i914 i915 i916 i917 i918 i919 i920 i921 i922 i923 i924 i925 i926 i927 i928 i929 i930 i931 i932 i933 i934 i935 i936 i937 i938 i939 i940 i941 i942 i943 i944 i945 i946 i947 i948 i949 i950 i951 i952 i953 i954 i955 i956 i957 i958 i959 i960 i961 i962 i963 i964 i965 i966 i967 i968 i969 i970 i971 i972 i973 i974 i975 i976 i977 i978 i979 i980 i981 i982 i983 i984 i985 i986 i987 i988 i989 i990 i991 i992 i993 i994 i995 i996 i997 i998 i999 i1000 b 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 PatrickG -update federated.t1 set i50=20; -select * from federated.t1; +UPDATE federated.t1 SET i50=20; +SELECT * FROM federated.t1; i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30 i31 i32 i33 i34 i35 i36 i37 i38 i39 i40 i41 i42 i43 i44 i45 i46 i47 i48 i49 i50 i51 i52 i53 i54 i55 i56 i57 i58 i59 i60 i61 i62 i63 i64 i65 i66 i67 i68 i69 i70 i71 i72 i73 i74 i75 i76 i77 i78 i79 i80 i81 i82 i83 i84 i85 i86 i87 i88 i89 i90 i91 i92 i93 i94 i95 i96 i97 i98 i99 i100 i101 i102 i103 i104 i105 i106 i107 i108 i109 i110 i111 i112 i113 i114 i115 i116 i117 i118 i119 i120 i121 i122 i123 i124 i125 i126 i127 i128 i129 i130 i131 i132 i133 i134 i135 i136 i137 i138 i139 i140 i141 i142 i143 i144 i145 i146 i147 i148 i149 i150 i151 i152 i153 i154 i155 i156 i157 i158 i159 i160 i161 i162 i163 i164 i165 i166 i167 i168 i169 i170 i171 i172 i173 i174 i175 i176 i177 i178 i179 i180 i181 i182 i183 i184 i185 i186 i187 i188 i189 i190 i191 i192 i193 i194 i195 i196 i197 i198 i199 i200 i201 i202 i203 i204 i205 i206 i207 i208 i209 i210 i211 i212 i213 i214 i215 i216 i217 i218 i219 i220 i221 i222 i223 i224 i225 i226 i227 i228 i229 i230 i231 i232 i233 i234 i235 i236 i237 i238 i239 i240 i241 i242 i243 i244 i245 i246 i247 i248 i249 i250 i251 i252 i253 i254 i255 i256 i257 i258 i259 i260 i261 i262 i263 i264 i265 i266 i267 i268 i269 i270 i271 i272 i273 i274 i275 i276 i277 i278 i279 i280 i281 i282 i283 i284 i285 i286 i287 i288 i289 i290 i291 i292 i293 i294 i295 i296 i297 i298 i299 i300 i301 i302 i303 i304 i305 i306 i307 i308 i309 i310 i311 i312 i313 i314 i315 i316 i317 i318 i319 i320 i321 i322 i323 i324 i325 i326 i327 i328 i329 i330 i331 i332 i333 i334 i335 i336 i337 i338 i339 i340 i341 i342 i343 i344 i345 i346 i347 i348 i349 i350 i351 i352 i353 i354 i355 i356 i357 i358 i359 i360 i361 i362 i363 i364 i365 i366 i367 i368 i369 i370 i371 i372 i373 i374 i375 i376 i377 i378 i379 i380 i381 i382 i383 i384 i385 i386 i387 i388 i389 i390 i391 i392 i393 i394 i395 i396 i397 i398 i399 i400 i401 i402 i403 i404 i405 i406 i407 i408 i409 i410 i411 i412 i413 i414 i415 i416 i417 i418 i419 i420 i421 i422 i423 i424 i425 i426 i427 i428 i429 i430 i431 i432 i433 i434 i435 i436 i437 i438 i439 i440 i441 i442 i443 i444 i445 i446 i447 i448 i449 i450 i451 i452 i453 i454 i455 i456 i457 i458 i459 i460 i461 i462 i463 i464 i465 i466 i467 i468 i469 i470 i471 i472 i473 i474 i475 i476 i477 i478 i479 i480 i481 i482 i483 i484 i485 i486 i487 i488 i489 i490 i491 i492 i493 i494 i495 i496 i497 i498 i499 i500 i501 i502 i503 i504 i505 i506 i507 i508 i509 i510 i511 i512 i513 i514 i515 i516 i517 i518 i519 i520 i521 i522 i523 i524 i525 i526 i527 i528 i529 i530 i531 i532 i533 i534 i535 i536 i537 i538 i539 i540 i541 i542 i543 i544 i545 i546 i547 i548 i549 i550 i551 i552 i553 i554 i555 i556 i557 i558 i559 i560 i561 i562 i563 i564 i565 i566 i567 i568 i569 i570 i571 i572 i573 i574 i575 i576 i577 i578 i579 i580 i581 i582 i583 i584 i585 i586 i587 i588 i589 i590 i591 i592 i593 i594 i595 i596 i597 i598 i599 i600 i601 i602 i603 i604 i605 i606 i607 i608 i609 i610 i611 i612 i613 i614 i615 i616 i617 i618 i619 i620 i621 i622 i623 i624 i625 i626 i627 i628 i629 i630 i631 i632 i633 i634 i635 i636 i637 i638 i639 i640 i641 i642 i643 i644 i645 i646 i647 i648 i649 i650 i651 i652 i653 i654 i655 i656 i657 i658 i659 i660 i661 i662 i663 i664 i665 i666 i667 i668 i669 i670 i671 i672 i673 i674 i675 i676 i677 i678 i679 i680 i681 i682 i683 i684 i685 i686 i687 i688 i689 i690 i691 i692 i693 i694 i695 i696 i697 i698 i699 i700 i701 i702 i703 i704 i705 i706 i707 i708 i709 i710 i711 i712 i713 i714 i715 i716 i717 i718 i719 i720 i721 i722 i723 i724 i725 i726 i727 i728 i729 i730 i731 i732 i733 i734 i735 i736 i737 i738 i739 i740 i741 i742 i743 i744 i745 i746 i747 i748 i749 i750 i751 i752 i753 i754 i755 i756 i757 i758 i759 i760 i761 i762 i763 i764 i765 i766 i767 i768 i769 i770 i771 i772 i773 i774 i775 i776 i777 i778 i779 i780 i781 i782 i783 i784 i785 i786 i787 i788 i789 i790 i791 i792 i793 i794 i795 i796 i797 i798 i799 i800 i801 i802 i803 i804 i805 i806 i807 i808 i809 i810 i811 i812 i813 i814 i815 i816 i817 i818 i819 i820 i821 i822 i823 i824 i825 i826 i827 i828 i829 i830 i831 i832 i833 i834 i835 i836 i837 i838 i839 i840 i841 i842 i843 i844 i845 i846 i847 i848 i849 i850 i851 i852 i853 i854 i855 i856 i857 i858 i859 i860 i861 i862 i863 i864 i865 i866 i867 i868 i869 i870 i871 i872 i873 i874 i875 i876 i877 i878 i879 i880 i881 i882 i883 i884 i885 i886 i887 i888 i889 i890 i891 i892 i893 i894 i895 i896 i897 i898 i899 i900 i901 i902 i903 i904 i905 i906 i907 i908 i909 i910 i911 i912 i913 i914 i915 i916 i917 i918 i919 i920 i921 i922 i923 i924 i925 i926 i927 i928 i929 i930 i931 i932 i933 i934 i935 i936 i937 i938 i939 i940 i941 i942 i943 i944 i945 i946 i947 i948 i949 i950 i951 i952 i953 i954 i955 i956 i957 i958 i959 i960 i961 i962 i963 i964 i965 i966 i967 i968 i969 i970 i971 i972 i973 i974 i975 i976 i977 i978 i979 i980 i981 i982 i983 i984 i985 i986 i987 i988 i989 i990 i991 i992 i993 i994 i995 i996 i997 i998 i999 i1000 b 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 20 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 PatrickG -delete from federated.t1 where i51=20; -select * from federated.t1; +DELETE FROM federated.t1 WHERE i51=20; +SELECT * FROM federated.t1; i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30 i31 i32 i33 i34 i35 i36 i37 i38 i39 i40 i41 i42 i43 i44 i45 i46 i47 i48 i49 i50 i51 i52 i53 i54 i55 i56 i57 i58 i59 i60 i61 i62 i63 i64 i65 i66 i67 i68 i69 i70 i71 i72 i73 i74 i75 i76 i77 i78 i79 i80 i81 i82 i83 i84 i85 i86 i87 i88 i89 i90 i91 i92 i93 i94 i95 i96 i97 i98 i99 i100 i101 i102 i103 i104 i105 i106 i107 i108 i109 i110 i111 i112 i113 i114 i115 i116 i117 i118 i119 i120 i121 i122 i123 i124 i125 i126 i127 i128 i129 i130 i131 i132 i133 i134 i135 i136 i137 i138 i139 i140 i141 i142 i143 i144 i145 i146 i147 i148 i149 i150 i151 i152 i153 i154 i155 i156 i157 i158 i159 i160 i161 i162 i163 i164 i165 i166 i167 i168 i169 i170 i171 i172 i173 i174 i175 i176 i177 i178 i179 i180 i181 i182 i183 i184 i185 i186 i187 i188 i189 i190 i191 i192 i193 i194 i195 i196 i197 i198 i199 i200 i201 i202 i203 i204 i205 i206 i207 i208 i209 i210 i211 i212 i213 i214 i215 i216 i217 i218 i219 i220 i221 i222 i223 i224 i225 i226 i227 i228 i229 i230 i231 i232 i233 i234 i235 i236 i237 i238 i239 i240 i241 i242 i243 i244 i245 i246 i247 i248 i249 i250 i251 i252 i253 i254 i255 i256 i257 i258 i259 i260 i261 i262 i263 i264 i265 i266 i267 i268 i269 i270 i271 i272 i273 i274 i275 i276 i277 i278 i279 i280 i281 i282 i283 i284 i285 i286 i287 i288 i289 i290 i291 i292 i293 i294 i295 i296 i297 i298 i299 i300 i301 i302 i303 i304 i305 i306 i307 i308 i309 i310 i311 i312 i313 i314 i315 i316 i317 i318 i319 i320 i321 i322 i323 i324 i325 i326 i327 i328 i329 i330 i331 i332 i333 i334 i335 i336 i337 i338 i339 i340 i341 i342 i343 i344 i345 i346 i347 i348 i349 i350 i351 i352 i353 i354 i355 i356 i357 i358 i359 i360 i361 i362 i363 i364 i365 i366 i367 i368 i369 i370 i371 i372 i373 i374 i375 i376 i377 i378 i379 i380 i381 i382 i383 i384 i385 i386 i387 i388 i389 i390 i391 i392 i393 i394 i395 i396 i397 i398 i399 i400 i401 i402 i403 i404 i405 i406 i407 i408 i409 i410 i411 i412 i413 i414 i415 i416 i417 i418 i419 i420 i421 i422 i423 i424 i425 i426 i427 i428 i429 i430 i431 i432 i433 i434 i435 i436 i437 i438 i439 i440 i441 i442 i443 i444 i445 i446 i447 i448 i449 i450 i451 i452 i453 i454 i455 i456 i457 i458 i459 i460 i461 i462 i463 i464 i465 i466 i467 i468 i469 i470 i471 i472 i473 i474 i475 i476 i477 i478 i479 i480 i481 i482 i483 i484 i485 i486 i487 i488 i489 i490 i491 i492 i493 i494 i495 i496 i497 i498 i499 i500 i501 i502 i503 i504 i505 i506 i507 i508 i509 i510 i511 i512 i513 i514 i515 i516 i517 i518 i519 i520 i521 i522 i523 i524 i525 i526 i527 i528 i529 i530 i531 i532 i533 i534 i535 i536 i537 i538 i539 i540 i541 i542 i543 i544 i545 i546 i547 i548 i549 i550 i551 i552 i553 i554 i555 i556 i557 i558 i559 i560 i561 i562 i563 i564 i565 i566 i567 i568 i569 i570 i571 i572 i573 i574 i575 i576 i577 i578 i579 i580 i581 i582 i583 i584 i585 i586 i587 i588 i589 i590 i591 i592 i593 i594 i595 i596 i597 i598 i599 i600 i601 i602 i603 i604 i605 i606 i607 i608 i609 i610 i611 i612 i613 i614 i615 i616 i617 i618 i619 i620 i621 i622 i623 i624 i625 i626 i627 i628 i629 i630 i631 i632 i633 i634 i635 i636 i637 i638 i639 i640 i641 i642 i643 i644 i645 i646 i647 i648 i649 i650 i651 i652 i653 i654 i655 i656 i657 i658 i659 i660 i661 i662 i663 i664 i665 i666 i667 i668 i669 i670 i671 i672 i673 i674 i675 i676 i677 i678 i679 i680 i681 i682 i683 i684 i685 i686 i687 i688 i689 i690 i691 i692 i693 i694 i695 i696 i697 i698 i699 i700 i701 i702 i703 i704 i705 i706 i707 i708 i709 i710 i711 i712 i713 i714 i715 i716 i717 i718 i719 i720 i721 i722 i723 i724 i725 i726 i727 i728 i729 i730 i731 i732 i733 i734 i735 i736 i737 i738 i739 i740 i741 i742 i743 i744 i745 i746 i747 i748 i749 i750 i751 i752 i753 i754 i755 i756 i757 i758 i759 i760 i761 i762 i763 i764 i765 i766 i767 i768 i769 i770 i771 i772 i773 i774 i775 i776 i777 i778 i779 i780 i781 i782 i783 i784 i785 i786 i787 i788 i789 i790 i791 i792 i793 i794 i795 i796 i797 i798 i799 i800 i801 i802 i803 i804 i805 i806 i807 i808 i809 i810 i811 i812 i813 i814 i815 i816 i817 i818 i819 i820 i821 i822 i823 i824 i825 i826 i827 i828 i829 i830 i831 i832 i833 i834 i835 i836 i837 i838 i839 i840 i841 i842 i843 i844 i845 i846 i847 i848 i849 i850 i851 i852 i853 i854 i855 i856 i857 i858 i859 i860 i861 i862 i863 i864 i865 i866 i867 i868 i869 i870 i871 i872 i873 i874 i875 i876 i877 i878 i879 i880 i881 i882 i883 i884 i885 i886 i887 i888 i889 i890 i891 i892 i893 i894 i895 i896 i897 i898 i899 i900 i901 i902 i903 i904 i905 i906 i907 i908 i909 i910 i911 i912 i913 i914 i915 i916 i917 i918 i919 i920 i921 i922 i923 i924 i925 i926 i927 i928 i929 i930 i931 i932 i933 i934 i935 i936 i937 i938 i939 i940 i941 i942 i943 i944 i945 i946 i947 i948 i949 i950 i951 i952 i953 i954 i955 i956 i957 i958 i959 i960 i961 i962 i963 i964 i965 i966 i967 i968 i969 i970 i971 i972 i973 i974 i975 i976 i977 i978 i979 i980 i981 i982 i983 i984 i985 i986 i987 i988 i989 i990 i991 i992 i993 i994 i995 i996 i997 i998 i999 i1000 b 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 20 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 PatrickG -delete from federated.t1 where i50=20; -select * from federated.t1; +DELETE FROM federated.t1 WHERE i50=20; +SELECT * FROM federated.t1; i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 i16 i17 i18 i19 i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30 i31 i32 i33 i34 i35 i36 i37 i38 i39 i40 i41 i42 i43 i44 i45 i46 i47 i48 i49 i50 i51 i52 i53 i54 i55 i56 i57 i58 i59 i60 i61 i62 i63 i64 i65 i66 i67 i68 i69 i70 i71 i72 i73 i74 i75 i76 i77 i78 i79 i80 i81 i82 i83 i84 i85 i86 i87 i88 i89 i90 i91 i92 i93 i94 i95 i96 i97 i98 i99 i100 i101 i102 i103 i104 i105 i106 i107 i108 i109 i110 i111 i112 i113 i114 i115 i116 i117 i118 i119 i120 i121 i122 i123 i124 i125 i126 i127 i128 i129 i130 i131 i132 i133 i134 i135 i136 i137 i138 i139 i140 i141 i142 i143 i144 i145 i146 i147 i148 i149 i150 i151 i152 i153 i154 i155 i156 i157 i158 i159 i160 i161 i162 i163 i164 i165 i166 i167 i168 i169 i170 i171 i172 i173 i174 i175 i176 i177 i178 i179 i180 i181 i182 i183 i184 i185 i186 i187 i188 i189 i190 i191 i192 i193 i194 i195 i196 i197 i198 i199 i200 i201 i202 i203 i204 i205 i206 i207 i208 i209 i210 i211 i212 i213 i214 i215 i216 i217 i218 i219 i220 i221 i222 i223 i224 i225 i226 i227 i228 i229 i230 i231 i232 i233 i234 i235 i236 i237 i238 i239 i240 i241 i242 i243 i244 i245 i246 i247 i248 i249 i250 i251 i252 i253 i254 i255 i256 i257 i258 i259 i260 i261 i262 i263 i264 i265 i266 i267 i268 i269 i270 i271 i272 i273 i274 i275 i276 i277 i278 i279 i280 i281 i282 i283 i284 i285 i286 i287 i288 i289 i290 i291 i292 i293 i294 i295 i296 i297 i298 i299 i300 i301 i302 i303 i304 i305 i306 i307 i308 i309 i310 i311 i312 i313 i314 i315 i316 i317 i318 i319 i320 i321 i322 i323 i324 i325 i326 i327 i328 i329 i330 i331 i332 i333 i334 i335 i336 i337 i338 i339 i340 i341 i342 i343 i344 i345 i346 i347 i348 i349 i350 i351 i352 i353 i354 i355 i356 i357 i358 i359 i360 i361 i362 i363 i364 i365 i366 i367 i368 i369 i370 i371 i372 i373 i374 i375 i376 i377 i378 i379 i380 i381 i382 i383 i384 i385 i386 i387 i388 i389 i390 i391 i392 i393 i394 i395 i396 i397 i398 i399 i400 i401 i402 i403 i404 i405 i406 i407 i408 i409 i410 i411 i412 i413 i414 i415 i416 i417 i418 i419 i420 i421 i422 i423 i424 i425 i426 i427 i428 i429 i430 i431 i432 i433 i434 i435 i436 i437 i438 i439 i440 i441 i442 i443 i444 i445 i446 i447 i448 i449 i450 i451 i452 i453 i454 i455 i456 i457 i458 i459 i460 i461 i462 i463 i464 i465 i466 i467 i468 i469 i470 i471 i472 i473 i474 i475 i476 i477 i478 i479 i480 i481 i482 i483 i484 i485 i486 i487 i488 i489 i490 i491 i492 i493 i494 i495 i496 i497 i498 i499 i500 i501 i502 i503 i504 i505 i506 i507 i508 i509 i510 i511 i512 i513 i514 i515 i516 i517 i518 i519 i520 i521 i522 i523 i524 i525 i526 i527 i528 i529 i530 i531 i532 i533 i534 i535 i536 i537 i538 i539 i540 i541 i542 i543 i544 i545 i546 i547 i548 i549 i550 i551 i552 i553 i554 i555 i556 i557 i558 i559 i560 i561 i562 i563 i564 i565 i566 i567 i568 i569 i570 i571 i572 i573 i574 i575 i576 i577 i578 i579 i580 i581 i582 i583 i584 i585 i586 i587 i588 i589 i590 i591 i592 i593 i594 i595 i596 i597 i598 i599 i600 i601 i602 i603 i604 i605 i606 i607 i608 i609 i610 i611 i612 i613 i614 i615 i616 i617 i618 i619 i620 i621 i622 i623 i624 i625 i626 i627 i628 i629 i630 i631 i632 i633 i634 i635 i636 i637 i638 i639 i640 i641 i642 i643 i644 i645 i646 i647 i648 i649 i650 i651 i652 i653 i654 i655 i656 i657 i658 i659 i660 i661 i662 i663 i664 i665 i666 i667 i668 i669 i670 i671 i672 i673 i674 i675 i676 i677 i678 i679 i680 i681 i682 i683 i684 i685 i686 i687 i688 i689 i690 i691 i692 i693 i694 i695 i696 i697 i698 i699 i700 i701 i702 i703 i704 i705 i706 i707 i708 i709 i710 i711 i712 i713 i714 i715 i716 i717 i718 i719 i720 i721 i722 i723 i724 i725 i726 i727 i728 i729 i730 i731 i732 i733 i734 i735 i736 i737 i738 i739 i740 i741 i742 i743 i744 i745 i746 i747 i748 i749 i750 i751 i752 i753 i754 i755 i756 i757 i758 i759 i760 i761 i762 i763 i764 i765 i766 i767 i768 i769 i770 i771 i772 i773 i774 i775 i776 i777 i778 i779 i780 i781 i782 i783 i784 i785 i786 i787 i788 i789 i790 i791 i792 i793 i794 i795 i796 i797 i798 i799 i800 i801 i802 i803 i804 i805 i806 i807 i808 i809 i810 i811 i812 i813 i814 i815 i816 i817 i818 i819 i820 i821 i822 i823 i824 i825 i826 i827 i828 i829 i830 i831 i832 i833 i834 i835 i836 i837 i838 i839 i840 i841 i842 i843 i844 i845 i846 i847 i848 i849 i850 i851 i852 i853 i854 i855 i856 i857 i858 i859 i860 i861 i862 i863 i864 i865 i866 i867 i868 i869 i870 i871 i872 i873 i874 i875 i876 i877 i878 i879 i880 i881 i882 i883 i884 i885 i886 i887 i888 i889 i890 i891 i892 i893 i894 i895 i896 i897 i898 i899 i900 i901 i902 i903 i904 i905 i906 i907 i908 i909 i910 i911 i912 i913 i914 i915 i916 i917 i918 i919 i920 i921 i922 i923 i924 i925 i926 i927 i928 i929 i930 i931 i932 i933 i934 i935 i936 i937 i938 i939 i940 i941 i942 i943 i944 i945 i946 i947 i948 i949 i950 i951 i952 i953 i954 i955 i956 i957 i958 i959 i960 i961 i962 i963 i964 i965 i966 i967 i968 i969 i970 i971 i972 i973 i974 i975 i976 i977 i978 i979 i980 i981 i982 i983 i984 i985 i986 i987 i988 i989 i990 i991 i992 i993 i994 i995 i996 i997 i998 i999 i1000 b -drop table if exists federated.t1; -create table federated.t1 (id int NOT NULL auto_increment, code char(20) NOT NULL, fileguts blob NOT NULL, creation_date datetime, entered_time datetime default '2004-04-04 04:04:04', primary key(id), index(code), index(fileguts(10))) DEFAULT CHARSET=latin1; -drop table if exists federated.t1; -create table federated.t1 (id int NOT NULL auto_increment, code char(20) NOT NULL, fileguts blob NOT NULL, creation_date datetime, entered_time datetime default '2004-04-04 04:04:04', primary key(id), index(code), index(fileguts(10))) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (code, fileguts, creation_date) values ('ASDFWERQWETWETAWETA', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2003-03-03 03:03:03'); -insert into federated.t1 (code, fileguts, creation_date) values ('DEUEUEUEUEUEUEUEUEU', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2004-04-04 04:04:04'); -insert into federated.t1 (code, fileguts, creation_date) values ('DEUEUEUEUEUEUEUEUEU', 'jimbob', '2004-04-04 04:04:04'); -select * from federated.t1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 (id int NOT NULL auto_increment, code char(20) NOT NULL, fileguts blob NOT NULL, creation_date datetime, entered_time datetime default '2004-04-04 04:04:04', PRIMARY KEY(id), index(code), index(fileguts(10))) DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +id int NOT NULL auto_increment, +code char(20) NOT NULL, +fileguts blob NOT NULL, +creation_date datetime, +entered_time datetime default '2004-04-04 04:04:04', +PRIMARY KEY(id), +index(code), +index(fileguts(10))) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('ASDFWERQWETWETAWETA', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2003-03-03 03:03:03'); +INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2004-04-04 04:04:04'); +INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', 'jimbob', '2004-04-04 04:04:04'); +SELECT * FROM federated.t1; id code fileguts creation_date entered_time 1 ASDFWERQWETWETAWETA *()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[ 2003-03-03 03:03:03 2004-04-04 04:04:04 2 DEUEUEUEUEUEUEUEUEU *()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[ 2004-04-04 04:04:04 2004-04-04 04:04:04 3 DEUEUEUEUEUEUEUEUEU jimbob 2004-04-04 04:04:04 2004-04-04 04:04:04 -select * from federated.t1 where fileguts = 'jimbob'; +SELECT * FROM federated.t1 WHERE fileguts = 'jimbob'; id code fileguts creation_date entered_time 3 DEUEUEUEUEUEUEUEUEU jimbob 2004-04-04 04:04:04 2004-04-04 04:04:04 -drop table if exists federated.t1; -CREATE TABLE federated.t1 (a BLOB); -drop table if exists federated.t1; -CREATE TABLE federated.t1 (a BLOB) ENGINE="FEDERATED" COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 (`a` BLOB); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`a` BLOB) +ENGINE="FEDERATED" +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; INSERT INTO federated.t1 VALUES (0x00); INSERT INTO federated.t1 VALUES (0x0001); INSERT INTO federated.t1 VALUES (0x0100); @@ -655,33 +761,52 @@ HEX(a) 00 0001 0100 -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id)); -drop table if exists federated.countries; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int(20) NOT NULL auto_increment, +`country_id` int(20) NOT NULL DEFAULT 0, +`name` varchar(32), +`other` varchar(20), +PRIMARY KEY (`id`), +key (country_id)); +DROP TABLE IF EXISTS federated.countries; Warnings: Note 1051 Unknown table 'countries' -CREATE TABLE federated.countries ( `id` int(20) NOT NULL auto_increment, `country` varchar(32), primary key (id)); -insert into federated.countries (country) values ('India'); -insert into federated.countries (country) values ('Germany'); -insert into federated.countries (country) values ('Italy'); -insert into federated.countries (country) values ('Finland'); -insert into federated.countries (country) values ('Ukraine'); -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, country_id, other) values ('Kumar', 1, 11111); -insert into federated.t1 (name, country_id, other) values ('Lenz', 2, 22222); -insert into federated.t1 (name, country_id, other) values ('Marizio', 3, 33333); -insert into federated.t1 (name, country_id, other) values ('Monty', 4, 33333); -insert into federated.t1 (name, country_id, other) values ('Sanja', 5, 33333); -select federated.t1.*, federated.countries.country from federated.t1 left join federated.countries on federated.t1.country_id = federated.countries.id; +CREATE TABLE federated.countries ( +`id` int(20) NOT NULL auto_increment, +`country` varchar(32), +PRIMARY KEY (id)); +INSERT INTO federated.countries (country) VALUES ('India'); +INSERT INTO federated.countries (country) VALUES ('Germany'); +INSERT INTO federated.countries (country) VALUES ('Italy'); +INSERT INTO federated.countries (country) VALUES ('Finland'); +INSERT INTO federated.countries (country) VALUES ('Ukraine'); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`id` int(20) NOT NULL auto_increment, +`country_id` int(20) NOT NULL DEFAULT 0, +`name` varchar(32), +`other` varchar(20), +PRIMARY KEY (`id`), +KEY (country_id) ) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Kumar', 1, 11111); +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Lenz', 2, 22222); +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Marizio', 3, 33333); +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Monty', 4, 33333); +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Sanja', 5, 33333); +SELECT federated.t1.*, federated.countries.country +FROM federated.t1 left join federated.countries +ON federated.t1.country_id = federated.countries.id; id country_id name other country 1 1 Kumar 11111 India 2 2 Lenz 22222 Germany 3 3 Marizio 33333 Italy 4 4 Monty 33333 Finland 5 5 Sanja 33333 Ukraine -drop table federated.countries; -drop table if exists federated.t1; -drop database if exists federated; -drop table if exists federated.t1; -drop database if exists federated; +DROP TABLE federated.countries; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index c634badf04e..5c6eb8db179 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -10,206 +10,304 @@ stop slave; --disable_warnings # at this point, we are connected to master -drop database if exists federated; +DROP DATABASE IF EXISTS federated; --enable_warnings -create database federated; +CREATE DATABASE federated; # I wanted to use timestamp, but results will fail if so!!! -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32) NOT NULL default '', `other` int(20) NOT NULL default '0', created datetime default '2004-04-04 04:04:04', PRIMARY KEY (`id`), KEY `name` (`name`), KEY `other_key` (`other`)) DEFAULT CHARSET=latin1; +CREATE TABLE federated.t1 ( + `id` int(20) NOT NULL auto_increment, + `name` varchar(32) NOT NULL default '', + `other` int(20) NOT NULL default '0', + `created` datetime default '2004-04-04 04:04:04', + PRIMARY KEY (`id`), + KEY `name` (`name`), + KEY `other_key` (`other`)) + DEFAULT CHARSET=latin1; connection master; --disable_warnings -drop database if exists federated; +DROP DATABASE IF EXISTS federated; --enable_warnings -create database federated; +CREATE DATABASE federated; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32) NOT NULL default '', `other` int(20) NOT NULL default '0', created datetime default '2004-04-04 04:04:04', PRIMARY KEY (`id`), KEY `name` (`name`), KEY `other_key` (`other`)) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `id` int(20) NOT NULL auto_increment, + `name` varchar(32) NOT NULL default '', + `other` int(20) NOT NULL default '0', + `created` datetime default '2004-04-04 04:04:04', + PRIMARY KEY (`id`), + KEY `name` (`name`), + KEY `other_key` (`other`)) + ENGINE="FEDERATED" DEFAULT CHARSET=latin1 + COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; -insert into federated.t1 (name, other) values ('First Name', 11111); -insert into federated.t1 (name, other) values ('Second Name', 22222); -insert into federated.t1 (name, other) values ('Third Name', 33333); -insert into federated.t1 (name, other) values ('Fourth Name', 44444); -insert into federated.t1 (name, other) values ('Fifth Name', 55555); -insert into federated.t1 (name, other) values ('Sixth Name', 66666); -insert into federated.t1 (name, other) values ('Seventh Name', 77777); -insert into federated.t1 (name, other) values ('Eigth Name', 88888); -insert into federated.t1 (name, other) values ('Ninth Name', 99999); -insert into federated.t1 (name, other) values ('Tenth Name', 101010); +INSERT INTO federated.t1 (name, other) VALUES ('First Name', 11111); +INSERT INTO federated.t1 (name, other) VALUES ('Second Name', 22222); +INSERT INTO federated.t1 (name, other) VALUES ('Third Name', 33333); +INSERT INTO federated.t1 (name, other) VALUES ('Fourth Name', 44444); +INSERT INTO federated.t1 (name, other) VALUES ('Fifth Name', 55555); +INSERT INTO federated.t1 (name, other) VALUES ('Sixth Name', 66666); +INSERT INTO federated.t1 (name, other) VALUES ('Seventh Name', 77777); +INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888); +INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999); +INSERT INTO federated.t1 (name, other) VALUES ('Tenth Name', 101010); # basic select -select * from federated.t1; -# with primary key index_read_idx -select * from federated.t1 where id = 5; +SELECT * FROM federated.t1; +# with PRIMARY KEY index_read_idx +SELECT * FROM federated.t1 WHERE id = 5; # with regular key index_read -> index_read_idx -select * from federated.t1 where name = 'Sixth Name'; -# regular and primary key index_read_idx -select * from federated.t1 where id = 6 and name = 'Sixth Name'; +SELECT * FROM federated.t1 WHERE name = 'Sixth Name'; +# regular and PRIMARY KEY index_read_idx +SELECT * FROM federated.t1 WHERE id = 6 and name = 'Sixth Name'; # with regular key index_read -> index_read_idx -select * from federated.t1 where other = 44444; -select * from federated.t1 where name like '%th%'; +SELECT * FROM federated.t1 WHERE other = 44444; +SELECT * FROM federated.t1 WHERE name like '%th%'; # update - update_row, index_read_idx -update federated.t1 set name = '3rd name' where id = 3; -select * from federated.t1 where name = '3rd name'; +UPDATE federated.t1 SET name = '3rd name' WHERE id = 3; +SELECT * FROM federated.t1 WHERE name = '3rd name'; # update - update_row, index_read -> index_read_idx -update federated.t1 set name = 'Third name' where name = '3rd name'; -select * from federated.t1 where name = 'Third name'; +UPDATE federated.t1 SET name = 'Third name' WHERE name = '3rd name'; +SELECT * FROM federated.t1 WHERE name = 'Third name'; # rnd_post, ::position -select * from federated.t1 order by id DESC; -select * from federated.t1 order by name; -select * from federated.t1 order by name DESC; -select * from federated.t1 order by name ASC; -select * from federated.t1 group by other; +SELECT * FROM federated.t1 ORDER BY id DESC; +SELECT * FROM federated.t1 ORDER BY name; +SELECT * FROM federated.t1 ORDER BY name DESC; +SELECT * FROM federated.t1 ORDER BY name ASC; +SELECT * FROM federated.t1 GROUP BY other; # ::delete_row -delete from federated.t1 where id = 5; -select * from federated.t1 where id = 5; +DELETE FROM federated.t1 WHERE id = 5; +SELECT * FROM federated.t1 WHERE id = 5; # ::delete_all_rows -delete from federated.t1; -select * from federated.t1 where id = 5; +DELETE FROM federated.t1; +SELECT * FROM federated.t1 WHERE id = 5; connection slave; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`) ); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( + `id` int(20) NOT NULL auto_increment, + `name` varchar(32), + `other` varchar(20), + PRIMARY KEY (`id`) ); connection master; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `id` int(20) NOT NULL auto_increment, + `name` varchar(32), + `other` varchar(20), + PRIMARY KEY (`id`) ) + ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 + COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; -insert into federated.t1 (name, other) values ('First Name', 11111); -insert into federated.t1 (name, other) values ('Second Name', NULL); -insert into federated.t1 (name, other) values ('Third Name', 33333); -insert into federated.t1 (name, other) values (NULL, NULL); -insert into federated.t1 (name, other) values ('Fifth Name', 55555); -insert into federated.t1 (name, other) values ('Sixth Name', 66666); -insert into federated.t1 (name) values ('Seventh Name'); -insert into federated.t1 (name, other) values ('Eigth Name', 88888); -insert into federated.t1 (name, other) values ('Ninth Name', 99999); -insert into federated.t1 (other) values ('fee fie foe fum'); +INSERT INTO federated.t1 (name, other) VALUES ('First Name', 11111); +INSERT INTO federated.t1 (name, other) VALUES ('Second Name', NULL); +INSERT INTO federated.t1 (name, other) VALUES ('Third Name', 33333); +INSERT INTO federated.t1 (name, other) VALUES (NULL, NULL); +INSERT INTO federated.t1 (name, other) VALUES ('Fifth Name', 55555); +INSERT INTO federated.t1 (name, other) VALUES ('Sixth Name', 66666); +INSERT INTO federated.t1 (name) VALUES ('Seventh Name'); +INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888); +INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999); +INSERT INTO federated.t1 (other) VALUES ('fee fie foe fum'); -select * from federated.t1 where other IS NULL; -select * from federated.t1 where name IS NULL; -select * from federated.t1 where name IS NULL and other IS NULL; -select * from federated.t1 where name IS NULL or other IS NULL; -update federated.t1 set name = 'Fourth Name', other = 'four four four' where name IS NULL and other IS NULL; -update federated.t1 set other = 'two two two two' where name = 'Second Name'; -update federated.t1 set other = 'seven seven' where name like 'Sec%'; -update federated.t1 set other = 'seven seven' where name = 'Seventh Name'; -update federated.t1 set name = 'Tenth Name' where other like 'fee fie%'; -select * from federated.t1 where name IS NULL or other IS NULL ; -select * from federated.t1; +SELECT * FROM federated.t1 WHERE other IS NULL; +SELECT * FROM federated.t1 WHERE name IS NULL; +SELECT * FROM federated.t1 WHERE name IS NULL and other IS NULL; +SELECT * FROM federated.t1 WHERE name IS NULL or other IS NULL; + +UPDATE federated.t1 +SET name = 'Fourth Name', other = 'four four four' +WHERE name IS NULL AND other IS NULL; + +UPDATE federated.t1 SET other = 'two two two two' WHERE name = 'Second Name'; +UPDATE federated.t1 SET other = 'seven seven' WHERE name like 'Sec%'; +UPDATE federated.t1 SET other = 'seven seven' WHERE name = 'Seventh Name'; +UPDATE federated.t1 SET name = 'Tenth Name' WHERE other like 'fee fie%'; +SELECT * FROM federated.t1 WHERE name IS NULL OR other IS NULL ; +SELECT * FROM federated.t1; # test multi-keys connection slave; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` -varchar(32) NOT NULL DEFAULT '', `other` varchar(20) NOT NULL DEFAULT '', PRIMARY KEY (`id`), key nameoth (name, other) ); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( + `id` int(20) NOT NULL auto_increment, + `name` varchar(32) NOT NULL DEFAULT '', + `other` varchar(20) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY nameoth (name, other) ); connection master; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `name` varchar(32) NOT NULL DEFAULT '', `other` varchar(20) NOT NULL DEFAULT '', PRIMARY KEY (`id`), key nameoth (name, other)) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, other) values ('First Name', '1111'); -insert into federated.t1 (name, other) values ('Second Name', '2222'); -insert into federated.t1 (name, other) values ('Third Name', '3333'); -select * from federated.t1 where name = 'Second Name'; -select * from federated.t1 where other = '2222'; -select * from federated.t1 where name = 'Third Name'; -select * from federated.t1 where name = 'Third Name' and other = '3333'; +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `id` int(20) NOT NULL auto_increment, + `name` varchar(32) NOT NULL DEFAULT '', + `other` varchar(20) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY nameoth (name, other)) + ENGINE="FEDERATED" DEFAULT + CHARSET=latin1 + COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + +INSERT INTO federated.t1 (name, other) VALUES ('First Name', '1111'); +INSERT INTO federated.t1 (name, other) VALUES ('Second Name', '2222'); +INSERT INTO federated.t1 (name, other) VALUES ('Third Name', '3333'); +SELECT * FROM federated.t1 WHERE name = 'Second Name'; +SELECT * FROM federated.t1 WHERE other = '2222'; +SELECT * FROM federated.t1 WHERE name = 'Third Name'; +SELECT * FROM federated.t1 WHERE name = 'Third Name' AND other = '3333'; connection slave; -drop table if exists federated.t1; -CREATE TABLE federated.t1 - (id int NOT NULL auto_increment, - name char(32) NOT NULL DEFAULT '', - bincol binary(4) NOT NULL, - floatval decimal(5,2) NOT NULL DEFAULT 0.0, - other int NOT NULL DEFAULT 0, - primary key(id), - key nameoth(name, other), - key bincol(bincol), - key floatval(floatval)); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( + `id` int NOT NULL auto_increment, + `name` char(32) NOT NULL DEFAULT '', + `bincol` binary(4) NOT NULL, + `floatval` decimal(5,2) NOT NULL DEFAULT 0.0, + `other` int NOT NULL DEFAULT 0, + PRIMARY KEY (id), + KEY nameoth(name, other), + KEY bincol(bincol), + KEY floatval(floatval)); # test other types of indexes connection master; -drop table if exists federated.t1; -CREATE TABLE federated.t1 - (id int NOT NULL auto_increment, - name char(32) NOT NULL DEFAULT '', - bincol binary(4) NOT NULL, - floatval decimal(5,2) NOT NULL DEFAULT 0.0, - other int NOT NULL DEFAULT 0, - primary key(id), - key nameoth(name,other), - key bincol(bincol), - key floatval(floatval)) - ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `id` int NOT NULL auto_increment, + `name` char(32) NOT NULL DEFAULT '', + `bincol` binary(4) NOT NULL, + `floatval` decimal(5,2) NOT NULL DEFAULT 0.0, + `other` int NOT NULL DEFAULT 0, + PRIMARY KEY (id), + KEY nameoth(name,other), + KEY bincol(bincol), + KEY floatval(floatval)) + ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 + COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; -insert into federated.t1 (name, bincol, floatval, other) values ('first', 0x65, 11.11, 1111); -insert into federated.t1 (name, bincol, floatval, other) values ('second', 0x66, 22.22, 2222); -insert into federated.t1 (name, bincol, floatval, other) values ('third', 'g', 22.22, 2222); -select * from federated.t1; -select * from federated.t1 where name = 'second'; -select * from federated.t1 where bincol= 'f'; -select * from federated.t1 where bincol= 0x66; -select * from federated.t1 where bincol= 0x67; -select * from federated.t1 where bincol= 'g'; -select * from federated.t1 where floatval=11.11; -select * from federated.t1 where name='third'; -select * from federated.t1 where other=2222; -select * from federated.t1 where name='third' and other=2222; +INSERT INTO federated.t1 (name, bincol, floatval, other) + VALUES ('first', 0x65, 11.11, 1111); +INSERT INTO federated.t1 (name, bincol, floatval, other) + VALUES ('second', 0x66, 22.22, 2222); +INSERT INTO federated.t1 (name, bincol, floatval, other) + VALUES ('third', 'g', 22.22, 2222); +SELECT * FROM federated.t1; +SELECT * FROM federated.t1 WHERE name = 'second'; +SELECT * FROM federated.t1 WHERE bincol= 'f'; +SELECT * FROM federated.t1 WHERE bincol= 0x66; +SELECT * FROM federated.t1 WHERE bincol= 0x67; +SELECT * FROM federated.t1 WHERE bincol= 'g'; +SELECT * FROM federated.t1 WHERE floatval=11.11; +SELECT * FROM federated.t1 WHERE name='third'; +SELECT * FROM federated.t1 WHERE other=2222; +SELECT * FROM federated.t1 WHERE name='third' and other=2222; # test NULLs connection slave; -drop table if exists federated.t1; -CREATE TABLE federated.t1 (id int, name varchar(32), floatval float, other int) DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( + `id` int, + `name` varchar(32), + `floatval` float, + `other` int) +DEFAULT CHARSET=latin1; connection master; -drop table if exists federated.t1; -CREATE TABLE federated.t1 (id int, name varchar(32), floatval float, other int) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `id` int, + `name` varchar(32), + `floatval` float, + `other` int) +ENGINE="FEDERATED" +DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + # these both should be the same -insert into federated.t1 values (NULL, NULL, NULL, NULL); -insert into federated.t1 values (); -insert into federated.t1 (id) values (1); -insert into federated.t1 (name, floatval, other) values ('foo', 33.33333332, NULL); -insert into federated.t1 (name, floatval, other) values (0, 00.3333, NULL); -select * from federated.t1; -select count(*) from federated.t1 where id IS NULL and name IS NULL and floatval IS NULL and other IS NULL; +INSERT INTO federated.t1 values (NULL, NULL, NULL, NULL); +INSERT INTO federated.t1 values (); +INSERT INTO federated.t1 (id) VALUES (1); +INSERT INTO federated.t1 (name, floatval, other) + VALUES ('foo', 33.33333332, NULL); +INSERT INTO federated.t1 (name, floatval, other) + VALUES (0, 00.3333, NULL); +SELECT * FROM federated.t1; +SELECT count(*) FROM federated.t1 +WHERE id IS NULL +AND name IS NULL +AND floatval IS NULL +AND other IS NULL; connection slave; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( blurb_id int NOT NULL DEFAULT 0, blurb text default '', primary key(blurb_id)) DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( + `blurb_id` int NOT NULL DEFAULT 0, + `blurb` text default '', + PRIMARY KEY (blurb_id)) + DEFAULT CHARSET=latin1; connection master; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( blurb_id int NOT NULL DEFAULT 0, blurb text default '', primary key(blurb_id)) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `blurb_id` int NOT NULL DEFAULT 0, + `blurb` text default '', + PRIMARY KEY (blurb_id)) + ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 + COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; INSERT INTO federated.t1 VALUES (1, " MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values."); INSERT INTO federated.t1 VALUES (2, "All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE."); INSERT INTO federated.t1 VALUES (3, " A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. "); INSERT INTO federated.t1 VALUES(4, "Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:"); -select * from federated.t1; +SELECT * FROM federated.t1; connection slave; -drop table if exists federated.t1; -create table federated.t1 (a int not null, b int not null, c int not null, primary key (a),key(b)); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( + `a` int NOT NULL, + `b` int NOT NULL, + `c` int NOT NULL, + PRIMARY KEY (a),key(b)); connection master; -drop table if exists federated.t1; -create table federated.t1 (a int not null, b int not null, c int not null, primary key (a),key(b)) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `a` int NOT NULL, + `b` int NOT NULL, + `c` int NOT NULL, + PRIMARY KEY (a), + KEY (b)) + ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 + COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; -insert into federated.t1 values (3,3,3),(1,1,1),(2,2,2),(4,4,4); -explain select * from federated.t1 order by a; -explain select * from federated.t1 order by b; -explain select * from federated.t1 order by c; -explain select a from federated.t1 order by a; -explain select b from federated.t1 order by b; -explain select a,b from federated.t1 order by b; -explain select a,b from federated.t1; -explain select a,b,c from federated.t1; +INSERT INTO federated.t1 VALUES (3,3,3),(1,1,1),(2,2,2),(4,4,4); +EXPLAIN SELECT * FROM federated.t1 ORDER BY a; +EXPLAIN SELECT * FROM federated.t1 ORDER BY b; +EXPLAIN SELECT * FROM federated.t1 ORDER BY c; +EXPLAIN SELECT a FROM federated.t1 ORDER BY a; +EXPLAIN SELECT b FROM federated.t1 ORDER BY b; +EXPLAIN SELECT a,b FROM federated.t1 ORDER BY b; +EXPLAIN SELECT a,b FROM federated.t1; +EXPLAIN SELECT a,b,c FROM federated.t1; connection slave; -drop table if exists federated.t1; -create table federated.t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17 int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int, i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34 @@ -336,10 +434,12 @@ int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998 int, i999 int, i1000 int, b blob) row_format=dynamic; connection master; -drop table if exists federated.t1; -create table federated.t1 (i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 -int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, i17 -int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int, +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 +(i1 int, i2 int, i3 int, i4 int, i5 int, i6 int, i7 int, i8 +int, i9 int, i10 int, i11 int, i12 int, i13 int, i14 int, i15 int, i16 int, +i17 int, i18 int, i19 int, i20 int, i21 int, i22 int, i23 int, i24 int, i25 int, i26 int, i27 int, i28 int, i29 int, i30 int, i31 int, i32 int, i33 int, i34 int, i35 int, i36 int, i37 int, i38 int, i39 int, i40 int, i41 int, i42 int, i43 int, i44 int, i45 int, i46 int, i47 int, i48 int, i49 int, i50 int, i51 @@ -461,8 +561,14 @@ int, i967 int, i968 int, i969 int, i970 int, i971 int, i972 int, i973 int, i974 int, i975 int, i976 int, i977 int, i978 int, i979 int, i980 int, i981 int, i982 int, i983 int, i984 int, i985 int, i986 int, i987 int, i988 int, i989 int, i990 int, i991 int, i992 int, i993 int, i994 int, i995 int, i996 int, i997 int, i998 -int, i999 int, i1000 int, b blob) row_format=dynamic ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +int, i999 int, i1000 int, b blob) +row_format=dynamic +ENGINE="FEDERATED" +DEFAULT CHARSET=latin1 +COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + +INSERT INTO federated.t1 +values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -501,38 +607,54 @@ insert into federated.t1 values (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "PatrickG"); -update federated.t1 set b=repeat('a',256); -update federated.t1 set i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0, i10=0; -select * from federated.t1 where i9=0 and i10=0; -update federated.t1 set i50=20; -select * from federated.t1; -delete from federated.t1 where i51=20; -select * from federated.t1; -delete from federated.t1 where i50=20; -select * from federated.t1; +UPDATE federated.t1 SET b=repeat('a',256); +UPDATE federated.t1 SET i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0, i10=0; +SELECT * FROM federated.t1 WHERE i9=0 and i10=0; +UPDATE federated.t1 SET i50=20; +SELECT * FROM federated.t1; +DELETE FROM federated.t1 WHERE i51=20; +SELECT * FROM federated.t1; +DELETE FROM federated.t1 WHERE i50=20; +SELECT * FROM federated.t1; connection slave; -drop table if exists federated.t1; -create table federated.t1 (id int NOT NULL auto_increment, code char(20) NOT NULL, fileguts blob NOT NULL, creation_date datetime, entered_time datetime default '2004-04-04 04:04:04', primary key(id), index(code), index(fileguts(10))) DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 (id int NOT NULL auto_increment, code char(20) NOT NULL, fileguts blob NOT NULL, creation_date datetime, entered_time datetime default '2004-04-04 04:04:04', PRIMARY KEY(id), index(code), index(fileguts(10))) DEFAULT CHARSET=latin1; connection master; -drop table if exists federated.t1; -create table federated.t1 (id int NOT NULL auto_increment, code char(20) NOT NULL, fileguts blob NOT NULL, creation_date datetime, entered_time datetime default '2004-04-04 04:04:04', primary key(id), index(code), index(fileguts(10))) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (code, fileguts, creation_date) values ('ASDFWERQWETWETAWETA', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2003-03-03 03:03:03'); -insert into federated.t1 (code, fileguts, creation_date) values ('DEUEUEUEUEUEUEUEUEU', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2004-04-04 04:04:04'); -insert into federated.t1 (code, fileguts, creation_date) values ('DEUEUEUEUEUEUEUEUEU', 'jimbob', '2004-04-04 04:04:04'); -select * from federated.t1; +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + id int NOT NULL auto_increment, + code char(20) NOT NULL, + fileguts blob NOT NULL, + creation_date datetime, + entered_time datetime default '2004-04-04 04:04:04', + PRIMARY KEY(id), + index(code), + index(fileguts(10))) + ENGINE="FEDERATED" DEFAULT CHARSET=latin1 + COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; +INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('ASDFWERQWETWETAWETA', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2003-03-03 03:03:03'); +INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2004-04-04 04:04:04'); +INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', 'jimbob', '2004-04-04 04:04:04'); +SELECT * FROM federated.t1; # test blob indexes -select * from federated.t1 where fileguts = 'jimbob'; +SELECT * FROM federated.t1 WHERE fileguts = 'jimbob'; # test blob with binary connection slave; -drop table if exists federated.t1; -CREATE TABLE federated.t1 (a BLOB); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 (`a` BLOB); connection master; -drop table if exists federated.t1; -CREATE TABLE federated.t1 (a BLOB) ENGINE="FEDERATED" COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `a` BLOB) +ENGINE="FEDERATED" +COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + INSERT INTO federated.t1 VALUES (0x00); INSERT INTO federated.t1 VALUES (0x0001); INSERT INTO federated.t1 VALUES (0x0100); @@ -541,66 +663,89 @@ SELECT HEX(a) FROM federated.t1; # TODO # -# create table federated.t1 (a char(20)) charset=cp1251 ENGINE="FEDERATED" COMMENT="mysql://root@127.0.0.1:9308/federated/t1"; +# CREATE TABLE federated.t1 +# (a char(20)) charset=cp1251 +# ENGINE="FEDERATED" COMMENT="mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1"; # # connection slave; -# drop table if exists federated.t1; -# create table federated.t1 (a char(20)) charset=cp1251; +# DROP TABLE IF EXISTS federated.t1; +# CREATE TABLE federated.t1 (a char(20)) charset=cp1251; # # connection master; -# insert into federated.t1 values (_cp1251'À-ÁÂÃ-1'); -# insert into federated.t1 values (_cp1251'Á-ÂÃÄ-2'); -# set names cp1251; -# insert into federated.t1 values ('Â-ÃÄÅ-3'); -# insert into federated.t1 values ('Ã-ŨÆ-4'); -# select * from federated.t1; +# INSERT INTO federated.t1 values (_cp1251'À-ÁÂÃ-1'); +# INSERT INTO federated.t1 values (_cp1251'Á-ÂÃÄ-2'); +# SET names cp1251; +# INSERT INTO federated.t1 values ('Â-ÃÄÅ-3'); +# INSERT INTO federated.t1 values ('Ã-ŨÆ-4'); +# SELECT * FROM federated.t1; # select hex(a) from federated.t1; -# select hex(a) from federated.t1 order by a desc; -# update federated.t1 set a='À-ÁÂÃ-1íîâûé' where a='À-ÁÂÃ-1'; -# select * from federated.t1; -# delete from federated.t1 where a='Ã-ŨÆ-4'; -# select * from federated.t1; -# delete from federated.t1 where a>'Â-'; -# select * from federated.t1; -# set names default; +# select hex(a) from federated.t1 ORDER BY a desc; +# update federated.t1 SET a='À-ÁÂÃ-1íîâûé' WHERE a='À-ÁÂÃ-1'; +# SELECT * FROM federated.t1; +# DELETE FROM federated.t1 WHERE a='Ã-ŨÆ-4'; +# SELECT * FROM federated.t1; +# DELETE FROM federated.t1 WHERE a>'Â-'; +# SELECT * FROM federated.t1; +# SET names default; # -# drop table if exists federated.t1; +# DROP TABLE IF EXISTS federated.t1; # # test joins with non-federated table connection slave; -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id)); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( + `id` int(20) NOT NULL auto_increment, + `country_id` int(20) NOT NULL DEFAULT 0, + `name` varchar(32), + `other` varchar(20), + PRIMARY KEY (`id`), + key (country_id)); connection master; -drop table if exists federated.countries; -CREATE TABLE federated.countries ( `id` int(20) NOT NULL auto_increment, `country` varchar(32), primary key (id)); -insert into federated.countries (country) values ('India'); -insert into federated.countries (country) values ('Germany'); -insert into federated.countries (country) values ('Italy'); -insert into federated.countries (country) values ('Finland'); -insert into federated.countries (country) values ('Ukraine'); +DROP TABLE IF EXISTS federated.countries; +CREATE TABLE federated.countries ( + `id` int(20) NOT NULL auto_increment, + `country` varchar(32), + PRIMARY KEY (id)); +INSERT INTO federated.countries (country) VALUES ('India'); +INSERT INTO federated.countries (country) VALUES ('Germany'); +INSERT INTO federated.countries (country) VALUES ('Italy'); +INSERT INTO federated.countries (country) VALUES ('Finland'); +INSERT INTO federated.countries (country) VALUES ('Ukraine'); -drop table if exists federated.t1; -CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, `country_id` int(20) NOT NULL DEFAULT 0, `name` varchar(32), `other` varchar(20), PRIMARY KEY (`id`), key (country_id) ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 COMMENT='mysql://root@127.0.0.1:9308/federated/t1'; -insert into federated.t1 (name, country_id, other) values ('Kumar', 1, 11111); -insert into federated.t1 (name, country_id, other) values ('Lenz', 2, 22222); -insert into federated.t1 (name, country_id, other) values ('Marizio', 3, 33333); -insert into federated.t1 (name, country_id, other) values ('Monty', 4, 33333); -insert into federated.t1 (name, country_id, other) values ('Sanja', 5, 33333); +DROP TABLE IF EXISTS federated.t1; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( + `id` int(20) NOT NULL auto_increment, + `country_id` int(20) NOT NULL DEFAULT 0, + `name` varchar(32), + `other` varchar(20), + PRIMARY KEY (`id`), + KEY (country_id) ) + ENGINE="FEDERATED" DEFAULT CHARSET=latin1 + COMMENT='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; -select federated.t1.*, federated.countries.country from federated.t1 left join federated.countries on federated.t1.country_id = federated.countries.id; +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Kumar', 1, 11111); +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Lenz', 2, 22222); +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Marizio', 3, 33333); +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Monty', 4, 33333); +INSERT INTO federated.t1 (name, country_id, other) VALUES ('Sanja', 5, 33333); -drop table federated.countries; +SELECT federated.t1.*, federated.countries.country +FROM federated.t1 left join federated.countries +ON federated.t1.country_id = federated.countries.id; + +DROP TABLE federated.countries; connection master; --disable_warnings -drop table if exists federated.t1; -drop database if exists federated; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; --enable_warnings connection slave; --disable_warnings -drop table if exists federated.t1; -drop database if exists federated; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; --enable_warnings diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index cf704f9f569..06e7a2f0aa6 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -21,27 +21,27 @@ ha_federated.cc - MySQL Federated Storage Engine Patrick Galbraith and Brian Aker, 2004 - This is a handler which uses a remote database as the data file, as + This is a handler which uses a foreign database as the data file, as opposed to a handler like MyISAM, which uses .MYD files locally. How this handler works ---------------------------------- - Normal database files are local and as such: You create a table called - 'users', a file such as 'users.MYD' is created. A handler reads, inserts, + Normal database files are local and as such: You create a table called + 'users', a file such as 'users.MYD' is created. A handler reads, inserts, deletes, updates data in this file. The data is stored in particular format, so to read, that data has to be parsed into fields, to write, fields have to - be stored in this format to write to this data file. + be stored in this format to write to this data file. With MySQL Federated storage engine, there will be no local files for each - table's data (such as .MYD). A remote database will store the data that would - normally be in this file. This will necessitate the use of MySQL client API + table's data (such as .MYD). A foreign database will store the data that would + normally be in this file. This will necessitate the use of MySQL client API to read, delete, update, insert this data. The data will have to be retrieve via an SQL call "SELECT * FROM users". Then, to read this data, it will have - to be retrieved via mysql_fetch_row one row at a time, then converted from + to be retrieved via mysql_fetch_row one row at a time, then converted from the column in this select into the format that the handler expects. - The create table will simply create the .frm file, and within the - "CREATE TABLE" SQL, there SHALL be any of the following : + 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 @@ -57,41 +57,41 @@ Only 'mysql://' is supported at this release. - This comment connection string is necessary for the handler to be - able to connect to the remote server. + This comment connection string is necessary for the handler to be + able to connect to the foreign server. The basic flow is this: SQL calls issues locally -> - mysql handler API (data in handler format) -> - mysql client API (data converted to SQL calls) -> - remote database -> mysql client API -> + mysql handler API (data in handler format) -> + mysql client API (data converted to SQL calls) -> + foreign database -> mysql client API -> convert result sets (if any) to handler format -> handler API -> results or rows affected to local What this handler does and doesn't support ------------------------------------------ - * Tables MUST be created on the remote server prior to any action on those - tables via the handler, first version. IMPORTANT: IF you MUST use the + * Tables MUST be created on the foreign server prior to any action on those + tables via the handler, first version. IMPORTANT: IF you MUST use the federated storage engine type on the REMOTE end, MAKE SURE [ :) ] That - the table you connect to IS NOT a table pointing BACK to your ORIGNAL + the table you connect to IS NOT a table pointing BACK to your ORIGNAL table! You know and have heard the screaching of audio feedback? You - know putting two mirror in front of each other how the reflection + know putting two mirror in front of each other how the reflection continues for eternity? Well, need I say more?! * There will not be support for transactions. - * There is no way for the handler to know if the database on the remote end + * There is no way for the handler to know if the foreign database or table has changed. The reason for this is that this database has to work like a - data file that would never be written to by anything other than the - database. The integrity of the data in the local table could be breached - if there was any change to the remote database. + data file that would never be written to by anything other than the + database. The integrity of the data in the local table could be breached + if there was any change to the foreign database. * Support for SELECT, INSERT, UPDATE , DELETE, indexes. * No ALTER TABLE, DROP TABLE or any other Data Definition Language calls. - * Prepared statements will not be used in the first implementation, it + * Prepared statements will not be used in the first implementation, it remains to to be seen whether the limited subset of the client API for the server supports this. - * This uses SELECT, INSERT, UPDATE, DELETE and not HANDLER for its - implementation. + * This uses SELECT, INSERT, UPDATE, DELETE and not HANDLER for its + implementation. * This will not work with the query cache. Method calls @@ -100,7 +100,7 @@ (SELECT) - "SELECT * FROM foo" + "SELECT * FROM foo" ha_federated::info ha_federated::scan_time: ha_federated::rnd_init: share->select_query SELECT * FROM foo @@ -140,7 +140,7 @@ ha_federated::rnd_next ha_federated::convert_row_to_internal_format ha_federated::update_row - + Field::quote_data Field::quote_data @@ -149,7 +149,7 @@ Field::quote_data Field::quote_data - + ha_federated::extra ha_federated::extra ha_federated::extra @@ -160,53 +160,53 @@ How do I use this handler? -------------------------- First of all, you need to build this storage engine: - + ./configure --with-federated-storage-engine make - Next, to use this handler, it's very simple. You must + Next, to use this handler, it's very simple. You must have two databases running, either both on the same host, or on different hosts. - One the server that will be connecting to the remote + One the server that will be connecting to the foreign host (client), you create your table as such: - CREATE TABLE test_table ( + CREATE TABLE test_table ( id int(20) NOT NULL auto_increment, name varchar(32) NOT NULL default '', other int(20) NOT NULL default '0', PRIMARY KEY (id), KEY name (name), - KEY other_key (other)) - ENGINE="FEDERATED" - DEFAULT CHARSET=latin1 + KEY other_key (other)) + ENGINE="FEDERATED" + DEFAULT CHARSET=latin1 COMMENT='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 remote - host information, this being the database your 'client' database - will connect to and use as the "data file". Obviously, the remote - database is running on port 9306, so you want to start up your other - database so that it is indeed on port 9306, and your federated - database on a port other than that. In my setup, I use port 5554 - for federated, and port 5555 for the remote. + Notice the "COMMENT" and "ENGINE" field? This is where you + respectively set the engine type, "FEDERATED" and foreign + host information, this being the database your 'client' database + will connect to and use as the "data file". Obviously, the foreign + database is running on port 9306, so you want to start up your other + database so that it is indeed on port 9306, and your federated + database on a port other than that. In my setup, I use port 5554 + for federated, and port 5555 for the foreign database. - Then, on the remote database: + Then, on the foreign database: - CREATE TABLE test_table ( + CREATE TABLE test_table ( id int(20) NOT NULL auto_increment, name varchar(32) NOT NULL default '', other int(20) NOT NULL default '0', PRIMARY KEY (id), KEY name (name), - KEY other_key (other)) + KEY other_key (other)) ENGINE="" <-- whatever you want, or not specify DEFAULT CHARSET=latin1 ; This table is exactly the same (and must be exactly the same), - except that it is not using the federated handler and does + except that it is not using the federated handler and does not need the URL. - + How to see the handler in action -------------------------------- @@ -214,17 +214,17 @@ When developing this handler, I compiled the federated database with debugging: - ./configure --with-federated-storage-engine + ./configure --with-federated-storage-engine --prefix=/home/mysql/mysql-build/federated/ --with-debug Once compiled, I did a 'make install' (not for the purpose of installing the binary, but to install all the files the binary expects to see in the - diretory I specified in the build with --prefix, - "/home/mysql/mysql-build/federated". - - Then, I started the remote server: + diretory I specified in the build with --prefix, + "/home/mysql/mysql-build/federated". - /usr/local/mysql/bin/mysqld_safe + Then, I started the foreign server: + + /usr/local/mysql/bin/mysqld_safe --user=mysql --log=/tmp/mysqld.5555.log -P 5555 Then, I went back to the directory containing the newly compiled mysqld, @@ -238,18 +238,18 @@ Next, I open several windows for each: 1. Tail the debug trace: tail -f /tmp/mysqld.trace|grep ha_fed - 2. Tail the SQL calls to the remote database: tail -f /tmp/mysqld.5555.log + 2. Tail the SQL calls to the foreign database: tail -f /tmp/mysqld.5555.log 3. A window with a client open to the federated server on port 5554 4. A window with a client open to the federated server on port 5555 - I would create a table on the client to the remote server on port + I would create a table on the client to the foreign server on port 5555, and then to the federated server on port 5554. At this point, I would run whatever queries I wanted to on the federated server, - just always remembering that whatever changes I wanted to make on + just always remembering that whatever changes I wanted to make on the table, or if I created new tables, that I would have to do that - on the remote server. - - Another thing to look for is 'show variables' to show you that you have + on the foreign server. + + Another thing to look for is 'show variables' to show you that you have support for federated handler support: show variables like '%federat%' @@ -264,26 +264,26 @@ Testing ------- - There is a test for MySQL Federated Storage Handler in ./mysql-test/t, + There is a test for MySQL Federated Storage Handler in ./mysql-test/t, federatedd.test It starts both a slave and master database using the same setup that the replication tests use, with the exception that it turns off replication, and sets replication to ignore the test tables. - After ensuring that you actually do have support for the federated storage - handler, numerous queries/inserts/updates/deletes are run, many derived + After ensuring that you actually do have support for the federated storage + handler, numerous queries/inserts/updates/deletes are run, many derived from the MyISAM tests, plus som other tests which were meant to reveal any issues that would be most likely to affect this handler. All tests should work! ;) - To run these tests, go into ./mysql-test (based in the directory you + To run these tests, go into ./mysql-test (based in the directory you built the server in) ./mysql-test-run federatedd - + To run the test, or if you want to run the test and have debug info: ./mysql-test-run --debug federated - This will run the test in debug mode, and you can view the trace and + This will run the test in debug mode, and you can view the trace and log files in the ./mysql-test/var/log directory ls -l mysql-test/var/log/ @@ -307,10 +307,10 @@ Of course, again, you can tail the trace log: - tail -f mysql-test/var/log/master.trace |grep ha_fed + tail -f mysql-test/var/log/master.trace |grep ha_fed As well as the slave query log: - + tail -f mysql-test/var/log/slave.log Files that comprise the test suit @@ -324,7 +324,7 @@ Other tidbits ------------- - These were the files that were modified or created for this + These were the files that were modified or created for this Federated handler to work: ./configure.in @@ -342,7 +342,7 @@ ./mysql-test/include/have_federated_db.inc ./sql/ha_federated.cc ./sql/ha_federated.h - + */ #ifdef __GNUC__ @@ -359,12 +359,11 @@ static HASH federated_open_tables; // Hash used to track open // tables pthread_mutex_t federated_mutex; // This is the mutex we use to // init the hash -static int federated_init= 0; // Variable for checking the +static int federated_init= FALSE; // Variable for checking the // init state of hash -/* - Function we use in the creation of our hash to get key. -*/ +/* Function we use in the creation of our hash to get key. */ + static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, my_bool not_used __attribute__ ((unused))) { @@ -426,7 +425,7 @@ bool federated_db_end() DESCRIPTION populates the share with information about the connection - to the remote database that will serve as the data source. + to the foreign database that will serve as the data source. This string must be specified (currently) in the "comment" field, listed in the CREATE TABLE statement. @@ -451,26 +450,25 @@ bool federated_db_end() 1 failure, wrong string format */ + static int parse_url(FEDERATED_SHARE *share, TABLE *table, uint table_create_flag) { DBUG_ENTER("ha_federated::parse_url"); share->port= 0; - uint error_num= table_create_flag ? ER_CANT_CREATE_TABLE : - ER_CONNECT_TO_MASTER; + uint error_num= (table_create_flag ? ER_CANT_CREATE_TABLE : + ER_CONNECT_TO_MASTER); share->scheme= my_strdup(table->s->comment, MYF(0)); if ((share->username= strstr(share->scheme, "://"))) { share->scheme[share->username - share->scheme]= '\0'; + if (strcmp(share->scheme, "mysql") != 0) - { - my_error(error_num, MYF(0), - "ERROR: federated handler only supports remote 'mysql://' database"); - DBUG_RETURN(1); - } + goto error; + share->username+= 3; if ((share->hostname= strchr(share->username, '@'))) @@ -483,19 +481,13 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, share->username[share->password - share->username]= '\0'; share->password++; share->username= share->username; - /* - make sure there isn't an extra / or @ - */ + /* make sure there isn't an extra / or @ */ if ((strchr(share->password, '/') || strchr(share->hostname, '@'))) - { - my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(1); - } - /* - Found that if the string is: - user:@hostname:port/database/table - Then password is a null string, so set to NULL + goto error; + /* + Found that if the string is: + user:@hostname:port/database/table + Then password is a null string, so set to NULL */ if ((share->password[0] == '\0')) share->password= NULL; @@ -503,15 +495,9 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, else share->username= share->username; - /* - make sure there isn't an extra / or @ - */ + /* make sure there isn't an extra / or @ */ if ((strchr(share->username, '/')) || (strchr(share->hostname, '@'))) - { - my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(1); - } + goto error; if ((share->database= strchr(share->hostname, '/'))) { @@ -534,27 +520,14 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, share->table_base_name++; } else - { - my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(1); - } + goto error; } else - { - my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(1); - } - /* - make sure there's not an extra / - */ + goto error; + /* make sure there's not an extra / */ if ((strchr(share->table_base_name, '/'))) - { - my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(1); - } + goto error; + if (share->hostname[0] == '\0') share->hostname= NULL; @@ -568,45 +541,45 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, DBUG_PRINT("ha_federated::parse_url", ("scheme %s username %s password %s \ - hostname %s port %d database %s tablename %s\n", - share->scheme, share->username, share->password, + hostname %s port %d database %s tablename %s\n", + share->scheme, share->username, share->password, share->hostname, share->port, share->database, share->table_base_name)); } else - { - my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(1); - } + goto error; } else - { - my_error(error_num, MYF(0), - "this connection string is not in the correct format!!!\n"); - DBUG_RETURN(1); - } + goto error; + DBUG_RETURN(0); + +error: + my_error(error_num, MYF(0), + "this connection string is not in the correct format!\n"); + DBUG_RETURN(1); + } -/* +/* Convert MySQL result set row to handler internal format SYNOPSIS convert_row_to_internal_format() - record Byte pointer to record + record Byte pointer to record row MySQL result set row from fetchrow() DESCRIPTION - This method simply iterates through a row returned via fetchrow with + This method simply iterates through a row returned via fetchrow with values from a successful SELECT , and then stores each column's value in the field object via the field object pointer (pointing to the table's - array of field object pointers). This is how the handler needs the data + array of field object pointers). This is how the handler needs the data to be stored to then return results back to the user RETURN VALUE - 0 After fields have had field values stored from record + 0 After fields have had field values stored from record */ + uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) { ulong *lengths; @@ -631,6 +604,28 @@ uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) DBUG_RETURN(0); } +/* + Create a WHERE clause based off of values in keys + Note: This code was inspired by key_copy from key.cc + + SYNOPSIS + create_where_from_key () + to String object to store WHERE clause + key_info KEY struct pointer + key byte pointer containing key + key_length length of key + + DESCRIPTION + Using iteration through all the keys via a KEY_PART_INFO pointer, + This method 'extracts' the value of each key in the byte pointer + *key, and for each key found, constructs an appropriate WHERE clause + + RETURN VALUE + 0 After all keys have been accounted for to create the WHERE clause + 1 No keys found + + */ + bool ha_federated::create_where_from_key(String *to, KEY *key_info, const byte *key, uint key_length) { @@ -644,9 +639,6 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, { Field *field= key_part->field; needs_quotes= field->needs_quotes(); - //bool needs_quotes= type_quote(field->type()); - DBUG_PRINT("ha_federated::create_where_from_key", - ("key name %s type %d", field->field_name, field->type())); uint length= key_part->length; if (second_loop++ && to->append(" AND ", 5)) @@ -675,7 +667,7 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, DBUG_RETURN(1); if (key_part->type == HA_KEYTYPE_BIT) { - /* This is can be threated as a hex string */ + /* This is can be treated as a hex string */ Field_bit *field= (Field_bit *) (key_part->field); char buff[64 + 2], *ptr; byte *end= (byte*)(key)+length; @@ -757,6 +749,7 @@ bool ha_federated::create_where_from_key(String *to, KEY *key_info, pass to each federated handler. Do you have to have one of these? Well, you have pieces that are used for locking, and they are needed to function. */ + static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) { FEDERATED_SHARE *share; @@ -767,17 +760,14 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) uint table_name_length, table_base_name_length; char *tmp_table_name, *tmp_table_base_name, *table_base_name, *select_query; - /* - share->table_name has the file location - we want the actual table's - name! - */ + /* share->table_name has the file location - we want the table's name! */ table_base_name= (char*) table->s->table_name; DBUG_PRINT("ha_federated::get_share", ("table_name %s", table_base_name)); /* - So why does this exist? There is no way currently to init a storage engine. - Innodb and BDB both have modifications to the server to allow them to - do this. Since you will not want to do this, this is probably the next - best method. + So why does this exist? There is no way currently to init a storage engine. + Innodb and BDB both have modifications to the server to allow them to + do this. Since you will not want to do this, this is probably the next + best method. */ pthread_mutex_lock(&federated_mutex); table_name_length= (uint) strlen(table_name); @@ -838,10 +828,11 @@ error: /* - Free lock controls. We call this whenever we close a table. + Free lock controls. We call this whenever we close a table. If the table had the last reference to the share then we free memory associated with it. */ + static int free_share(FEDERATED_SHARE *share) { pthread_mutex_lock(&federated_mutex); @@ -864,10 +855,11 @@ static int free_share(FEDERATED_SHARE *share) /* If frm_error() is called then we will use this to to find out - what file extentions exist for the storage engine. This is - also used by the default rename_table and delete_table method + what file extentions exist for the storage engine. This is + also used by the default rename_table and delete_table method in handler.cc. */ + const char **ha_federated::bas_ext() const { static const char *ext[]= @@ -888,16 +880,17 @@ const char **ha_federated::bas_ext() const all tables by calling ha_open() which then calls the handler specific open(). */ + int ha_federated::open(const char *name, int mode, uint test_if_locked) { - DBUG_ENTER("ha_federated::open"); int rc; + DBUG_ENTER("ha_federated::open"); if (!(share= get_share(name, table))) DBUG_RETURN(1); thr_lock_data_init(&share->lock, &lock, NULL); - /* Connect to remote database mysql_real_connect() */ + /* Connect to foreign database mysql_real_connect() */ mysql= mysql_init(0); DBUG_PRINT("ha_federated::open", ("hostname %s", share->hostname)); DBUG_PRINT("ha_federated::open", ("username %s", share->username)); @@ -929,6 +922,7 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) myisam table. For sql_base.cc look at close_data_tables(). */ + int ha_federated::close(void) { DBUG_ENTER("ha_federated::close"); @@ -949,7 +943,7 @@ int ha_federated::close(void) /* - Checks if a field in a record is SQL NULL. + Checks if a field in a record is SQL NULL. SYNOPSIS field_in_record_is_null() @@ -959,12 +953,13 @@ int ha_federated::close(void) DESCRIPTION This method uses the record format information in table to track - the null bit in record. + the null bit in record. RETURN VALUE 1 if NULL - 0 otherwise + 0 otherwise */ + inline uint field_in_record_is_null(TABLE *table, Field *field, char *record) @@ -996,6 +991,7 @@ inline uint field_in_record_is_null(TABLE *table, Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc, sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc. */ + int ha_federated::write_row(byte *buf) { uint x= 0, num_fields= 0; @@ -1026,9 +1022,9 @@ int ha_federated::write_row(byte *buf) table->timestamp_field->set_time(); /* - get the current query id - the fields that we add to the insert - statement to send to the remote will not be appended unless they match - this query id + get the current query id - the fields that we add to the insert + statement to send to the foreign will not be appended unless they match + this query id */ current_query_id= table->in_use->query_id; DBUG_PRINT("ha_federated::write_row", ("current query id %d", @@ -1041,10 +1037,10 @@ int ha_federated::write_row(byte *buf) insert_string.append(" ("); values_string.append(" VALUES ("); - /* - Even if one field is different, all_fields_same_query_id can't remain - 0 if it remains 0, then that means no fields were specified in the query - such as in the case of INSERT INTO table VALUES (val1, val2, valN) + /* + Even if one field is different, all_fields_same_query_id can't remain + 0 if it remains 0, then that means no fields were specified in the query + such as in the case of INSERT INTO table VALUES (val1, val2, valN) */ for (field= table->field; *field; field++, x++) { @@ -1054,8 +1050,8 @@ int ha_federated::write_row(byte *buf) tmp_query_id= (*field)->query_id; } /* - loop through the field pointer array, add any fields to both the values - list and the fields list that match the current query id + loop through the field pointer array, add any fields to both the values + list and the fields list that match the current query id */ for (field= table->field; *field; field++, x++) { @@ -1101,17 +1097,17 @@ int ha_federated::write_row(byte *buf) } /* - chop of the trailing comma, or if there were no fields, a '(' - So, "INSERT INTO foo (" becomes "INSERT INTO foo " - or, with fields, "INSERT INTO foo (field1, field2," becomes - "INSERT INTO foo (field1, field2" + chop of the trailing comma, or if there were no fields, a '(' + So, "INSERT INTO foo (" becomes "INSERT INTO foo " + or, with fields, "INSERT INTO foo (field1, field2," becomes + "INSERT INTO foo (field1, field2" */ insert_string.chop(); /* - if there were no fields, we don't want to add a closing paren - AND, we don't want to chop off the last char '(' - insert will be "INSERT INTO t1 VALUES ();" + if there were no fields, we don't want to add a closing paren + AND, we don't want to chop off the last char '(' + insert will be "INSERT INTO t1 VALUES ();" */ DBUG_PRINT("ha_federated::write_row", ("x %d num fields %d", x, num_fields)); if (num_fields > 0) @@ -1154,6 +1150,7 @@ int ha_federated::write_row(byte *buf) Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc. */ + int ha_federated::update_row(const byte *old_data, byte *new_data) { uint x= 0; @@ -1162,9 +1159,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) char old_field_value_buffer[IO_SIZE], new_field_value_buffer[IO_SIZE]; char update_buffer[IO_SIZE], where_buffer[IO_SIZE]; - /* - stores the value to be replaced of the field were are updating - */ + /* stores the value to be replaced of the field were are updating */ String old_field_value(old_field_value_buffer, sizeof(old_field_value_buffer), &my_charset_bin); old_field_value.length(0); @@ -1175,14 +1170,14 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) /* stores the update query */ String update_string(update_buffer, sizeof(update_buffer), &my_charset_bin); update_string.length(0); - /* stores the WHERE clause */ + /* stores the WHERE clause */ String where_string(where_buffer, sizeof(where_buffer), &my_charset_bin); where_string.length(0); DBUG_ENTER("ha_federated::update_row"); - has_a_primary_key= table->s->primary_key == 0 ? 1 : 0; + has_a_primary_key= (table->s->primary_key == 0 ? 1 : 0); primary_key_field_num= has_a_primary_key ? table->key_info[table->s->primary_key].key_part->fieldnr - 1 : -1; if (has_a_primary_key) @@ -1193,23 +1188,23 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) update_string.append(" SET "); /* - In this loop, we want to match column names to values being inserted - (while building INSERT statement). + In this loop, we want to match column names to values being inserted + (while building INSERT statement). - Iterate through table->field (new data) and share->old_filed (old_data) - using the same index to created an SQL UPDATE statement, new data is - used to create SET field=value and old data is used to create WHERE - field=oldvalue + Iterate through table->field (new data) and share->old_filed (old_data) + using the same index to created an SQL UPDATE statement, new data is + used to create SET field=value and old data is used to create WHERE + field=oldvalue */ for (Field **field= table->field; *field; field++, x++) { /* - In all of these tests for 'has_a_primary_key', what I'm trying to - accomplish is to only use the primary key in the WHERE clause if the - table has a primary key, as opposed to a table without a primary key - in which case we have to use all the fields to create a WHERE clause - using the old/current values, as well as adding a LIMIT statement + In all of these tests for 'has_a_primary_key', what I'm trying to + accomplish is to only use the primary key in the WHERE clause if the + table has a primary key, as opposed to a table without a primary key + in which case we have to use all the fields to create a WHERE clause + using the old/current values, as well as adding a LIMIT statement */ if (has_a_primary_key) { @@ -1226,7 +1221,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) new_field_value.append("NULL"); else { - // otherwise = + /* otherwise = */ (*field)->val_str(&new_field_value); (*field)->quote_data(&new_field_value); @@ -1299,10 +1294,11 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) ORDER BY clauses can be used. Called in sql_acl.cc and sql_udf.cc to manage internal table information. - Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select + Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select it is used for removing duplicates while in insert it is used for REPLACE calls. */ + int ha_federated::delete_row(const byte *buf) { uint x= 0; @@ -1362,6 +1358,7 @@ int ha_federated::delete_row(const byte *buf) index. This method, which is called in the case of an SQL statement having a WHERE clause on a non-primary key index, simply calls index_read_idx. */ + int ha_federated::index_read(byte *buf, const byte *key, uint key_len __attribute__ ((unused)), enum ha_rkey_function find_flag @@ -1377,9 +1374,10 @@ int ha_federated::index_read(byte *buf, const byte *key, row if any. This is only used to read whole keys. This method is called via index_read in the case of a WHERE clause using - a regular non-primary key index, OR is called DIRECTLY when the WHERE clause + a regular non-primary key index, OR is called DIRECTLY when the WHERE clause uses a PRIMARY KEY index. */ + int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, uint key_len __attribute__ ((unused)), enum ha_rkey_function find_flag @@ -1443,9 +1441,7 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, DBUG_RETURN(rnd_next(buf)); } -/* - Initialized at each key walk (called multiple times unlike ::rnd_init()) -*/ +/* Initialized at each key walk (called multiple times unlike rnd_init()) */ int ha_federated::index_init(uint keynr) { int error; @@ -1456,9 +1452,7 @@ int ha_federated::index_init(uint keynr) DBUG_RETURN(0); } -/* - Used to read forward through the index. -*/ +/* Used to read forward through the index. */ int ha_federated::index_next(byte *buf) { DBUG_ENTER("ha_federated::index_next"); @@ -1478,20 +1472,45 @@ int ha_federated::index_next(byte *buf) Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc, and sql_update.cc. */ + int ha_federated::rnd_init(bool scan) { DBUG_ENTER("ha_federated::rnd_init"); int num_fields, rows; /* - This 'scan' flag is incredibly important for this handler to work properly, - especially with updates that are called with indexes, because what happens - without this is index_read_idx gets called, does a query using the - index in a where clause, calls mysql_store_result, which then rnd_init - (from sql_update.cc) is called after this, which would do a - "select * from table" then a mysql_store_result, wiping out the result - set from index_read_idx's query, which causes the subsequent update_row - to update the wrong row! + This 'scan' flag is incredibly important for this handler to work + properly, especially with updates containing WHERE clauses using + indexed columns. + + When the initial query contains a WHERE clause of the query using an + indexed column, it's index_read_idx that selects the exact record from + the foreign database. + + When there is NO index in the query, either due to not having a WHERE + clause, or the WHERE clause is using columns that are not indexed, a + 'full table scan' done by rnd_init, which in this situation simply means + a 'select * from ...' on the foreign table. + + In other words, this 'scan' flag gives us the means to ensure that if + there is an index involved in the query, we want index_read_idx to + retrieve the exact record (scan flag is 0), and do not want rnd_init + to do a 'full table scan' and wipe out that result set. + + Prior to using this flag, the problem was most apparent with updates. + + An initial query like 'UPDATE tablename SET anything = whatever WHERE + indexedcol = someval', index_read_idx would get called, using a query + constructed with a WHERE clause built from the values of index ('indexcol' + in this case, having a value of 'someval'). mysql_store_result would + then get called (this would be the result set we want to use). + + After this rnd_init (from sql_update.cc) would be called, it would then + unecessarily call "select * from table" on the foreign table, then call + mysql_store_result, which would wipe out the correct previous result set + from the previous call of index_read_idx's that had the result set + containing the correct record, hence update the wrong row! + */ scan_flag= scan; if (scan) @@ -1551,12 +1570,13 @@ int ha_federated::index_end(void) Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, sql_table.cc, and sql_update.cc. */ + int ha_federated::rnd_next(byte *buf) { MYSQL_ROW row; DBUG_ENTER("ha_federated::rnd_next"); - // Fetch a row, insert it back in a row format. + /* Fetch a row, insert it back in a row format. */ current_position= result->data_cursor; DBUG_PRINT("ha_federated::rnd_next", ("current position %d", current_position)); @@ -1580,10 +1600,11 @@ int ha_federated::rnd_next(byte *buf) Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc. */ + void ha_federated::position(const byte *record) { DBUG_ENTER("ha_federated::position"); - //my_store_ptr Add seek storage + /* my_store_ptr Add seek storage */ *(MYSQL_ROW_OFFSET *) ref= current_position; // ref is always aligned DBUG_VOID_RETURN; } @@ -1602,16 +1623,16 @@ void ha_federated::position(const byte *record) int ha_federated::rnd_pos(byte *buf, byte *pos) { DBUG_ENTER("ha_federated::rnd_pos"); - /* - we do not need to do any of this if there has been a scan performed already, or - if this is an update and index_read_idx already has a result set in which to build - it's update query from + /* + we do not need to do any of this if there has been a scan performed + already, or if this is an update and index_read_idx already has a result + set in which to build it's update query from */ if (scan_flag) { statistic_increment(table->in_use->status_var.ha_read_rnd_count, &LOCK_status); - memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos + memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos /* is not aligned */ result->current_row= 0; result->data_cursor= current_position; @@ -1665,10 +1686,11 @@ int ha_federated::rnd_pos(byte *buf, byte *pos) */ /* FIX: later version provide better information to the optimizer */ + void ha_federated::info(uint flag) { DBUG_ENTER("ha_federated::info"); - records= 10000; // fix later + records= 10000; // fix later DBUG_VOID_RETURN; } @@ -1684,6 +1706,7 @@ void ha_federated::info(uint flag) Called from sql_select.cc by JOIN::reinit(). Called from sql_union.cc by st_select_lex_unit::exec(). */ + int ha_federated::delete_all_rows() { DBUG_ENTER("ha_federated::delete_all_rows"); @@ -1735,29 +1758,30 @@ int ha_federated::delete_all_rows() Called from lock.cc by get_lock_data(). */ + THR_LOCK_DATA **ha_federated::store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type) { if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { - /* - Here is where we get into the guts of a row level lock. - If TL_UNLOCK is set - If we are not doing a LOCK TABLE or DISCARD/IMPORT - TABLESPACE, then allow multiple writers + /* + Here is where we get into the guts of a row level lock. + If TL_UNLOCK is set + If we are not doing a LOCK TABLE or DISCARD/IMPORT + TABLESPACE, then allow multiple writers */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) && !thd->in_lock_tables && !thd->tablespace_op) lock_type= TL_WRITE_ALLOW_WRITE; - /* - In queries of type INSERT INTO t1 SELECT ... FROM t2 ... - MySQL would use the lock TL_READ_NO_INSERT on t2, and that - would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts - to t2. Convert the lock to a normal read lock to allow - concurrent inserts to t2. + /* + In queries of type INSERT INTO t1 SELECT ... FROM t2 ... + MySQL would use the lock TL_READ_NO_INSERT on t2, and that + would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts + to t2. Convert the lock to a normal read lock to allow + concurrent inserts to t2. */ if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) @@ -1773,9 +1797,9 @@ THR_LOCK_DATA **ha_federated::store_lock(THD *thd, /* create() does nothing, since we have no local setup of our own. - FUTURE: We should potentially connect to the remote database and - create tables if they do not exist. + FUTURE: We should potentially connect to the foreign database and */ + int ha_federated::create(const char *name, TABLE *table_arg, HA_CREATE_INFO *create_info) { From 77d149a476790caee08cb4a5b57e2ec5362730c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Feb 2005 23:46:40 +0100 Subject: [PATCH 07/20] missing DBUG_RETURN added --- sql/sql_base.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6b75fd1847b..530ef567aaa 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -635,14 +635,14 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list) { - DBUG_ENTER("unique_table"); - DBUG_PRINT("enter", ("table alias: %s", table->alias)); TABLE_LIST *res; const char *d_name= table->db, *t_name= table->table_name; char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME]; + DBUG_ENTER("unique_table"); + DBUG_PRINT("enter", ("table alias: %s", table->alias)); /* temporary table is always unique */ if (table->table && table->table->s->tmp_table != NO_TMP_TABLE) - return 0; + DBUG_RETURN(0); if (table->view) { /* it is view and table opened */ From ea24940fbaa9f4e55f41843c2441fad7c2af5689 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 08:17:03 +0200 Subject: [PATCH 08/20] Fixed XA recovery for InnoDB. Note that XA recovery is still disabled until it has been comprehensive tested. innobase/log/log0log.c: Added general documentation of InnoDB redo-logs. innobase/trx/trx0roll.c: Prepared transactions are not rolled back in a recovery if innobase_force_recovery = 0. But they are rolled back if innobase_force_recovery > 0. innobase/trx/trx0trx.c: Disable the XA code in InnoDB crash recovery until it has been comprehensive tested. SHOW INNODB STATUS now prints different output for prepared transactions. innobase/trx/trx0undo.c: Do not unnecessary write X/Open XA XID. XID is written in the prepare. Space for a XID should be reserved at this stage. sql/ha_innodb.cc: Remove error. --- innobase/log/log0log.c | 26 ++++++++++++++++++++++++++ innobase/trx/trx0roll.c | 12 +++++++++++- innobase/trx/trx0trx.c | 28 +++++++++++++++------------- innobase/trx/trx0undo.c | 14 ++++++-------- sql/ha_innodb.cc | 3 --- 5 files changed, 58 insertions(+), 25 deletions(-) diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c index 1ab91b71e8f..5915146b466 100644 --- a/innobase/log/log0log.c +++ b/innobase/log/log0log.c @@ -24,6 +24,32 @@ Created 12/9/1995 Heikki Tuuri #include "trx0sys.h" #include "trx0trx.h" +/* +General philosophy of InnoDB redo-logs: + +1) Every change to a contents of a data page must be done +through mtr, which in mtr_commit() writes log records +to the InnoDB redo log. + +2) Normally these changes are performed using a mlog_write_ulint() +or similar function. + +3) In some page level operations only a code number of a +c-function and its parameters are written to the log to +reduce the size of the log. + + 3a) You should not add parameters to these kind of functions + (e.g. trx_undo_header_create(), trx_undo_insert_header_reuse()) + + 3b) You should not add such functionality which either change + working when compared with the old or are dependent on data + outside of the page. These kind of functions should implement + self-contained page transformation and it should be unchanged + if you don't have very essential reasons to change log + semantics or format. + +*/ + /* Current free limit of space 0; protected by the log sys mutex; 0 means uninitialized */ ulint log_fsp_current_free_limit = 0; diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c index 559c2cb5128..4c68e0a0dd3 100644 --- a/innobase/trx/trx0roll.c +++ b/innobase/trx/trx0roll.c @@ -440,7 +440,17 @@ loop: if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) { trx = UT_LIST_GET_NEXT(trx_list, trx); } else if (trx->conc_state == TRX_PREPARED) { - trx->sess = trx_dummy_sess; + + /* Roll back all prepared transactions if + innobase_force_recovery > 0 in my.cnf */ + + if (srv_force_recovery > 0) { + trx->conc_state = TRX_ACTIVE; + break; + } else { + trx->sess = trx_dummy_sess; + trx = UT_LIST_GET_NEXT(trx_list, trx); + } } else { break; } diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index a33ca4b8ec3..344fe280711 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -435,14 +435,14 @@ trx_lists_init_at_db_start(void) if (undo->state == TRX_UNDO_PREPARED) { - fprintf(stderr, + fprintf(stderr, "InnoDB: Transaction %lu %lu was in the XA prepared state.\n", ut_dulint_get_high(trx->id), ut_dulint_get_low(trx->id)); - /* trx->conc_state = TRX_PREPARED; */ - trx->conc_state = - TRX_ACTIVE; + trx->conc_state = TRX_ACTIVE; + + /* trx->conc_state = TRX_PREPARED;*/ } else { trx->conc_state = TRX_COMMITTED_IN_MEMORY; @@ -498,16 +498,15 @@ trx_lists_init_at_db_start(void) commit or abort decision from MySQL */ if (undo->state == TRX_UNDO_PREPARED) { - - fprintf(stderr, + fprintf(stderr, "InnoDB: Transaction %lu %lu was in the XA prepared state.\n", - ut_dulint_get_high(trx->id), - ut_dulint_get_low(trx->id)); + ut_dulint_get_high(trx->id), + ut_dulint_get_low(trx->id)); - /* trx->conc_state = TRX_PREPARED; */ - trx->conc_state = - TRX_ACTIVE; + trx->conc_state = TRX_ACTIVE; + /* trx->conc_state = + TRX_PREPARED; */ } else { trx->conc_state = TRX_COMMITTED_IN_MEMORY; @@ -1638,10 +1637,13 @@ trx_print( fputs(", not started", f); break; case TRX_ACTIVE: - case TRX_PREPARED: fprintf(f, ", ACTIVE %lu sec", (ulong)difftime(time(NULL), trx->start_time)); break; + case TRX_PREPARED: + fprintf(f, ", ACTIVE (PREPARED) %lu sec", + (ulong)difftime(time(NULL), trx->start_time)); + break; case TRX_COMMITTED_IN_MEMORY: fputs(", COMMITTED IN MEMORY", f); break; @@ -1938,7 +1940,7 @@ trx_get_trx_by_xid( if (xid->gtrid_length == trx->xid.gtrid_length && xid->bqual_length == trx->xid.bqual_length && - memcmp(xid, &trx->xid, + memcmp(xid->data, trx->xid.data, xid->gtrid_length + xid->bqual_length) == 0) { break; diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c index 545e1b77fee..88185973dfc 100644 --- a/innobase/trx/trx0undo.c +++ b/innobase/trx/trx0undo.c @@ -599,11 +599,10 @@ trx_undo_read_xid( Adds the XA XID after an undo log old-style header. */ static void -trx_undo_header_add_xid( -/*====================*/ +trx_undo_header_add_space_for_xid( +/*==============================*/ page_t* undo_page,/* in: undo log segment header page */ trx_ulogf_t* log_hdr,/* in: undo log header */ - XID* xid, /* in: X/Open XA transaction identification */ mtr_t* mtr) /* in: mtr */ { trx_upagef_t* page_hdr; @@ -620,9 +619,8 @@ trx_undo_header_add_xid( new_free = free + (TRX_UNDO_LOG_XA_HDR_SIZE - TRX_UNDO_LOG_OLD_HDR_SIZE); - trx_undo_write_xid(log_hdr, xid, mtr); - /* Now that we added the XID after the header, update the free offset + /* Add space for a XID after the header, update the free offset fields on the undo log page and in the undo log header */ mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_START, new_free, @@ -1532,7 +1530,7 @@ trx_undo_create( offset = trx_undo_header_create(undo_page, trx_id, mtr); - trx_undo_header_add_xid(undo_page, undo_page + offset, xid, mtr); + trx_undo_header_add_space_for_xid(undo_page, undo_page + offset, mtr); undo = trx_undo_mem_create(rseg, id, type, trx_id, xid, page_no, offset); @@ -1599,7 +1597,7 @@ trx_undo_reuse_cached( if (type == TRX_UNDO_INSERT) { offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr); - trx_undo_header_add_xid(undo_page, undo_page + offset, xid, + trx_undo_header_add_space_for_xid(undo_page, undo_page + offset, mtr); } else { ut_a(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR @@ -1607,7 +1605,7 @@ trx_undo_reuse_cached( == TRX_UNDO_UPDATE); offset = trx_undo_header_create(undo_page, trx_id, mtr); - trx_undo_header_add_xid(undo_page, undo_page + offset, xid, + trx_undo_header_add_space_for_xid(undo_page, undo_page + offset, mtr); } diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index f68ad99ac44..b733af7774e 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3071,9 +3071,6 @@ ha_innobase::unlock_row(void) DBUG_ENTER("ha_innobase::unlock_row"); - ut_ad(prebuilt->trx == - (trx_t*) current_thd->transaction.all.innobase_tid); - if (last_query_id != user_thd->query_id) { ut_print_timestamp(stderr); fprintf(stderr, From 61ffbc31ae2172d3282288bc8c4520ea493c92ae Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 09:27:09 +0200 Subject: [PATCH 09/20] InnoDB: Fix compilation errors on IA-64 Windows innobase/include/srv0srv.h: Declare srv_auto_extend_increment and srv_max_purge_lag as ulong, because ulint and ulong are of different size on Win64. innobase/srv/srv0srv.c: Declare srv_auto_extend_increment and srv_max_purge_lag as ulong, because ulint and ulong are of different size on Win64. --- innobase/include/srv0srv.h | 4 ++-- innobase/srv/srv0srv.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index aa2fead53c2..30dd3db7bb1 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -50,7 +50,7 @@ extern ulint* srv_data_file_is_raw_partition; extern ibool srv_auto_extend_last_data_file; extern ulint srv_last_file_size_max; -extern ulint srv_auto_extend_increment; +extern ulong srv_auto_extend_increment; extern ibool srv_created_new_raw; @@ -101,7 +101,7 @@ extern ibool srv_use_doublewrite_buf; extern ibool srv_set_thread_priorities; extern int srv_query_thread_priority; -extern ulint srv_max_purge_lag; +extern ulong srv_max_purge_lag; /*-------------------------------------------*/ extern ulint srv_n_rows_inserted; diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 217a97d84a2..5c5d62f777b 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -86,7 +86,7 @@ ulint srv_last_file_size_max = 0; /* if != 0, this tells the max size auto-extending may increase the last data file size */ -ulint srv_auto_extend_increment = 8; /* If the last data file is +ulong srv_auto_extend_increment = 8; /* If the last data file is auto-extended, we add this many pages to it at a time */ ulint* srv_data_file_is_raw_partition = NULL; @@ -849,7 +849,7 @@ srv_general_init(void) /*======================= InnoDB Server FIFO queue =======================*/ /* Maximum allowable purge history length. <=0 means 'infinite'. */ -ulint srv_max_purge_lag = 0; +ulong srv_max_purge_lag = 0; /************************************************************************* Puts an OS thread to wait if there are too many concurrent threads From 22e0b300a47321ec8dfef0bb8bc5f7c0f1449ce1 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 16:09:22 +0200 Subject: [PATCH 10/20] InnoDB: Commit inserts to the temporary tables created by CREATE INDEX and DROP INDEX every 10,000 rows, similar to ALTER TABLE. sql/ha_innodb.cc: Commit inserts to the temporary tables created by CREATE INDEX and DROP INDEX every 10,000 rows, similar to ALTER TABLE. sql/ha_innodb.h: Remove duplicate declaration of srv_max_purge_lag. --- sql/ha_innodb.cc | 4 +++- sql/ha_innodb.h | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 4f32bb08e9a..0fbac13be28 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -2316,7 +2316,9 @@ ha_innobase::write_row( if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); - if (user_thd->lex->sql_command == SQLCOM_ALTER_TABLE + if ((user_thd->lex->sql_command == SQLCOM_ALTER_TABLE + || user_thd->lex->sql_command == SQLCOM_CREATE_INDEX + || user_thd->lex->sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h index e76a966c6b9..f10785b695d 100644 --- a/sql/ha_innodb.h +++ b/sql/ha_innodb.h @@ -202,7 +202,6 @@ extern "C" { extern ulong srv_max_buf_pool_modified_pct; extern ulong srv_max_purge_lag; extern ulong srv_auto_extend_increment; -extern ulong srv_max_purge_lag; } extern TYPELIB innobase_lock_typelib; From a10fb6971ae10304dac0798e79f5a6824aed0620 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Mar 2005 20:46:23 +0200 Subject: [PATCH 11/20] row0sel.c: row_sel_store_mysql_rec(): Do not try to space-pad BLOB fields. (Bug #8771) innobase/row/row0sel.c: row_sel_store_mysql_rec(): Do not try to space-pad BLOB fields. (Bug #8771) --- innobase/row/row0sel.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c index 2de02081176..7c935128d8a 100644 --- a/innobase/row/row0sel.c +++ b/innobase/row/row0sel.c @@ -2407,10 +2407,11 @@ row_sel_store_mysql_rec( collations will be introduced in 4.1, we hardcode the charset-collation codes here. 5.0 will use a different approach. */ - if (templ->charset == 35 + if (pad_char != '\0' + && (templ->charset == 35 || templ->charset == 90 || (templ->charset >= 128 - && templ->charset <= 144)) { + && templ->charset <= 144))) { /* There are two bytes per char, so the length has to be an even number. */ ut_a(!(templ->mysql_col_len & 1)); From af529fd14c871e78acac4d6c0dd6091086692675 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 00:25:16 +0100 Subject: [PATCH 12/20] Makefile.am: updated ndb test makefile to make src dist complete ndb/test/ndbapi/Makefile.am: updated ndb test makefile to make src dist complete --- ndb/test/ndbapi/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am index 5eb3c215ee5..9a1726ae11a 100644 --- a/ndb/test/ndbapi/Makefile.am +++ b/ndb/test/ndbapi/Makefile.am @@ -74,8 +74,8 @@ testReadPerf_SOURCES = testReadPerf.cpp testLcp_SOURCES = testLcp.cpp testPartitioning_SOURCES = testPartitioning.cpp testBitfield_SOURCES = testBitfield.cpp -DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp -DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp +DbCreate_SOURCES = bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp +DbAsyncGenerator_SOURCES = bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel From 67457597b80a0f636a8477cffcca37bf64c7c1d0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 01:25:17 +0200 Subject: [PATCH 13/20] ha_innodb.cc: Correct indentation + some small style corrections sql/ha_innodb.cc: Correct indentation + some small style corrections --- sql/ha_innodb.cc | 215 ++++++++++++++++++++++++++--------------------- 1 file changed, 118 insertions(+), 97 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 121dbdccc12..35f60d1daf9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB & Innobase Oy +/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy 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 @@ -336,14 +336,18 @@ innobase_release_temporary_latches( /*===============================*/ THD *thd) { + trx_t* trx; + if (!innodb_inited) { return; } - trx_t *trx= (trx_t*) thd->ha_data[innobase_hton.slot]; - if (trx) - innobase_release_stat_resources(trx); + trx = (trx_t*) thd->ha_data[innobase_hton.slot]; + + if (trx) { + innobase_release_stat_resources(trx); + } } /************************************************************************ @@ -743,14 +747,15 @@ transaction internally. */ static void register_trans( -/*============*/ +/*===========*/ THD* thd) /* in: thd to use the handle */ { - /* register the start of the statement */ + /* Register the start of the statement */ trans_register_ha(thd, FALSE, &innobase_hton); + if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { - /* no autocommit mode, register for a transaction */ + /* No autocommit mode, register for a transaction */ trans_register_ha(thd, TRUE, &innobase_hton); } } @@ -1051,7 +1056,7 @@ ha_innobase::init_table_handle_for_HANDLER(void) /************************************************************************* Opens an InnoDB database. */ -handlerton * +handlerton* innobase_init(void) /*===============*/ /* out: TRUE if error */ @@ -1220,7 +1225,7 @@ innobase_init(void) srv_print_verbose_log = mysqld_embedded ? 0 : 1; - /* Store the default charset-collation number of this MySQL + /* Store the default charset-collation number of this MySQL installation */ data_mysql_default_charset_coll = (ulint)default_charset_info->number; @@ -1346,14 +1351,16 @@ innobase_commit_low( return; } +/* The following will be enabled later when we put the 4.1 functionality back +to 5.0. */ #ifdef DISABLE_HAVE_REPLICATION if (current_thd->slave_thread) { /* Update the replication position info inside InnoDB */ trx->mysql_master_log_file_name = active_mi->rli.group_master_log_name; - trx->mysql_master_log_pos= ((ib_longlong) - active_mi->rli.future_group_master_log_pos); + trx->mysql_master_log_pos = ((ib_longlong) + active_mi->rli.future_group_master_log_pos); } #endif /* HAVE_REPLICATION */ @@ -1456,7 +1463,8 @@ innobase_commit( "InnoDB: but trx->conc_state != TRX_NOT_STARTED\n"); } - if (all || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + if (all + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { /* We were instructed to commit the whole transaction, or this is an SQL statement end and autocommit is on */ @@ -1489,10 +1497,9 @@ innobase_commit( DBUG_RETURN(0); } -/* - don't delete it - it may be re-enabled later - as an optimization for the most common case InnoDB+binlog -*/ +/* The following defined-out code will be enabled later when we put the +MySQL-4.1 functionality back to 5.0. This is needed to get InnoDB Hot Backup +to work. */ #if 0 /********************************************************************* This is called when MySQL writes the binlog entry for the current @@ -1627,7 +1634,8 @@ innobase_rollback( row_unlock_table_autoinc_for_mysql(trx); } - if (all || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + if (all + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { error = trx_rollback_for_mysql(trx); trx->active_trans = 0; @@ -1686,6 +1694,7 @@ innobase_rollback_to_savepoint( ib_longlong mysql_binlog_cache_pos; int error = 0; trx_t* trx; + char name[64]; DBUG_ENTER("innobase_rollback_to_savepoint"); @@ -1698,8 +1707,8 @@ innobase_rollback_to_savepoint( innobase_release_stat_resources(trx); /* TODO: use provided savepoint data area to store savepoint data */ - char name[64]; - longlong2str((ulonglong)savepoint,name,36); + + longlong2str((ulonglong)savepoint, name, 36); error = trx_rollback_to_savepoint_for_mysql(trx, name, &mysql_binlog_cache_pos); @@ -1708,26 +1717,27 @@ innobase_rollback_to_savepoint( /********************************************************************* Release transaction savepoint name. */ - -static int +static +int innobase_release_savepoint( -/*===========================*/ +/*=======================*/ /* out: 0 if success, HA_ERR_NO_SAVEPOINT if no savepoint with the given name */ THD* thd, /* in: handle to the MySQL thread of the user whose transaction should be rolled back */ - void *savepoint) /* in: savepoint data */ + void* savepoint) /* in: savepoint data */ { int error = 0; trx_t* trx; + char name[64]; DBUG_ENTER("innobase_release_savepoint"); trx = check_trx_exists(thd); /* TODO: use provided savepoint data area to store savepoint data */ - char name[64]; - longlong2str((ulonglong)savepoint,name,36); + + longlong2str((ulonglong)savepoint, name, 36); error = trx_release_savepoint_for_mysql(trx, name); @@ -1736,13 +1746,13 @@ innobase_release_savepoint( /********************************************************************* Sets a transaction savepoint. */ - -static int +static +int innobase_savepoint( /*===============*/ /* out: always 0, that is, always succeeds */ THD* thd, /* in: handle to the MySQL thread */ - void *savepoint) /* in: savepoint data */ + void* savepoint) /* in: savepoint data */ { int error = 0; trx_t* trx; @@ -1911,7 +1921,8 @@ ha_innobase::open( fields when packed actually became 1 byte longer, when we also stored the string length as the first byte. */ - upd_and_key_val_buff_len = table->s->reclength + table->s->max_key_length + upd_and_key_val_buff_len = + table->s->reclength + table->s->max_key_length + MAX_REF_PARTS * 3; if (!(mysql_byte*) my_multi_malloc(MYF(MY_WME), &upd_buff, upd_and_key_val_buff_len, @@ -1963,7 +1974,8 @@ ha_innobase::open( innobase_prebuilt = row_create_prebuilt(ib_table); - ((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = table->s->reclength; + ((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len = + table->s->reclength; /* Looks like MySQL-3.23 sometimes has primary key number != 0 */ @@ -1985,13 +1997,11 @@ ha_innobase::open( ((row_prebuilt_t*)innobase_prebuilt) ->clust_index_was_generated = FALSE; - /* - MySQL allocates the buffer for ref. key_info->key_length - includes space for all key columns + one byte for each column - that may be NULL. ref_length must be as exact as possible to - save space, because all row reference buffers are allocated - based on ref_length. - */ + /* MySQL allocates the buffer for ref. key_info->key_length + includes space for all key columns + one byte for each column + that may be NULL. ref_length must be as exact as possible to + save space, because all row reference buffers are allocated + based on ref_length. */ ref_length = table->key_info[primary_key].key_length; } else { @@ -2013,15 +2023,13 @@ ha_innobase::open( ref_length = DATA_ROW_ID_LEN; - /* - If we automatically created the clustered index, then - MySQL does not know about it, and MySQL must NOT be aware - of the index used on scan, to make it avoid checking if we - update the column of the index. That is why we assert below - that key_used_on_scan is the undefined value MAX_KEY. - The column is the row id in the automatical generation case, - and it will never be updated anyway. - */ + /* If we automatically created the clustered index, then + MySQL does not know about it, and MySQL must NOT be aware + of the index used on scan, to make it avoid checking if we + update the column of the index. That is why we assert below + that key_used_on_scan is the undefined value MAX_KEY. + The column is the row id in the automatical generation case, + and it will never be updated anyway. */ if (key_used_on_scan != MAX_KEY) { fprintf(stderr, @@ -2611,7 +2619,8 @@ ha_innobase::write_row( "InnoDB: Dump of 200 bytes around transaction.all: ", stderr); ut_print_buf(stderr, - ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100, 200); + ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100, + 200); putc('\n', stderr); ut_error; } @@ -2646,7 +2655,7 @@ ha_innobase::write_row( src_table = lock_get_src_table( prebuilt->trx, prebuilt->table, &mode); if (!src_table) { - no_commit: +no_commit: /* Unknown situation: do not commit */ /* ut_print_timestamp(stderr); @@ -2669,6 +2678,7 @@ ha_innobase::write_row( } else { /* Ensure that there are no other table locks than LOCK_IX and LOCK_AUTO_INC on the destination table. */ + if (!lock_is_table_exclusive(prebuilt->table, prebuilt->trx)) { goto no_commit; @@ -2746,11 +2756,11 @@ ha_innobase::write_row( if (error == DB_SUCCESS && auto_inc_used) { - /* Fetch the value that was set in the autoincrement field */ + /* Fetch the value that was set in the autoincrement field */ - auto_inc = table->next_number_field->val_int(); + auto_inc = table->next_number_field->val_int(); - if (auto_inc != 0) { + if (auto_inc != 0) { /* This call will calculate the max of the current value and the value supplied by the user and update the counter accordingly */ @@ -2762,15 +2772,15 @@ ha_innobase::write_row( The lock is released at each SQL statement's end. */ - error = row_lock_table_autoinc_for_mysql(prebuilt); + error = row_lock_table_autoinc_for_mysql(prebuilt); - if (error != DB_SUCCESS) { - - error = convert_error_code_to_mysql(error, user_thd); - goto func_exit; - } - dict_table_autoinc_update(prebuilt->table, auto_inc); - } + if (error != DB_SUCCESS) { + error = convert_error_code_to_mysql(error, + user_thd); + goto func_exit; + } + dict_table_autoinc_update(prebuilt->table, auto_inc); + } } innodb_srv_conc_exit_innodb(prebuilt->trx); @@ -2785,7 +2795,6 @@ func_exit: DBUG_RETURN(error); } - /****************************************************************** Converts field data for storage in an InnoDB update vector. */ inline @@ -4514,10 +4523,10 @@ ha_innobase::records_in_range( dict_index_t* index; mysql_byte* key_val_buff2 = (mysql_byte*) my_malloc( table->s->reclength - + table->s->max_key_length + 100, + + table->s->max_key_length + 100, MYF(MY_WME)); ulint buff2_len = table->s->reclength - + table->s->max_key_length + 100; + + table->s->max_key_length + 100; dtuple_t* range_start; dtuple_t* range_end; ib_longlong n_rows; @@ -4674,21 +4683,27 @@ ha_innobase::read_time( ha_rows total_rows; double time_for_scan; - if (index != table->s->primary_key) - return handler::read_time(index, ranges, rows); // Not clustered + if (index != table->s->primary_key) { + /* Not clustered */ + return(handler::read_time(index, ranges, rows)); + } - if (rows <= 2) - return (double) rows; + if (rows <= 2) { + + return((double) rows); + } /* Assume that the read time is proportional to the scan time for all rows + at most one seek per range. */ time_for_scan = scan_time(); - if ((total_rows = estimate_rows_upper_bound()) < rows) - return time_for_scan; + if ((total_rows = estimate_rows_upper_bound()) < rows) { - return (ranges + (double) rows / (double) total_rows * time_for_scan); + return(time_for_scan); + } + + return(ranges + (double) rows / (double) total_rows * time_for_scan); } /************************************************************************* @@ -5106,7 +5121,7 @@ ha_innobase::get_foreign_key_list(THD *thd, List *f_key_list) tmp_buff, i, 1); tmp_buff+= i + 1; f_key_info.referenced_table= make_lex_string(thd, 0, - tmp_buff, strlen(tmp_buff), 1); + tmp_buff, strlen(tmp_buff), 1); for (i= 0;;) { @@ -5624,7 +5639,6 @@ innodb_export_status(void) srv_export_innodb_status(); } - /**************************************************************************** Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB Monitor to the client. */ @@ -5636,6 +5650,8 @@ innodb_show_status( { Protocol *protocol= thd->protocol; trx_t* trx; + long flen; + char* str; DBUG_ENTER("innodb_show_status"); @@ -5652,14 +5668,13 @@ innodb_show_status( /* We let the InnoDB Monitor to output at most 64000 bytes of text. */ - long flen; - char* str; - mutex_enter_noninline(&srv_monitor_file_mutex); rewind(srv_monitor_file); + srv_printf_innodb_monitor(srv_monitor_file); flen = ftell(srv_monitor_file); os_file_set_eof(srv_monitor_file); + if (flen < 0) { flen = 0; } else if (flen > 64000 - 1) { @@ -5669,10 +5684,10 @@ innodb_show_status( /* allocate buffer for the string, and read the contents of the temporary file */ - if (!(str = my_malloc(flen + 1, MYF(0)))) - { - mutex_exit_noninline(&srv_monitor_file_mutex); - DBUG_RETURN(TRUE); + if (!(str = my_malloc(flen + 1, MYF(0)))) { + mutex_exit_noninline(&srv_monitor_file_mutex); + + DBUG_RETURN(TRUE); } rewind(srv_monitor_file); @@ -5686,7 +5701,6 @@ innodb_show_status( if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) { - my_free(str, MYF(0)); DBUG_RETURN(TRUE); @@ -5696,10 +5710,12 @@ innodb_show_status( protocol->store(str, flen, system_charset_info); my_free(str, MYF(0)); - if (protocol->write()) - DBUG_RETURN(TRUE); + if (protocol->write()) { + DBUG_RETURN(TRUE); + } send_eof(thd); + DBUG_RETURN(FALSE); } @@ -6093,7 +6109,7 @@ ha_innobase::get_auto_increment() if (error) { - return(~(ulonglong) 0); + return(~(ulonglong) 0); } return((ulonglong) nr); @@ -6115,7 +6131,8 @@ ha_innobase::cmp_ref( /* Do type-aware comparison of Primary Key members. PK members are always NOT NULL, so no checks for NULL are performed */ - KEY_PART_INFO *key_part= table->key_info[table->s->primary_key].key_part; + KEY_PART_INFO *key_part= + table->key_info[table->s->primary_key].key_part; KEY_PART_INFO *key_part_end= key_part + table->key_info[table->s->primary_key].key_parts; for (; key_part != key_part_end; ++key_part) { @@ -6260,19 +6277,21 @@ innobase_query_is_update(void) thd = (THD *)innobase_current_thd(); - if ( thd->lex->sql_command == SQLCOM_REPLACE || - thd->lex->sql_command == SQLCOM_REPLACE_SELECT || - ( thd->lex->sql_command == SQLCOM_LOAD && - thd->lex->duplicates == DUP_REPLACE )) { - return true; + if (thd->lex->sql_command == SQLCOM_REPLACE || + thd->lex->sql_command == SQLCOM_REPLACE_SELECT || + (thd->lex->sql_command == SQLCOM_LOAD && + thd->lex->duplicates == DUP_REPLACE)) { + + return(1); } - if ( thd->lex->sql_command == SQLCOM_INSERT && - thd->lex->duplicates == DUP_UPDATE ) { - return true; + if (thd->lex->sql_command == SQLCOM_INSERT && + thd->lex->duplicates == DUP_UPDATE) { + + return(1); } - return false; + return(0); } } @@ -6308,7 +6327,8 @@ innobase_xa_prepare( "InnoDB: but trx->conc_state != TRX_NOT_STARTED\n"); } - if (all || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { + if (all + || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) { /* We were instructed to prepare the whole transaction, or this is an SQL statement end and autocommit is on */ @@ -6359,10 +6379,11 @@ innobase_xa_recover( uint len) /* in: number of slots in xid_list */ { if (len == 0 || xid_list == NULL) { - return 0; + + return(0); } - return (trx_recover_for_mysql(xid_list, len)); + return(trx_recover_for_mysql(xid_list, len)); } /*********************************************************************** @@ -6373,7 +6394,7 @@ int innobase_commit_by_xid( /*===================*/ /* out: 0 or error number */ - XID* xid) /* in: X/Open XA Transaction Identification */ + XID* xid) /* in: X/Open XA transaction identification */ { trx_t* trx; @@ -6396,7 +6417,7 @@ int innobase_rollback_by_xid( /*=====================*/ /* out: 0 or error number */ - XID *xid) /* in : X/Open XA Transaction Idenfification */ + XID *xid) /* in: X/Open XA transaction idenfification */ { trx_t* trx; From 26f75ffc83e39ee915e8d4973955c950ddabb35b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 10:35:00 +0100 Subject: [PATCH 14/20] Bug#8306 - TRUNCATE leads to index corruption Added a check, if the table, which we are going to create, is open. This can happen if a MERGE mapped table is TRUNCATEd. myisam/mi_open.c: Bug#8306 - TRUNCATE leads to index corruption Made test_if_reopen() globally available. myisam/myisamdef.h: Bug#8306 - TRUNCATE leads to index corruption Declared test_if_reopen() as globally available. mysql-test/r/myisam.result: Bug#8306 - TRUNCATE leads to index corruption The test result. mysql-test/t/myisam.test: Bug#8306 - TRUNCATE leads to index corruption The test case. --- myisam/mi_create.c | 15 +++++++++++++++ myisam/mi_open.c | 2 +- myisam/myisamdef.h | 1 + mysql-test/r/myisam.result | 18 ++++++++++++++++++ mysql-test/t/myisam.test | 26 ++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 1 deletion(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index f99a2c655d2..da3330627a7 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -533,6 +533,21 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, create_flag=MY_DELETE_OLD; } + /* + If a MRG_MyISAM table is in use, the mapped MyISAM tables are open, + but no entry is made in the table cache for them. + A TRUNCATE command checks for the table in the cache only and could + be fooled to believe, the table is not open. + Pull the emergency brake in this situation. (Bug #8306) + */ + if (test_if_reopen(filename)) + { + my_printf_error(0, "MyISAM table '%s' is in use " + "(most likely by a MERGE table). Try FLUSH TABLES.", + MYF(0), name + dirname_length(name)); + goto err; + } + if ((file= my_create_with_symlink(linkname_ptr, filename, 0, O_RDWR | O_TRUNC, diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 2a327e4bd35..2c85a03c6f4 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -50,7 +50,7 @@ if (pos > end_pos) \ ** In MySQL the server will handle version issues. ******************************************************************************/ -static MI_INFO *test_if_reopen(char *filename) +MI_INFO *test_if_reopen(char *filename) { LIST *pos; diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 736ce3f3869..916932c9eb3 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -705,6 +705,7 @@ void mi_copy_status(void* to,void *from); my_bool mi_check_status(void* param); void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); +extern MI_INFO *test_if_reopen(char *filename); my_bool check_table_is_closed(const char *name, const char *where); int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup); int mi_open_keyfile(MYISAM_SHARE *share); diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index d155a14bb60..eaed7c620e3 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -555,3 +555,21 @@ select count(*) from t1 where a is null; count(*) 2 drop table t1; +create table t1 (c1 int, index(c1)); +create table t2 (c1 int, index(c1)) engine=merge union=(t1); +insert into t1 values (1); +flush tables; +select * from t2; +c1 +1 +flush tables; +truncate table t1; +insert into t1 values (1); +flush tables; +select * from t2; +c1 +1 +truncate table t1; +ERROR HY000: MyISAM table 't1' is in use (most likely by a MERGE table). Try FLUSH TABLES. +insert into t1 values (1); +drop table t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index c8ed7910b76..0babd1f9401 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -524,3 +524,29 @@ explain select count(*) from t1 where a is null; select count(*) from t1 where a is null; drop table t1; +# +# Bug #8306: TRUNCATE leads to index corruption +# +create table t1 (c1 int, index(c1)); +create table t2 (c1 int, index(c1)) engine=merge union=(t1); +insert into t1 values (1); +# Close all tables. +flush tables; +# Open t2 and (implicitly) t1. +select * from t2; +# Truncate after flush works (unless another threads reopens t2 in between). +flush tables; +truncate table t1; +insert into t1 values (1); +# Close all tables. +flush tables; +# Open t2 and (implicitly) t1. +select * from t2; +# Truncate t1, wich was not recognized as open without the bugfix. +# Now, it should fail with a table-in-use error message. +--error 1105 +truncate table t1; +# The insert used to fail on the crashed table. +insert into t1 values (1); +drop table t1,t2; + From e1ba1632fbb444adea39054f6cc1e58e9d1c3ee0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 10:38:25 +0100 Subject: [PATCH 15/20] bug#8151 - truncate leaves a transaction open deadlock in MYSQL_LOG::new_file() style fixes mysql-test/r/innodb.result: one more test for truncate mysql-test/t/innodb.test: one more test for truncate sql/ha_innodb.cc: bug#8151 - truncate leaves a transaction open sql/handler.cc: bug#8151 - truncate leaves a transaction open sql/item.h: style fix sql/item_cmpfunc.cc: style fix sql/item_cmpfunc.h: style fix sql/item_func.cc: style fix sql/item_func.h: style fix sql/log.cc: let new_file() to lock LOCK_index, don't check for prepared_xids in rotate_and_purge() increase thread_safe_increment when LOCK_log is taken sql/log_event.cc: mysqlbinlog now prints a warning if binlog was not closed properly sql/sql_class.h: comments sql/sql_repl.cc: DBUG_ENTER tag corrected --- mysql-test/r/innodb.result | 8 +++--- mysql-test/t/innodb.test | 2 ++ sql/ha_innodb.cc | 2 -- sql/handler.cc | 17 ++++++++++-- sql/item.h | 11 ++++---- sql/item_cmpfunc.cc | 5 ++-- sql/item_cmpfunc.h | 8 +++--- sql/item_func.cc | 5 ++-- sql/item_func.h | 5 ++-- sql/log.cc | 53 +++++++++++++++++--------------------- sql/log_event.cc | 3 +++ sql/sql_class.h | 6 ++--- sql/sql_repl.cc | 2 +- 13 files changed, 66 insertions(+), 61 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index c63c869219a..2c285efafaf 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -906,6 +906,7 @@ truncate table t1; ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction commit; truncate table t1; +truncate table t1; select * from t1; a insert into t1 values(1),(2); @@ -924,6 +925,7 @@ a 1 2 truncate table t1; +truncate table t1; insert into t1 values(1),(2); delete from t1; select * from t1; @@ -1637,14 +1639,14 @@ t2 CREATE TABLE `t2` ( drop table t2, t1; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 152 +Binlog_cache_use 154 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 0 create table t1 (a int) engine=innodb; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 153 +Binlog_cache_use 155 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 1 @@ -1653,7 +1655,7 @@ delete from t1; commit; show status like "binlog_cache_use"; Variable_name Value -Binlog_cache_use 154 +Binlog_cache_use 156 show status like "binlog_cache_disk_use"; Variable_name Value Binlog_cache_disk_use 1 diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 797ad5cb5f9..3c9752bb928 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -591,6 +591,7 @@ insert into t1 values(1),(2); truncate table t1; commit; truncate table t1; +truncate table t1; select * from t1; insert into t1 values(1),(2); delete from t1; @@ -605,6 +606,7 @@ truncate table t1; insert into t1 values(1),(2); select * from t1; truncate table t1; +truncate table t1; insert into t1 values(1),(2); delete from t1; select * from t1; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index f68ad99ac44..cc37410e5f6 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4256,8 +4256,6 @@ ha_innobase::delete_all_rows(void) goto fallback; } - innobase_commit(thd, 1); - error = convert_error_code_to_mysql(error, NULL); DBUG_RETURN(error); diff --git a/sql/handler.cc b/sql/handler.cc index cd3656c6f0d..cc1f1635556 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1606,7 +1606,12 @@ int handler::rename_table(const char * from, const char * to) } /* - Tell the handler to turn on or off transaction in the handler + Tell the storage engine that it is allowed to "disable transaction" in the + handler. It is a hint that ACID is not required - it is used in NDB for + ALTER TABLE, for example, when data are copied to temporary table. + A storage engine may treat this hint any way it likes. NDB for example + starts to commit every now and then automatically. + This hint can be safely ignored. */ int ha_enable_transaction(THD *thd, bool on) @@ -1616,7 +1621,15 @@ int ha_enable_transaction(THD *thd, bool on) DBUG_ENTER("ha_enable_transaction"); thd->transaction.on= on; if (on) - ha_commit(thd); + { + /* + Now all storage engines should have transaction handling enabled. + But some may have it enabled all the time - "disabling" transactions + is an optimization hint that storage engine is free to ignore. + So, let's commit an open transaction (if any) now. + */ + error= end_trans(thd, COMMIT); + } DBUG_RETURN(error); } diff --git a/sql/item.h b/sql/item.h index 4082e77efad..ca69af39f62 100644 --- a/sql/item.h +++ b/sql/item.h @@ -113,7 +113,7 @@ public: typedef bool (Item::*Item_processor)(byte *arg); typedef Item* (Item::*Item_transformer) (byte *arg); -typedef void (*Item_cond_traverser) (const Item *item, void *arg); +typedef void (*Cond_traverser) (const Item *item, void *arg); class Item { Item(const Item &); /* Prevent use of these */ @@ -393,18 +393,17 @@ public: return (this->*processor)(arg); } - virtual Item* transform(Item_transformer transformer, byte *arg) + virtual Item* transform(Item_transformer transformer, byte *arg) { return (this->*transformer)(arg); } - virtual void traverse_cond(Item_cond_traverser traverser, - void *arg, - traverse_order order = POSTFIX) + virtual void traverse_cond(Cond_traverser traverser, + void *arg, traverse_order order) { (*traverser)(this, arg); } - + virtual bool remove_dependence_processor(byte * arg) { return 0; } virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; } virtual bool cleanup_processor(byte *arg); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5d764a734bc..3204e5ac711 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2363,9 +2363,8 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg) return Item_func::transform(transformer, arg); } -void Item_cond::traverse_cond(Item_cond_traverser traverser, - void *arg, - traverse_order order) +void Item_cond::traverse_cond(Cond_traverser traverser, + void *arg, traverse_order order) { List_iterator li(list); Item *item; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 3ec7131aac1..212a3dd4501 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1028,9 +1028,7 @@ public: void copy_andor_arguments(THD *thd, Item_cond *item); bool walk(Item_processor processor, byte *arg); Item *transform(Item_transformer transformer, byte *arg); - void traverse_cond(Item_cond_traverser, - void *arg, - traverse_order order = POSTFIX); + void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); }; @@ -1039,8 +1037,8 @@ public: The class Item_equal is used to represent conjunctions of equality predicates of the form field1 = field2, and field=const in where conditions and on expressions. - - All equality predicates of the form field1=field2 contained in a + + All equality predicates of the form field1=field2 contained in a conjunction are substituted for a sequence of items of this class. An item of this class Item_equal(f1,f2,...fk) represents a multiple equality f1=f2=...=fk. diff --git a/sql/item_func.cc b/sql/item_func.cc index 19228108bfc..5ca2ee2b11f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -360,9 +360,8 @@ bool Item_func::walk (Item_processor processor, byte *argument) return (this->*processor)(argument); } -void Item_func::traverse_cond(Item_cond_traverser traverser, - void *argument, - traverse_order order) +void Item_func::traverse_cond(Cond_traverser traverser, + void *argument, traverse_order order) { if (arg_count) { diff --git a/sql/item_func.h b/sql/item_func.h index b3fa73bb15b..b1ccbfeea53 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -163,9 +163,8 @@ public: uint flags= 0); bool walk(Item_processor processor, byte *arg); Item *transform(Item_transformer transformer, byte *arg); - void traverse_cond(Item_cond_traverser traverser, - void * arg, - traverse_order order = POSTFIX); + void traverse_cond(Cond_traverser traverser, + void * arg, traverse_order order); }; diff --git a/sql/log.cc b/sql/log.cc index 56d16c9c7cf..5d77197a9b9 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1296,10 +1296,9 @@ void MYSQL_LOG::new_file(bool need_lock) } if (need_lock) - { pthread_mutex_lock(&LOCK_log); - pthread_mutex_lock(&LOCK_index); - } + pthread_mutex_lock(&LOCK_index); + safe_mutex_assert_owner(&LOCK_log); safe_mutex_assert_owner(&LOCK_index); @@ -1377,10 +1376,9 @@ void MYSQL_LOG::new_file(bool need_lock) end: if (need_lock) - { - pthread_mutex_unlock(&LOCK_index); pthread_mutex_unlock(&LOCK_log); - } + pthread_mutex_unlock(&LOCK_index); + DBUG_VOID_RETURN; } @@ -1404,11 +1402,7 @@ bool MYSQL_LOG::append(Log_event* ev) bytes_written+= ev->data_written; DBUG_PRINT("info",("max_size: %lu",max_size)); if ((uint) my_b_append_tell(&log_file) > max_size) - { - pthread_mutex_lock(&LOCK_index); new_file(0); - pthread_mutex_unlock(&LOCK_index); - } err: pthread_mutex_unlock(&LOCK_log); @@ -1423,9 +1417,9 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...) DBUG_ENTER("MYSQL_LOG::appendv"); va_list(args); va_start(args,len); - + DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); - + pthread_mutex_lock(&LOCK_log); do { @@ -1438,11 +1432,7 @@ bool MYSQL_LOG::appendv(const char* buf, uint len,...) } while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint))); DBUG_PRINT("info",("max_size: %lu",max_size)); if ((uint) my_b_append_tell(&log_file) > max_size) - { - pthread_mutex_lock(&LOCK_index); new_file(0); - pthread_mutex_unlock(&LOCK_index); - } err: pthread_mutex_unlock(&LOCK_log); @@ -1774,15 +1764,10 @@ err: void MYSQL_LOG::rotate_and_purge(uint flags) { - if (!prepared_xids && // see new_file() for the explanation - ((flags & RP_FORCE_ROTATE) || - (my_b_tell(&log_file) >= (my_off_t) max_size))) + if ((flags & RP_FORCE_ROTATE) || + (my_b_tell(&log_file) >= (my_off_t) max_size)) { - if (flags & RP_LOCK_LOG_IS_ALREADY_LOCKED) - pthread_mutex_lock(&LOCK_index); new_file(!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)); - if (flags & RP_LOCK_LOG_IS_ALREADY_LOCKED) - pthread_mutex_unlock(&LOCK_index); #ifdef HAVE_REPLICATION // QQ why do we need #ifdef here ??? if (expire_logs_days) @@ -1828,9 +1813,8 @@ uint MYSQL_LOG::next_file_id() bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event) { - bool error= 0; - VOID(pthread_mutex_lock(&LOCK_log)); DBUG_ENTER("MYSQL_LOG::write(THD *, IO_CACHE *, Log_event *)"); + VOID(pthread_mutex_lock(&LOCK_log)); if (likely(is_open())) // Should always be true { @@ -1888,12 +1872,22 @@ DBUG_skip_commit: goto err; } signal_update(); - DBUG_PRINT("info",("max_size: %lu",max_size)); - rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED); + /* + if commit_event is Xid_log_event, increase the number of + prepared_xids (it's decreasd in ::unlog()). Binlog cannot be rotated + if there're prepared xids in it - see the comment in new_file() for + an explanation. + If the commit_event is not Xid_log_event (then it's a Query_log_event) + rotate binlog, if necessary. + */ + if (commit_event->get_type_code() == XID_EVENT) + thread_safe_increment(prepared_xids, &LOCK_prep_xids); + else + rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED); } VOID(pthread_mutex_unlock(&LOCK_log)); - DBUG_RETURN(error); + DBUG_RETURN(0); err: if (!write_error) @@ -2992,7 +2986,6 @@ int TC_LOG_BINLOG::log(THD *thd, my_xid xid) { Xid_log_event xle(thd, xid); IO_CACHE *trans_log= (IO_CACHE*)thd->ha_data[binlog_hton.slot]; - thread_safe_increment(prepared_xids, &LOCK_prep_xids); return !binlog_end_trans(thd, trans_log, &xle); // invert return value } @@ -3000,7 +2993,7 @@ void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid) { if (thread_safe_dec_and_test(prepared_xids, &LOCK_prep_xids)) pthread_cond_signal(&COND_prep_xids); - rotate_and_purge(0); // in case ::write() was not able to rotate + rotate_and_purge(0); // as ::write() did not rotate } int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle) diff --git a/sql/log_event.cc b/sql/log_event.cc index 7f92159208b..813636a9ba5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1684,6 +1684,9 @@ void Start_log_event_v3::print(FILE* file, bool short_form, LAST_EVENT_INFO* las if (created) fprintf(file," at startup"); fputc('\n', file); + if (flags & LOG_EVENT_BINLOG_IN_USE_F) + fprintf(file, "# Warning: this binlog was not closed properly. " + "Most probably mysqld crashed writing it.\n"); } if (!artificial_event && created) { diff --git a/sql/sql_class.h b/sql/sql_class.h index 2cd525f54bc..ff30faf1150 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1061,9 +1061,9 @@ public: SAVEPOINT *savepoints; THD_TRANS all; // Trans since BEGIN WORK THD_TRANS stmt; // Trans for current statement - bool on; - XID xid; - enum xa_states xa_state; + bool on; // see ha_enable_transaction() + XID xid; // transaction identifier + enum xa_states xa_state; // used by external XA only /* Tables changed in transaction (that must be invalidated in query cache). List contain only transactional tables, that not invalidated in query diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 3b4e822a3df..b3c963f5f03 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1271,7 +1271,7 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1, bool mysql_show_binlog_events(THD* thd) { Protocol *protocol= thd->protocol; - DBUG_ENTER("show_binlog_events"); + DBUG_ENTER("mysql_show_binlog_events"); List field_list; const char *errmsg = 0; IO_CACHE log; From ff7d3c3de5125b9582e6d2311f86605d2aefe9a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 11:47:09 +0100 Subject: [PATCH 16/20] Variable 'k' declared at both loop and function level caused compiler failures - use function-wide declaration also for loop body. ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Get rid of a duplicate declaration ('Uint32 k;' at function start) that caused compiler failures on 'octane2' (both 32 and 64 bit) and a compiler crash on 'ds20'. It would be better not to use those variable declarations with a loop scope, they have caused compile problems again and again. --- ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 5db0cd7af1b..78209c3affa 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -6443,7 +6443,7 @@ Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr) // write index key attributes AttributeRecordPtr aRecPtr; c_attributeRecordPool.getPtr(aRecPtr, tablePtr.p->firstAttribute); - for (unsigned k = 0; k < opPtr.p->m_attrList.sz; k++) { + for (k = 0; k < opPtr.p->m_attrList.sz; k++) { // insert the attributes in the order decided above in attrid_map // k is new order, current_id is in previous order // ToDo: make sure "current_id" is stored with the table and From 199e195d3dd41d42defd5942a3b9da42e6cf1d5c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 11:49:50 +0100 Subject: [PATCH 17/20] Bug#8306 - TRUNCATE leads to index corruption After merge fix. The bugfix results in a different error message in this situation. --- mysql-test/t/symlink.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 25c78129129..7fb7e81b3b1 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -83,7 +83,7 @@ create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, p create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path"; # Should fail becasue the file t9.MYI already exist in 'run' ---error 1,1 +--error 1,1,1105 eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="$MYSQL_TEST_DIR/var/run"; # Should fail becasue the file t9.MYD already exist in 'tmp' From 618669091378dd1050d678b4b68ad4f31d0132b9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 15:29:46 +0100 Subject: [PATCH 18/20] workaround for a bug removed mysys/my_mmap.c: cleanup sql/ha_innodb.cc: don's start a transaction in prepare(). restore disabled code for ibbackup --- mysys/my_mmap.c | 9 ++------- sql/ha_innodb.cc | 18 ++++++------------ 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index 98243c9d5d8..a111c3dc571 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -28,8 +28,7 @@ int my_msync(int fd, void *addr, size_t len, int flags) return my_sync(fd, MYF(0)); } -#else -#ifdef __WIN__ +#elif defined(__WIN__) static SECURITY_ATTRIBUTES mmap_security_attributes= {sizeof(SECURITY_ATTRIBUTES), 0, TRUE}; @@ -83,11 +82,7 @@ int my_msync(int fd, void *addr, size_t len, int flags) return FlushViewOfFile(addr, len) ? 0 : -1; } -#endif - -#ifndef __WIN__ +#else #warning "no mmap!" #endif -#endif - diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 1251d30eb11..5d348a51555 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -1351,10 +1351,10 @@ innobase_commit_low( return; } -/* The following will be enabled later when we put the 4.1 functionality back -to 5.0. */ -#ifdef DISABLE_HAVE_REPLICATION - if (current_thd->slave_thread) { +#ifdef HAVE_REPLICATION + THD *thd=current_thd; + + if (thd && thd->slave_thread) { /* Update the replication position info inside InnoDB */ trx->mysql_master_log_file_name @@ -6328,13 +6328,7 @@ innobase_xa_prepare( /* We were instructed to prepare the whole transaction, or this is an SQL statement end and autocommit is on */ - /* If there is no active InnoDB transaction, - trx_prepare_for_mysql() will (temporarily) start one */ - - if (trx->active_trans == 0) { - - trx->active_trans = 1; - } + ut_ad(trx->active_trans); error = trx_prepare_for_mysql(trx); } else { @@ -6344,7 +6338,7 @@ innobase_xa_prepare( if (trx->auto_inc_lock) { /* If we had reserved the auto-inc lock for some table in this SQL statement we release it now */ - + row_unlock_table_autoinc_for_mysql(trx); } /* Store the current undo_no of the transaction so that we From 6990e80de834ffd42b7cbef32d8abffc972646c6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 23:16:32 +0300 Subject: [PATCH 19/20] fix to avoid relinking on each "make" server-tools/instance-manager/Makefile.am: "Makefile" target removed --- server-tools/instance-manager/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server-tools/instance-manager/Makefile.am b/server-tools/instance-manager/Makefile.am index d73ba95ea0a..7b1d0383f46 100644 --- a/server-tools/instance-manager/Makefile.am +++ b/server-tools/instance-manager/Makefile.am @@ -50,11 +50,11 @@ libnet_a_LIBADD= $(top_builddir)/sql/password.$(OBJEXT) \ CLEANFILES= net_serv.cc client_settings.h -net_serv.cc: Makefile +net_serv.cc: rm -f $(srcdir)/net_serv.cc @LN_CP_F@ $(top_srcdir)/sql/net_serv.cc $(srcdir)/net_serv.cc -client_settings.h: Makefile +client_settings.h: rm -f $(srcdir)/client_settings.h @LN_CP_F@ $(top_srcdir)/sql/client_settings.h $(srcdir)/client_settings.h From 41624daa4c80a45cdd67be40e14cef9f42349b71 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Mar 2005 16:14:46 -0800 Subject: [PATCH 20/20] WL# 2094, removed federated 'disable' file. BitKeeper/deleted/.del-federated.disabled~a5703a3321e4108: Delete: mysql-test/t/federated.disabled --- mysql-test/t/federated.disabled | 1 - 1 file changed, 1 deletion(-) delete mode 100644 mysql-test/t/federated.disabled diff --git a/mysql-test/t/federated.disabled b/mysql-test/t/federated.disabled deleted file mode 100644 index 5ad728b6f10..00000000000 --- a/mysql-test/t/federated.disabled +++ /dev/null @@ -1 +0,0 @@ -Patrick Galbraith should fix this