Commit 9a833dc6 authored by Alexander Barkov's avatar Alexander Barkov

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.
parent 9c960615
#
# 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
#
--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 #
......@@ -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
#
......@@ -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 #
......@@ -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;
}
......
......@@ -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,
......
......@@ -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
......
......@@ -840,6 +840,15 @@ class String: public Charset, public Binary_string
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 @@ class String: public Charset, public Binary_string
{
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);
......
......@@ -8914,6 +8914,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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment