mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
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.
This commit is contained in:
parent
9c96061525
commit
9a833dc688
9 changed files with 368 additions and 257 deletions
88
mysql-test/main/partition_utf8-debug.result
Normal file
88
mysql-test/main/partition_utf8-debug.result
Normal file
|
@ -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
|
||||
#
|
71
mysql-test/main/partition_utf8-debug.test
Normal file
71
mysql-test/main/partition_utf8-debug.test
Normal file
|
@ -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 #
|
|
@ -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,
|
||||
|
|
175
sql/sql_show.cc
175
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
|
||||
|
|
|
@ -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);
|
||||
|
|
139
sql/sql_type.cc
139
sql/sql_type.cc
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue