summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-10-18 08:07:40 +0400
committerAlexander Barkov <bar@mariadb.com>2019-10-18 10:15:17 +0400
commit9a833dc6881b896e65cf76c9699faa6c324e1775 (patch)
tree25b3daa904d7fb75a50c08d777ae3fce025684f2
parent9c9606152505792fcb8f4b7386e5b6a25e2790b4 (diff)
downloadmariadb-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.result88
-rw-r--r--mysql-test/main/partition_utf8-debug.test71
-rw-r--r--mysql-test/main/partition_utf8.result22
-rw-r--r--mysql-test/main/partition_utf8.test19
-rw-r--r--sql/sql_partition.cc88
-rw-r--r--sql/sql_partition.h6
-rw-r--r--sql/sql_show.cc175
-rw-r--r--sql/sql_string.h17
-rw-r--r--sql/sql_type.cc139
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
{
/*