From 97cdd9df8a67a26335fba3ffbb9daca7b2877b10 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Jul 2006 17:28:50 -0700 Subject: [PATCH 1/4] Bug #17766: The server accepts to create MERGE tables which cannot work Changed the error reporting (and a crash) when inserting data into a MERGE table that has no underlying tables or no INSERT_METHOD specified by reporting that it is read-only. include/my_base.h: Add new handler error mysql-test/r/merge.result: Update results mysql-test/t/merge.test: Add new regression test sql/ha_myisammrg.cc: When trying to insert into a MERGE table with no underlying tables or no INSERT_METHOD, report that it is read-only. sql/handler.cc: Handle new error message --- include/my_base.h | 3 ++- mysql-test/r/merge.result | 12 ++++++++++++ mysql-test/t/merge.test | 17 ++++++++++++++++- sql/ha_myisammrg.cc | 4 ++++ sql/handler.cc | 4 ++++ 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index 076eed9998f..e5744fd1621 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -347,8 +347,9 @@ enum ha_base_keytype { #define HA_ERR_NULL_IN_SPATIAL 158 /* NULLs are not supported in spatial index */ #define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ #define HA_ERR_TABLE_NEEDS_UPGRADE 160 /* The table changed in storage engine */ +#define HA_ERR_TABLE_READONLY 161 /* The table is not writable */ -#define HA_ERR_LAST 160 /*Copy last error nr.*/ +#define HA_ERR_LAST 161 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 568f83b7d6d..2877661e851 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -782,3 +782,15 @@ create table tm (b bit(1)) engine = merge union = (t1,t2); select * from tm; b drop table tm, t1, t2; +create table t1 (a int) insert_method = last engine = merge; +insert into t1 values (1); +ERROR HY000: Table 't1' is read only +create table t2 (a int) engine = myisam; +alter table t1 union (t2); +insert into t1 values (1); +alter table t1 insert_method = no; +insert into t1 values (1); +ERROR HY000: Table 't1' is read only +drop table t2; +drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 400279a826b..9a1980968c5 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -399,4 +399,19 @@ create table tm (b bit(1)) engine = merge union = (t1,t2); select * from tm; drop table tm, t1, t2; -# End of 5.0 tests +# +# Bug #17766: The server accepts to create MERGE tables which cannot work +# +create table t1 (a int) insert_method = last engine = merge; +--error ER_OPEN_AS_READONLY +insert into t1 values (1); +create table t2 (a int) engine = myisam; +alter table t1 union (t2); +insert into t1 values (1); +alter table t1 insert_method = no; +--error ER_OPEN_AS_READONLY +insert into t1 values (1); +drop table t2; +drop table t1; + +--echo End of 5.0 tests diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index d2fd1a9e28a..a22f74df5de 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -132,6 +132,10 @@ int ha_myisammrg::close(void) int ha_myisammrg::write_row(byte * buf) { statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); + + if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables) + return (HA_ERR_TABLE_READONLY); + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) diff --git a/sql/handler.cc b/sql/handler.cc index b40934ea194..0c58950b09f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -426,6 +426,7 @@ static int ha_init_errors(void) SETMSG(HA_ERR_NO_CONNECTION, "Could not connect to storage engine"); SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED)); SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE)); + SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY)); /* Register the error messages for use with my_error(). */ return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST); @@ -1799,6 +1800,9 @@ void handler::print_error(int error, myf errflag) case HA_ERR_TABLE_NEEDS_UPGRADE: textno=ER_TABLE_NEEDS_UPGRADE; break; + case HA_ERR_TABLE_READONLY: + textno= ER_OPEN_AS_READONLY; + break; default: { /* The error was "unknown" to this function. From abbf7ad01461284d8c92fbc385caa4b37fa50765 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Jul 2006 16:33:29 -0700 Subject: [PATCH 2/4] Bug #17608: String literals lost during INSERT query on FEDERATED table The Federated storage engine used Field methods that had arbitrary limits on the amount of data they could process, which caused problems with data over that limit (4K). By removing those Field methods and just using features of the String class, we can avoid this problem. mysql-test/r/federated.result: Add new results mysql-test/t/federated.test: Add new regression test sql/field.cc: Remove unnecessary methods sql/field.h: Remove unnecessary methods sql/ha_federated.cc: Remove use of quote_data, use String::print() to get escaping of strings, and don't bother with needs_quotes, just always quote values. --- mysql-test/r/federated.result | 13 +++++ mysql-test/t/federated.test | 18 +++++++ sql/field.cc | 98 ----------------------------------- sql/field.h | 2 - sql/ha_federated.cc | 58 ++++++++------------- 5 files changed, 54 insertions(+), 135 deletions(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 709e44579e2..d17aedf22f9 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1733,6 +1733,19 @@ id val 2 0 drop table t1; drop table t1; +create table t1 (a longblob not null); +create table t1 +(a longblob not null) engine=federated +connection='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; +insert into t1 values (repeat('a',5000)); +select length(a) from t1; +length(a) +5000 +select length(a) from t1; +length(a) +5000 +drop table t1; +drop table t1; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 773c9121af0..f504fec1c96 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1425,4 +1425,22 @@ drop table t1; connection master; drop table t1; +# +# Bug #17608: String literals lost during INSERT query on FEDERATED table +# +connection slave; +create table t1 (a longblob not null); +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval create table t1 + (a longblob not null) engine=federated + connection='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; +insert into t1 values (repeat('a',5000)); +select length(a) from t1; +connection slave; +select length(a) from t1; +drop table t1; +connection master; +drop table t1; + source include/federated_cleanup.inc; diff --git a/sql/field.cc b/sql/field.cc index 946351efe36..2cf4a2f83af 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1551,104 +1551,6 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table, } -/* - SYNOPSIS - Field::quote_data() - unquoted_string Pointer pointing to the value of a field - - DESCRIPTION - Simple method that passes the field type to the method "type_quote" - To get a true/false value as to whether the value in string1 needs - to be enclosed with quotes. This ensures that values in the final - sql statement to be passed to the remote server will be quoted properly - - RETURN_VALUE - void Immediately - if string doesn't need quote - void Upon prepending/appending quotes on each side of variable - -*/ - -bool Field::quote_data(String *unquoted_string) -{ - char escaped_string[IO_SIZE]; - DBUG_ENTER("Field::quote_data"); - - if (!needs_quotes()) - DBUG_RETURN(0); - - // this is the same call that mysql_real_escape_string() calls - if (escape_string_for_mysql(&my_charset_bin, (char *)escaped_string, - sizeof(escaped_string), unquoted_string->ptr(), - unquoted_string->length()) == (ulong)~0) - DBUG_RETURN(1); - - // reset string, then re-append with quotes and escaped values - unquoted_string->length(0); - if (unquoted_string->append('\'') || - unquoted_string->append((char *)escaped_string) || - unquoted_string->append('\'')) - DBUG_RETURN(1); - DBUG_RETURN(0); -} - - -/* - Quote a field type if needed - - SYNOPSIS - Field::type_quote - - DESCRIPTION - Simple method to give true/false whether a field should be quoted. - Used when constructing INSERT and UPDATE queries to the remote server - see write_row and update_row - - RETURN VALUE - 0 if value is of type NOT needing quotes - 1 if value is of type needing quotes -*/ - -bool Field::needs_quotes(void) -{ - DBUG_ENTER("Field::type_quote"); - - switch (type()) { - //FIX this when kernel is fixed - case MYSQL_TYPE_VARCHAR : - case FIELD_TYPE_STRING : - case FIELD_TYPE_VAR_STRING : - case FIELD_TYPE_YEAR : - case FIELD_TYPE_NEWDATE : - case FIELD_TYPE_TIME : - case FIELD_TYPE_TIMESTAMP : - case FIELD_TYPE_DATE : - case FIELD_TYPE_DATETIME : - case FIELD_TYPE_TINY_BLOB : - case FIELD_TYPE_BLOB : - case FIELD_TYPE_MEDIUM_BLOB : - case FIELD_TYPE_LONG_BLOB : - case FIELD_TYPE_GEOMETRY : - case FIELD_TYPE_BIT: - DBUG_RETURN(1); - - case FIELD_TYPE_DECIMAL : - case FIELD_TYPE_TINY : - case FIELD_TYPE_SHORT : - case FIELD_TYPE_INT24 : - case FIELD_TYPE_LONG : - case FIELD_TYPE_FLOAT : - case FIELD_TYPE_DOUBLE : - case FIELD_TYPE_LONGLONG : - case FIELD_TYPE_NULL : - case FIELD_TYPE_SET : - case FIELD_TYPE_ENUM : - DBUG_RETURN(0); - default: - DBUG_RETURN(0); - } -} - - /**************************************************************************** Field_null, a field that always return NULL ****************************************************************************/ diff --git a/sql/field.h b/sql/field.h index 3b33d3651e3..09638b9a979 100644 --- a/sql/field.h +++ b/sql/field.h @@ -251,8 +251,6 @@ public: ptr= old_ptr; return str; } - bool quote_data(String *unquoted_string); - bool needs_quotes(void); virtual bool send_binary(Protocol *protocol); virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0) { diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index e2988df1619..7f2113ce749 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -124,11 +124,6 @@ ha_federated::write_row - - Field::quote_data - Field::quote_data - - ha_federated::reset (UPDATE) @@ -138,20 +133,10 @@ ha_federated::index_init ha_federated::index_read ha_federated::index_read_idx - Field::quote_data ha_federated::rnd_next ha_federated::convert_row_to_internal_format ha_federated::update_row - - Field::quote_data - Field::quote_data - Field::quote_data - Field::quote_data - Field::quote_data - Field::quote_data - - ha_federated::extra ha_federated::extra ha_federated::extra @@ -1151,7 +1136,7 @@ bool ha_federated::create_where_from_key(String *to, Field *field= key_part->field; uint store_length= key_part->store_length; uint part_length= min(store_length, length); - needs_quotes= field->needs_quotes(); + needs_quotes= 1; DBUG_DUMP("key, start of loop", (char *) ptr, length); if (key_part->null_bit) @@ -1641,20 +1626,21 @@ int ha_federated::write_row(byte *buf) */ has_fields= TRUE; - if ((*field)->is_null()) - insert_field_value_string.append(FEDERATED_NULL); - else - { - (*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); - /* append the value */ - values_string.append(insert_field_value_string); - insert_field_value_string.length(0); + /* append the field value */ + if ((*field)->is_null()) + values_string.append(FEDERATED_NULL); + else + { + (*field)->val_str(&insert_field_value_string); + values_string.append('\''); + insert_field_value_string.print(&values_string); + values_string.append('\''); + + insert_field_value_string.length(0); + } /* append commas between both fields and fieldnames */ /* @@ -1861,8 +1847,9 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) { /* otherwise = */ (*field)->val_str(&field_value); - (*field)->quote_data(&field_value); - update_string.append(field_value); + update_string.append('\''); + field_value.print(&update_string); + update_string.append('\''); field_value.length(0); } @@ -1873,8 +1860,9 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) where_string.append(FEDERATED_EQ); (*field)->val_str(&field_value, (char*) (old_data + (*field)->offset())); - (*field)->quote_data(&field_value); - where_string.append(field_value); + where_string.append('\''); + field_value.print(&where_string); + where_string.append('\''); field_value.length(0); } @@ -1944,17 +1932,17 @@ int ha_federated::delete_row(const byte *buf) if (cur_field->is_null()) { - delete_string.append(FEDERATED_IS); - data_string.append(FEDERATED_NULL); + delete_string.append(FEDERATED_ISNULL); } else { delete_string.append(FEDERATED_EQ); cur_field->val_str(&data_string); - cur_field->quote_data(&data_string); + delete_string.append('\''); + data_string.print(&delete_string); + delete_string.append('\''); } - delete_string.append(data_string); delete_string.append(FEDERATED_AND); } delete_string.length(delete_string.length()-5); // Remove trailing AND From 469813c7f3022035a1e577abbd21c44827b4cf6c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 17 Jul 2006 16:45:04 -0700 Subject: [PATCH 3/4] "BUG #18764: Delete conditions causing inconsistencies in Federated tables" Removed logic in ha_federated::write_row, which checks field query ids in the loop which builds the query to run on the remote server. mysql-test/r/federated.result: "BUG #18764: Delete conditions causing inconsistencies in Federated tables" New test results for test that verifies that one can insert to rows using "insert into... select * from..", delete them by id, then immediately insert them in the same way they were originally inserted. mysql-test/t/federated.test: "BUG #18764: Delete conditions causing inconsistencies in Federated tables" New test that verifies that one can insert to rows using "insert into... select * from..", delete them by id, then immediately insert them in the same way they were originally inserted. sql/ha_federated.cc: "BUG #18764: Delete conditions causing inconsistencies in Federated tables" Removed the logic in ha_federated::write_row which checked the query id of each field and compared it to the thread query id. Each field has a query id, and the problem used to be that if I did an insert no fields specified, the field value would contain the last inserted value for that field. The way to work around this was to see if the query id for that field was the same as the current query id or of the rest of the field query ids. If it wasn't, that told me the query didn't have the field value specified. Somewhere from when I wrote that code to now the problem went away, and there was no longer the need for this logic. Also removed the bool "has_fields", which needs not exist and using table->s->fields is sufficient. --- mysql-test/r/federated.result | 38 +++++++++++++++ mysql-test/t/federated.test | 57 ++++++++++++++++++++++ sql/ha_federated.cc | 91 +++++++++-------------------------- 3 files changed, 119 insertions(+), 67 deletions(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 2eb0c81ec2e..cf75a013572 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1689,6 +1689,44 @@ id c1 c2 9 abc ppc drop table federated.t1, federated.t2; drop table federated.t1, federated.t2; +DROP TABLE IF EXISTS federated.test; +CREATE TABLE federated.test ( +`id` int(11) NOT NULL, +`val1` varchar(255) NOT NULL, +`val2` varchar(255) NOT NULL, +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +DROP TABLE IF EXISTS federated.test_local; +DROP TABLE IF EXISTS federated.test_remote; +CREATE TABLE federated.test_local ( +`id` int(11) NOT NULL, +`val1` varchar(255) NOT NULL, +`val2` varchar(255) NOT NULL, +PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO federated.test_local VALUES (1, 'foo', 'bar'), +(2, 'bar', 'foo'); +CREATE TABLE federated.test_remote ( +`id` int(11) NOT NULL, +`val1` varchar(255) NOT NULL, +`val2` varchar(255) NOT NULL, +PRIMARY KEY (`id`) +) ENGINE=FEDERATED DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/test'; +insert into federated.test_remote select * from federated.test_local; +select * from federated.test_remote; +id val1 val2 +1 foo bar +2 bar foo +delete from federated.test_remote where id in (1,2); +insert into federated.test_remote select * from federated.test_local; +select * from federated.test_remote; +id val1 val2 +2 bar foo +1 foo bar +DROP TABLE federated.test_local; +DROP TABLE federated.test_remote; +DROP TABLE federated.test; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index a8b16edc80a..d6efb870e55 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1365,4 +1365,61 @@ drop table federated.t1, federated.t2; connection slave; drop table federated.t1, federated.t2; +# +# BUG #18764: Delete conditions causing inconsistencies in Federated tables +# +connection slave; +--disable_warnings +DROP TABLE IF EXISTS federated.test; +--enable_warnings +CREATE TABLE federated.test ( + `id` int(11) NOT NULL, + `val1` varchar(255) NOT NULL, + `val2` varchar(255) NOT NULL, + PRIMARY KEY (`id`) + ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +connection master; +--disable_warnings +DROP TABLE IF EXISTS federated.test_local; +DROP TABLE IF EXISTS federated.test_remote; +--enable_warnings +CREATE TABLE federated.test_local ( + `id` int(11) NOT NULL, + `val1` varchar(255) NOT NULL, + `val2` varchar(255) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +INSERT INTO federated.test_local VALUES (1, 'foo', 'bar'), +(2, 'bar', 'foo'); + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.test_remote ( + `id` int(11) NOT NULL, + `val1` varchar(255) NOT NULL, + `val2` varchar(255) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=FEDERATED DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/test'; + +insert into federated.test_remote select * from federated.test_local; + +select * from federated.test_remote; + +delete from federated.test_remote where id in (1,2); + +insert into federated.test_remote select * from federated.test_local; + +select * from federated.test_remote; +--disable_warnings +DROP TABLE federated.test_local; +DROP TABLE federated.test_remote; +--enable_warnings + +connection slave; +--disable_warnings +DROP TABLE federated.test; +--enable_warnings + source include/federated_cleanup.inc; diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 11f676d9cf6..abdcb6dc9c0 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1559,10 +1559,6 @@ inline uint field_in_record_is_null(TABLE *table, int ha_federated::write_row(byte *buf) { - bool has_fields= FALSE; - uint all_fields_have_same_query_id= 1; - ulong current_query_id= 1; - ulong tmp_query_id= 1; char insert_buffer[FEDERATED_QUERY_BUFFER_SIZE]; char values_buffer[FEDERATED_QUERY_BUFFER_SIZE]; char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE]; @@ -1580,23 +1576,11 @@ int ha_federated::write_row(byte *buf) insert_string.length(0); insert_field_value_string.length(0); DBUG_ENTER("ha_federated::write_row"); - DBUG_PRINT("info", - ("table charset name %s csname %s", - table->s->table_charset->name, - table->s->table_charset->csname)); 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 foreign will not be appended unless they match - this query id - */ - current_query_id= table->in_use->query_id; - DBUG_PRINT("info", ("current query id %d", current_query_id)); - /* start both our field and field values strings */ @@ -1609,64 +1593,37 @@ int ha_federated::write_row(byte *buf) values_string.append(FEDERATED_VALUES); values_string.append(FEDERATED_OPENPAREN); - /* - 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++) - { - if (field > table->field && tmp_query_id != (*field)->query_id) - all_fields_have_same_query_id= 0; - - 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 - - You might ask "Why an index variable (has_fields) ?" My answer is that - we need to count how many fields we actually need */ for (field= table->field; *field; field++) { - /* 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)->is_null()) + insert_field_value_string.append(FEDERATED_NULL); + else { - /* - There are some fields. This will be used later to determine - whether to chop off commas and parens. - */ - has_fields= TRUE; - - if ((*field)->is_null()) - insert_field_value_string.append(FEDERATED_NULL); - else - { - (*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); - - /* append the value */ - values_string.append(insert_field_value_string); - insert_field_value_string.length(0); - - /* append commas between both fields and fieldnames */ - /* - unfortunately, we can't use the logic - if *(fields + 1) to make the following - appends conditional because we may not append - if the next field doesn't match the condition: - (((*field)->query_id && (*field)->query_id == current_query_id) - */ - insert_string.append(FEDERATED_COMMA); - values_string.append(FEDERATED_COMMA); + (*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); + + /* append the value */ + values_string.append(insert_field_value_string); + insert_field_value_string.length(0); + + /* append commas between both fields and fieldnames */ + /* + unfortunately, we can't use the logic + if *(fields + 1) to make the following + appends conditional because we may not append + if the next field doesn't match the condition: + (((*field)->query_id && (*field)->query_id == current_query_id) + */ + insert_string.append(FEDERATED_COMMA); + values_string.append(FEDERATED_COMMA); } /* @@ -1678,7 +1635,7 @@ int ha_federated::write_row(byte *buf) AND, we don't want to chop off the last char '(' insert will be "INSERT INTO t1 VALUES ();" */ - if (has_fields) + if (table->s->fields) { /* chops off leading commas */ values_string.length(values_string.length() - strlen(FEDERATED_COMMA)); From 9378fc627ecaf22d47bfd0de1c192953c96d5159 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Jul 2006 18:41:36 -0700 Subject: [PATCH 4/4] "BUG #18764: Delete conditions causing inconsistencies in Federated tables" Post merge changes. --- mysql-test/r/federated.result | 1 - mysql-test/t/federated.test | 1 - sql/ha_federated.cc | 7 +++++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index e975f94baab..5d17afd8cfc 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1727,7 +1727,6 @@ id val1 val2 DROP TABLE federated.test_local; DROP TABLE federated.test_remote; DROP TABLE federated.test; - drop table if exists federated.t1; create table federated.t1 (a int, b int, c int); drop table if exists federated.t1; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index bed168f5b8f..38beab605fd 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1416,7 +1416,6 @@ select * from federated.test_remote; DROP TABLE federated.test_local; DROP TABLE federated.test_remote; --enable_warnings - connection slave; --disable_warnings DROP TABLE federated.test; diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 0012e4ba131..2267c2b5d79 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1589,8 +1589,11 @@ int ha_federated::write_row(byte *buf) else { (*field)->val_str(&insert_field_value_string); - /* quote these fields if they require it */ - (*field)->quote_data(&insert_field_value_string); + values_string.append('\''); + insert_field_value_string.print(&values_string); + values_string.append('\''); + + insert_field_value_string.length(0); } /* append the field name */ insert_string.append((*field)->field_name);