1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-11361 Equal condition propagation does not work for DECIMAL and temporal dynamic SQL parameters

MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
A cleanup for MDEV-14630: fixing a crash in Item_decimal::eq().

Problems:
- old implementations of Item_decimal::eq() and
  Item_temporal_literal::eq() were not symmetric
  with Item_param::eq(), this caused MDEV-11361.

- old implementations for DECIMAL and temporal data types
  did not take into account that in case when eq() is called
  with binary_cmp==true, {{eq()}} should check not only equality
  of the two values, but also equality if their decimal precision.
  This cuases MDEV-16426.

- Item_decimal::eq() crashes with "item" pointing
  to a non-DECIMAL value. Before MDEV-14630
  non-DECIMAL values were filtered out by the test:
    type() == item->type()
  as literals of different types had different type().
  After MDEV-14630 type() for literals of all data types return CONST_ITEM.
  This caused failures in tests:
    ./mtr engines/iuds.insert_number
    ./mtr --ps --embedded main.explain_slowquerylog
  (revealed by buildbot)

The essence of the fix:
Making literals and Item_param reuse the same code to avoid
asymmetries between Item_param::eq(Item_literal) and
Item_literal::eq(Item_param), now and in the future, and to
avoid code duplication between Item_literal and Item_param.
Adding tests for "decimals" for DECIMAL and temporal data types,
to treat constants of different scale as not equal when "binary_cmp"
is "true".

Details:
1. Adding a helper class Item_const to extract constant values from Items easier
2. Deriving Item_basic_value from Item_const
3. Joining Type_handler::Item_basic_value_eq() and Item_basic_value_bin_eq()
   into a single method with an extra "binary_cmp" argument
   (it looks simple this way) and renaming the new method to Item_const_eq().
   Modifying its implementations to operate with
   Item_const instead of Item_basic_value.
4. Adding a new class Type_handler_hex_hybrid,
   to handle hex constants like 0x616263.
5. Removing Item::VARBIN_ITEM and fixing Item_hex_constant to
   use type_handler_hex_hybrid instead of type_handler_varchar.
   Item_hex_hybrid::type() now returns CONST_ITEM, like all
   other literals do.
6. Move virtual methods Item::type_handler_for_system_time() and
   Item::cast_to_int_type_handler() from Item to Type_handler.
7. Removing Item_decimal::eq() and Item_temporal_literal::eq().
   These classes are now handled by the generic Item_basic_value::eq().
8. Implementing Type_handler_temporal_result::Item_const_eq()
   and Type_handler_decimal_result::Item_const_eq(),
   this fixes MDEV-11361.
9. Adding tests for "decimals" into
   Type_handler_decimal_result::Item_const_eq() and
   Type_handler_temporal_result::Item_const_eq()
   in case if "binary_cmp" is true.
   This fixes MDEV-16426.
10. Moving Item_cache out of Item_basic_value.
   They share nothing. It simplifies implementation
   of Item_basic_value::eq(). Deriving Item_cache
   directly from Item.

11. Adding class DbugStringItemTypeValue, which
    used Item::print() internally, and using
    in instead of the old debug printing code.
    This gives nicer output in func_debug.result.

Changes N5 and N6 do not directly relate to the bugs fixed,
but make the code fully symmetric across all literal types.
Without a new handler Type_handler_hex_hybrid we'd have
to keep two code branches (for regular literals and for
hex hybrid literals).
This commit is contained in:
Alexander Barkov
2018-06-08 12:36:42 +04:00
parent 054412598b
commit 9043dd7a2d
23 changed files with 1126 additions and 182 deletions

View File

@ -30,7 +30,7 @@ class Field;
class Column_definition;
class Column_definition_attributes;
class Item;
class Item_basic_value;
class Item_const;
class Item_param;
class Item_cache;
class Item_func_or_sum;
@ -1168,6 +1168,10 @@ public:
{
return this;
}
virtual const Type_handler *type_handler_for_system_time() const
{
return this;
}
virtual CHARSET_INFO *charset_for_protocol(const Item *item) const;
virtual const Type_handler*
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
@ -1391,16 +1395,11 @@ public:
return NULL;
}
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const
virtual bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const
{
return false;
}
virtual bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const
{
return Item_basic_value_eq(a, b);
}
virtual bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
@ -1877,8 +1876,8 @@ public:
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_param_set_from_value(THD *thd,
@ -1956,6 +1955,8 @@ public:
uint32 max_display_length(const Item *item) const;
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
void Item_param_set_param_func(Item_param *param,
@ -2158,8 +2159,8 @@ public:
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_param_set_from_value(THD *thd,
@ -2239,6 +2240,8 @@ public:
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
bool Item_param_set_from_value(THD *thd,
Item_param *param,
const Type_all_attributes *attr,
@ -2323,10 +2326,8 @@ public:
const Schema_specification_st *schema)
const;
uint32 max_display_length(const Item *item) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
uint Item_time_precision(Item *item) const
{
return Item_temporal_precision(item, true);
@ -3315,13 +3316,8 @@ public:
const Type_handler *type_handler_for_union(const Item *) const;
uint32 max_display_length(const Item *item) const { return 0; }
uint32 calc_pack_length(uint32 length) const { return 0; }
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const
{
return Type_handler_null::Item_basic_value_eq(a, b);
}
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
@ -3468,6 +3464,17 @@ public:
};
class Type_handler_hex_hybrid: public Type_handler_varchar
{
static const Name m_name_hex_hybrid;
public:
virtual ~Type_handler_hex_hybrid() {}
const Name name() const { return m_name_hex_hybrid; }
const Type_handler *cast_to_int_type_handler() const;
const Type_handler *type_handler_for_system_time() const;
};
class Type_handler_varchar_compressed: public Type_handler_varchar
{
public:
@ -3871,6 +3878,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_set type_handler_set;
extern MYSQL_PLUGIN_IMPORT Type_handler_string type_handler_string;
extern MYSQL_PLUGIN_IMPORT Type_handler_var_string type_handler_var_string;
extern MYSQL_PLUGIN_IMPORT Type_handler_varchar type_handler_varchar;
extern MYSQL_PLUGIN_IMPORT Type_handler_hex_hybrid type_handler_hex_hybrid;
extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob;
extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob;