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