diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index e9158347..7de375a4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6637,7 +6637,9 @@ wsrep_store_key_val_for_row( format) */ uint buff_len,/*!< in: buffer length */ const uchar* record, - bool* key_is_null)/*!< out: full key was null */ + bool* key_is_null,/*!< out: full key was null */ + bool comp) /*!< in: false = the table is + ROW_FORMAT=REDUNDANT */ { KEY* key_info = table->key_info + keynr; KEY_PART_INFO* key_part = key_info->key_part; @@ -6887,10 +6889,33 @@ wsrep_store_key_val_for_row( const CHARSET_INFO* cs= field->charset(); - /* For multi byte character sets we need to - calculate the true length of the key */ - - if (true_len > 0 && cs->mbmaxlen > 1) { + /* InnoDB stores a fixed length CHAR column with + its trailing spaces stripped down to n_chars + bytes, and padded in full where that strip does + not apply, see + row_mysql_store_col_in_innobase_format(). The + reference key of a foreign key is built from + those stored bytes, so the row key has to follow + the same rule. Cutting at n_chars characters + instead gives the same parent row two different + keys as soon as the value holds a multi byte + character. A key part over a column prefix is + not compared against a reference key and keeps + the character cut. */ + if (true_len > 0 && cs->mbmaxlen > 1 + && real_type == MYSQL_TYPE_STRING + && true_len == field->pack_length()) { + if (comp && cs->mbminlen == 1) { + const size_t n_chars= + true_len / cs->mbmaxlen; + + while (true_len > n_chars + && src_start[true_len - 1] + == 0x20) { + true_len--; + } + } + } else if (true_len > 0 && cs->mbmaxlen > 1) { int error; true_len= my_well_formed_length(cs, @@ -10210,7 +10235,8 @@ ha_innobase::wsrep_append_keys( auto len = wsrep_store_key_val_for_row( thd, table, 0, key, WSREP_MAX_SUPPORTED_KEY_LENGTH, - record0, &is_null); + record0, &is_null, + m_prebuilt->table->not_redundant()); if (!is_null) { rcode = wsrep_append_key( @@ -10269,14 +10295,17 @@ ha_innobase::wsrep_append_keys( auto len0 = wsrep_store_key_val_for_row( thd, table, i, key0, WSREP_MAX_SUPPORTED_KEY_LENGTH, - record0, &is_null0); + record0, &is_null0, + m_prebuilt->table->not_redundant()); if (record1) { bool is_null1; auto len1= wsrep_store_key_val_for_row( thd, table, i, key1, WSREP_MAX_SUPPORTED_KEY_LENGTH, - record1, &is_null1); + record1, &is_null1, + m_prebuilt->table + ->not_redundant()); if (is_null0 != is_null1 || len0 != len1 ||