1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03: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:
Alexander Barkov
2019-10-18 08:07:40 +04:00
parent 9c96061525
commit 9a833dc688
9 changed files with 368 additions and 257 deletions

View File

@ -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