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

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