diff options
author | Alexander Barkov <bar@mariadb.com> | 2019-10-18 08:07:40 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2019-10-18 10:15:17 +0400 |
commit | 9a833dc6881b896e65cf76c9699faa6c324e1775 (patch) | |
tree | 25b3daa904d7fb75a50c08d777ae3fce025684f2 | |
parent | 9c9606152505792fcb8f4b7386e5b6a25e2790b4 (diff) | |
download | mariadb-git-9a833dc6881b896e65cf76c9699faa6c324e1775.tar.gz |
MDEV-20856 Bad values in metadata views for partitions on VARBINARY
The old code to print partition values was too complicated:
- it created new Items for character set conversion purposes.
- it mixed string conversion and partition error reporting
in the same code blocks.
Simplifying the code as follows:
- Adding helper methods String::can_be_safely_convert_to() and
String::append_introducer_and_hex().
- Adding DBUG_EXECUTE_IF("generate_partition_syntax_for_frm", push_warning...)
into generate_partition_syntax_for_frm(), to test the PARTITON
clause written to FRM. Adding test partition_utf8-debug.test for this.
- Removing functions get_cs_converted_part_value_from_string() and
get_cs_converted_string_value. Changing get_partition_column_description()
to use Type_handler::partition_field_append_value() instead.
This makes SHOW CREATE TABLE and SELECT FROM I_S.PARTITIONS
use the same code path.
- Changing Type_handler::partition_field_append_value() not to
call convert_charset_partition_constant(), to avoid creating a new Item
for string conversion pursposes.
Rewritting the code to use only String methods.
- Removing error reporting code (ER_PARTITION_FUNCTION_IS_NOT_ALLOWED)
from Type_handler::partition_field_append_value().
The error is correctly detected and reported on the caller level.
So error reporting was redundant here.
Also:
- Moving methods Type_handler::partition_field_*() from sql_partition.cc
to sql_type.cc. This fixes compilation problem with -DPLUGIN_PARTITION=NO,
earlier introduced by the patch for MDEV-20831.
-rw-r--r-- | mysql-test/main/partition_utf8-debug.result | 88 | ||||
-rw-r--r-- | mysql-test/main/partition_utf8-debug.test | 71 | ||||
-rw-r--r-- | mysql-test/main/partition_utf8.result | 22 | ||||
-rw-r--r-- | mysql-test/main/partition_utf8.test | 19 | ||||
-rw-r--r-- | sql/sql_partition.cc | 88 | ||||
-rw-r--r-- | sql/sql_partition.h | 6 | ||||
-rw-r--r-- | sql/sql_show.cc | 175 | ||||
-rw-r--r-- | sql/sql_string.h | 17 | ||||
-rw-r--r-- | sql/sql_type.cc | 139 |
9 files changed, 368 insertions, 257 deletions
diff --git a/mysql-test/main/partition_utf8-debug.result b/mysql-test/main/partition_utf8-debug.result new file mode 100644 index 00000000000..569bec3ea8a --- /dev/null +++ b/mysql-test/main/partition_utf8-debug.result @@ -0,0 +1,88 @@ +# +# Start of 10.5 tests +# +# +# MDEV-20856 Bad values in metadata views for partitions on VARBINARY +# +SET NAMES utf8; +SET @save_dbug = @@debug_dbug; +SET SESSION debug_dbug="+d,generate_partition_syntax_for_frm"; +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (_utf8'Ṡ')); +ERROR HY000: This partition function is not allowed +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN ('Ṡ')); +ERROR HY000: This partition function is not allowed +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (_latin1 0xDF)); +Warnings: +Note 1003 PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (_latin1 0xdf) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +PARTITION_DESCRIPTION +'ß' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (_utf8'ß')); +Warnings: +Note 1003 PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (_latin1 0xdf) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +PARTITION_DESCRIPTION +'ß' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN ('ß')); +Warnings: +Note 1003 PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (_latin1 0xdf) ENGINE = MyISAM) +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (_utf8'ß')); +Warnings: +Note 1003 PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (_utf8 0xc39f) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +PARTITION_DESCRIPTION +'ß' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN ('ß')); +Warnings: +Note 1003 PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (_utf8 0xc39f) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +PARTITION_DESCRIPTION +'ß' +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a VARBINARY(10)) CHARACTER SET utf8 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (0xFF)); +Warnings: +Note 1003 PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (_binary 0xff) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +PARTITION_DESCRIPTION +_binary 0xff +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a DATE) CHARACTER SET utf8 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(NULL))); +Warnings: +Note 1003 PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (NULL) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +PARTITION_DESCRIPTION +NULL +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 (a DATE) CHARACTER SET utf8 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(100))); +Warnings: +Note 1003 PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (_utf8 0x303030302d30302d3030) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +PARTITION_DESCRIPTION +'0000-00-00' +DROP TABLE t1; +SET debug_dbug=@save_dbug; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/partition_utf8-debug.test b/mysql-test/main/partition_utf8-debug.test new file mode 100644 index 00000000000..c321c944676 --- /dev/null +++ b/mysql-test/main/partition_utf8-debug.test @@ -0,0 +1,71 @@ +--source include/have_partition.inc +--source include/have_debug_sync.inc + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-20856 Bad values in metadata views for partitions on VARBINARY +--echo # + +SET NAMES utf8; +SET @save_dbug = @@debug_dbug; +SET SESSION debug_dbug="+d,generate_partition_syntax_for_frm"; + + +--error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (_utf8'Ṡ')); + +--error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN ('Ṡ')); + +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (_latin1 0xDF)); +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (_utf8'ß')); +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET latin1 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN ('ß')); +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (_utf8'ß')); +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a VARCHAR(10)) CHARACTER SET utf8 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN ('ß')); +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + + +CREATE OR REPLACE TABLE t1 (a VARBINARY(10)) CHARACTER SET utf8 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (0xFF)); +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + + +CREATE OR REPLACE TABLE t1 (a DATE) CHARACTER SET utf8 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(NULL))); +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + +CREATE OR REPLACE TABLE t1 (a DATE) CHARACTER SET utf8 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(100))); +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + + +SET debug_dbug=@save_dbug; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/partition_utf8.result b/mysql-test/main/partition_utf8.result index 7718e651423..c9c376787a3 100644 --- a/mysql-test/main/partition_utf8.result +++ b/mysql-test/main/partition_utf8.result @@ -51,3 +51,25 @@ t1 CREATE TABLE `t1` ( insert into t1 values (''); insert into t1 values (_ucs2 0x2020); drop table t1; +# +# Start of 10.5 tests +# +# +# MDEV-20856 Bad values in metadata views for partitions on VARBINARY +# +CREATE TABLE t1 (a VARBINARY(10)) CHARACTER SET utf8 +PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (0xFF)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varbinary(10) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8 + PARTITION BY LIST COLUMNS(`a`) +(PARTITION `p0` VALUES IN (_binary 0xff) ENGINE = MyISAM) +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +PARTITION_DESCRIPTION +_binary 0xff +DROP TABLE t1; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/partition_utf8.test b/mysql-test/main/partition_utf8.test index d3ad7ba671e..8adbb6b30c3 100644 --- a/mysql-test/main/partition_utf8.test +++ b/mysql-test/main/partition_utf8.test @@ -40,3 +40,22 @@ show create table t1; insert into t1 values (''); insert into t1 values (_ucs2 0x2020); drop table t1; + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-20856 Bad values in metadata views for partitions on VARBINARY +--echo # + +CREATE TABLE t1 (a VARBINARY(10)) CHARACTER SET utf8 + PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (0xFF)); +SHOW CREATE TABLE t1; +SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; +DROP TABLE t1; + + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index d95b14c437c..9957a3b064c 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -146,7 +146,7 @@ Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs) item= item->safe_charset_converter(thd, cs); context->table_list= NULL; thd->where= "convert character set partition constant"; - if (item->fix_fields_if_needed(thd, (Item**)NULL)) + if (item && item->fix_fields_if_needed(thd, (Item**)NULL)) item= NULL; thd->where= save_where; context->table_list= save_list; @@ -2240,36 +2240,6 @@ static int add_partition_options(String *str, partition_element *p_elem) } -void -Type_handler::partition_field_type_not_allowed(const LEX_CSTRING &field_name) -{ - my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0), - field_name.str); -} - - -bool -Type_handler::partition_field_check_result_type(Item *item, - Item_result expected_type) -{ - if (item->result_type() != expected_type) - { - my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0)); - return TRUE; - } - return false; -} - - -bool -Type_handler_blob_common::partition_field_check(const LEX_CSTRING &field_name, - Item *item_expr) const -{ - my_error(ER_BLOB_FIELD_IN_PART_FUNC_ERROR, MYF(0)); - return true; -} - - /* Find the given field's Create_field object using name of field @@ -2303,58 +2273,6 @@ static Create_field* get_sql_field(const char *field_name, } -bool -Type_handler_general_purpose_int::partition_field_append_value( - String *str, - Item *item_expr, - CHARSET_INFO *field_cs, - partition_value_print_mode_t mode) - const -{ - DBUG_ASSERT(item_expr->cmp_type() == INT_RESULT); - StringBuffer<21> tmp; - longlong value= item_expr->val_int(); - tmp.set(value, system_charset_info); - return str->append(tmp); -} - - -bool Type_handler::partition_field_append_value( - String *str, - Item *item_expr, - CHARSET_INFO *field_cs, - partition_value_print_mode_t mode) - const -{ - DBUG_ASSERT(cmp_type() != INT_RESULT); - - if (field_cs && field_cs != item_expr->collation.collation) - { - if (!(item_expr= convert_charset_partition_constant(item_expr, - field_cs))) - { - my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); - return true; - } - } - StringBuffer<MAX_KEY_LENGTH> buf; - String val_conv, *res; - val_conv.set_charset(system_charset_info); - if (!(res= item_expr->val_str(&buf))) - { - my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); - return true; - } - if (get_cs_converted_part_value_from_string(current_thd, - item_expr, res, - &val_conv, field_cs, - mode == - PARTITION_VALUE_PRINT_MODE_FRM)) - return true; - return str->append(val_conv); -} - - static int add_column_list_values(String *str, partition_info *part_info, part_elem_value *list_value, HA_CREATE_INFO *create_info, @@ -2564,6 +2482,10 @@ char *generate_partition_syntax_for_frm(THD *thd, partition_info *part_info, Sql_mode_instant_remove sms(thd, MODE_ANSI_QUOTES); char *res= generate_partition_syntax(thd, part_info, buf_length, true, create_info, alter_info); + DBUG_EXECUTE_IF("generate_partition_syntax_for_frm", + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_YES, + ErrConvString(res, (uint32) *buf_length, + system_charset_info).ptr());); return res; } diff --git a/sql/sql_partition.h b/sql/sql_partition.h index ea197a6fc2c..8732aacbbd7 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -98,12 +98,6 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index, const key_range *key_spec, part_id_range *part_spec); uint get_partition_field_store_length(Field *field); -int get_cs_converted_part_value_from_string(THD *thd, - Item *item, - String *input_str, - String *output_str, - CHARSET_INFO *cs, - bool use_hex); void get_full_part_id_from_key(const TABLE *table, uchar *buf, KEY *key_info, const key_range *key_spec, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6552d91df03..4b47f9683eb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -122,14 +122,6 @@ static const char *ha_choice_values[] = {"", "0", "1"}; static void store_key_options(THD *, String *, TABLE *, KEY *); -#ifdef WITH_PARTITION_STORAGE_ENGINE -static void get_cs_converted_string_value(THD *thd, - String *input_str, - String *output_str, - CHARSET_INFO *cs, - bool use_hex); -#endif - static int show_create_view(THD *thd, TABLE_LIST *table, String *buff); static int show_create_sequence(THD *thd, TABLE_LIST *table_list, String *packet); @@ -7124,56 +7116,6 @@ static void collect_partition_expr(THD *thd, List<const char> &field_list, return; } - -/* - Convert a string in a given character set to a string which can be - used for FRM file storage in which case use_hex is TRUE and we store - the character constants as hex strings in the character set encoding - their field have. In the case of SHOW CREATE TABLE and the - PARTITIONS information schema table we instead provide utf8 strings - to the user and convert to the utf8 character set. - - SYNOPSIS - get_cs_converted_part_value_from_string() - item Item from which constant comes - input_str String as provided by val_str after - conversion to character set - output_str Out value: The string created - cs Character set string is encoded in - NULL for INT_RESULT's here - use_hex TRUE => hex string created - FALSE => utf8 constant string created - - RETURN VALUES - TRUE Error - FALSE Ok -*/ - -int get_cs_converted_part_value_from_string(THD *thd, - Item *item, - String *input_str, - String *output_str, - CHARSET_INFO *cs, - bool use_hex) -{ - if (item->result_type() == INT_RESULT) - { - longlong value= item->val_int(); - output_str->set(value, system_charset_info); - return FALSE; - } - if (!input_str) - { - my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0)); - return TRUE; - } - get_cs_converted_string_value(thd, - input_str, - output_str, - cs, - use_hex); - return FALSE; -} #endif @@ -7265,24 +7207,14 @@ static int get_partition_column_description(THD *thd, partition_info *part_info, tmp_str.append("NULL"); else { - char buffer[MAX_KEY_LENGTH]; - String str(buffer, sizeof(buffer), &my_charset_bin); - String val_conv; Item *item= col_val->item_expression; - - if (!(item= part_info->get_column_item(item, - part_info->part_field_array[i]))) - { - DBUG_RETURN(1); - } - String *res= item->val_str(&str); - if (get_cs_converted_part_value_from_string(thd, item, res, &val_conv, - part_info->part_field_array[i]->charset(), - FALSE)) - { - DBUG_RETURN(1); - } - tmp_str.append(val_conv); + StringBuffer<MAX_KEY_LENGTH> val; + const Field *field= part_info->part_field_array[i]; + const Type_handler *th= field->type_handler(); + th->partition_field_append_value(&val, item, + field->charset(), + PARTITION_VALUE_PRINT_MODE_SHOW); + tmp_str.append(val); } if (i != num_elements - 1) tmp_str.append(","); @@ -9964,99 +9896,6 @@ void initialize_information_schema_acl() &is_internal_schema_access); } -#ifdef WITH_PARTITION_STORAGE_ENGINE -/* - Convert a string in character set in column character set format - to utf8 character set if possible, the utf8 character set string - will later possibly be converted to character set used by client. - Thus we attempt conversion from column character set to both - utf8 and to character set client. - - Examples of strings that should fail conversion to utf8 are unassigned - characters as e.g. 0x81 in cp1250 (Windows character set for for countries - like Czech and Poland). Example of string that should fail conversion to - character set on client (e.g. if this is latin1) is 0x2020 (daggger) in - ucs2. - - If the conversion fails we will as a fall back convert the string to - hex encoded format. The caller of the function can also ask for hex - encoded format of output string unconditionally. - - SYNOPSIS - get_cs_converted_string_value() - thd Thread object - input_str Input string in cs character set - output_str Output string to be produced in utf8 - cs Character set of input string - use_hex Use hex string unconditionally - - - RETURN VALUES - No return value -*/ - -static void get_cs_converted_string_value(THD *thd, - String *input_str, - String *output_str, - CHARSET_INFO *cs, - bool use_hex) -{ - - output_str->length(0); - if (input_str->length() == 0) - { - output_str->append("''"); - return; - } - if (!use_hex) - { - String try_val; - uint try_conv_error= 0; - - try_val.copy(input_str->ptr(), input_str->length(), cs, - thd->variables.character_set_client, &try_conv_error); - if (likely(!try_conv_error)) - { - String val; - uint conv_error= 0; - - val.copy(input_str->ptr(), input_str->length(), cs, - system_charset_info, &conv_error); - if (likely(!conv_error)) - { - append_unescaped(output_str, val.ptr(), val.length()); - return; - } - } - /* We had a conversion error, use hex encoded string for safety */ - } - { - const uchar *ptr; - uint i, len; - char buf[3]; - - output_str->append("_"); - output_str->append(cs->csname); - output_str->append(" "); - output_str->append("0x"); - len= input_str->length(); - ptr= (uchar*)input_str->ptr(); - for (i= 0; i < len; i++) - { - uint high, low; - - high= (*ptr) >> 4; - low= (*ptr) & 0x0F; - buf[0]= _dig_vec_upper[high]; - buf[1]= _dig_vec_upper[low]; - buf[2]= 0; - output_str->append((const char*)buf); - ptr++; - } - } - return; -} -#endif /** Dumps a text description of a thread, its security context diff --git a/sql/sql_string.h b/sql/sql_string.h index deff81f3333..8ced35657e8 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -840,6 +840,15 @@ public: bool copy_aligned(const char *s, size_t arg_length, size_t offset, CHARSET_INFO *cs); bool set_or_copy_aligned(const char *s, size_t arg_length, CHARSET_INFO *cs); + bool can_be_safely_converted_to(CHARSET_INFO *tocs) const + { + if (charset() == &my_charset_bin) + return Well_formed_prefix(tocs, ptr(), length()).length() == length(); + String try_val; + uint try_conv_error= 0; + try_val.copy(ptr(), length(), charset(), tocs, &try_conv_error); + return try_conv_error == 0; + } bool copy(const char*s, size_t arg_length, CHARSET_INFO *csfrom, CHARSET_INFO *csto, uint *errors); bool copy(const String *str, CHARSET_INFO *tocs, uint *errors) @@ -874,6 +883,14 @@ public: { return Binary_string::append_hex((const char*)src, srclen); } + bool append_introducer_and_hex(CHARSET_INFO *cs, const LEX_CSTRING &str) + { + return + append(STRING_WITH_LEN("_")) || + append(cs->csname) || + append(STRING_WITH_LEN(" 0x")) || + append_hex(str.str, (uint32) str.length); + } bool append(IO_CACHE* file, uint32 arg_length) { return Binary_string::append(file, arg_length); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 390a1df9ea7..0fdebb51d8d 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -8916,6 +8916,145 @@ bool Type_handler::Column_definition_data_type_info_image(Binary_string *to, /***************************************************************************/ +void +Type_handler::partition_field_type_not_allowed(const LEX_CSTRING &field_name) +{ + my_error(ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD, MYF(0), + field_name.str); +} + + +bool +Type_handler::partition_field_check_result_type(Item *item, + Item_result expected_type) +{ + if (item->result_type() != expected_type) + { + my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0)); + return TRUE; + } + return false; +} + + +bool +Type_handler_blob_common::partition_field_check(const LEX_CSTRING &field_name, + Item *item_expr) const +{ + my_error(ER_BLOB_FIELD_IN_PART_FUNC_ERROR, MYF(0)); + return true; +} + + +bool +Type_handler_general_purpose_int::partition_field_append_value( + String *str, + Item *item_expr, + CHARSET_INFO *field_cs, + partition_value_print_mode_t mode) + const +{ + DBUG_ASSERT(item_expr->cmp_type() == INT_RESULT); + StringBuffer<21> tmp; + longlong value= item_expr->val_int(); + tmp.set(value, system_charset_info); + return str->append(tmp); +} + + +/* + Append an Item value to a String using a desired mode. + + @param [OUT] str The string to append the value to. + @param item_expr The item to get the value from + @param field_cs The character set of the value owner field. + @param mode The mode. + @retval true on error + @retval false on success + + The value is added using system_charset_info (no matter what mode is). + + (1) If mode is equal to PARTITION_VALUE_PRINT_MODE_FRM, + the value is appended as a pure ASCII string in the format '_latin1 0xdf', + i.e. a character set introducer followed by a hex hybrid. + + Before appending, we value is first converted to field_cs. + a) If the conversion succeeds, the value is printed in its field_cs + represenation. + b) If the conversion fails, the value is printed without conversion, + using the original character set introducer followed by the original + string hex representation. + In this case, open_table_from_share() will later notice that + the value cannot be actually stored to the field, and report + the error. So here we don't need to report errors such as + ER_PARTITION_FUNCTION_IS_NOT_ALLOWED. + + (2) If the mode is equal to PARTITION_VALUE_PRINT_SHOW, + then the value is needed for: + - SHOW CREATE TABLE, or + - the PARTITION_DESCRIPTION column in a + INFORMATION_SCHEMA.PARTITION query. + + The value generated here will be later sent to the client and + therefore will be converted to the client character set in the protocol. + + We try to generate the value as a simple quoted utf8 string without + introducers (e.g. 'utf8-string') when possible, to make it: + - as human readable as possible + - but still safe for mysqldump purposes. + + Simple quoted utf8 string is generated when these two conditions are true + at the same time: + a) The value can be safely converted to utf8, + so we can return it without data loss from this function. + b) The value can be safely converted to the client character set, + so we can convert it later without data loss to the client character + set in the protocol. + + If one of the conditions fail, the value is returned using + PARTITION_VALUE_PRINT_MODE_FRM representation. See (1). +*/ +bool Type_handler::partition_field_append_value( + String *str, + Item *item_expr, + CHARSET_INFO *field_cs, + partition_value_print_mode_t mode) + const +{ + DBUG_ASSERT(cmp_type() != INT_RESULT); + StringBuffer<MAX_KEY_LENGTH> buf; + String *res; + + if (!(res= item_expr->val_str(&buf))) + return str->append(STRING_WITH_LEN("NULL"), system_charset_info); + + if (!res->length()) + return str->append(STRING_WITH_LEN("''"), system_charset_info); + + if (mode == PARTITION_VALUE_PRINT_MODE_FRM || + !res->can_be_safely_converted_to(current_thd-> + variables.character_set_client) || + !res->can_be_safely_converted_to(system_charset_info)) + { + StringBuffer<64> buf2; + uint cnverr2= 0; + buf2.copy(res->ptr(), res->length(), res->charset(), field_cs, &cnverr2); + if (!cnverr2) + return str->append_introducer_and_hex(buf2.charset(), buf2.lex_cstring()); + return str->append_introducer_and_hex(res->charset(), res->lex_cstring()); + } + + StringBuffer<64> val(system_charset_info); + uint cnverr= 0; + val.copy(res->ptr(), res->length(), res->charset(), + system_charset_info, &cnverr); + append_unescaped(str, val.ptr(), val.length()); + return false; +} + + +/***************************************************************************/ + LEX_CSTRING Charset::collation_specific_name() const { /* |