mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +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:
113
sql/sql_type.cc
113
sql/sql_type.cc
@ -57,6 +57,7 @@ Type_handler_set type_handler_set;
|
||||
Type_handler_string type_handler_string;
|
||||
Type_handler_var_string type_handler_var_string;
|
||||
Type_handler_varchar type_handler_varchar;
|
||||
Type_handler_hex_hybrid type_handler_hex_hybrid;
|
||||
static Type_handler_varchar_compressed type_handler_varchar_compressed;
|
||||
|
||||
Type_handler_tiny_blob type_handler_tiny_blob;
|
||||
@ -91,6 +92,9 @@ bool Type_handler_data::init()
|
||||
m_type_aggregator_for_result.add(&type_handler_geometry,
|
||||
&type_handler_geometry,
|
||||
&type_handler_geometry) ||
|
||||
m_type_aggregator_for_result.add(&type_handler_geometry,
|
||||
&type_handler_hex_hybrid,
|
||||
&type_handler_long_blob) ||
|
||||
m_type_aggregator_for_result.add(&type_handler_geometry,
|
||||
&type_handler_tiny_blob,
|
||||
&type_handler_long_blob) ||
|
||||
@ -434,6 +438,7 @@ const Name
|
||||
Type_handler_string::m_name_char(STRING_WITH_LEN("char")),
|
||||
Type_handler_var_string::m_name_var_string(STRING_WITH_LEN("varchar")),
|
||||
Type_handler_varchar::m_name_varchar(STRING_WITH_LEN("varchar")),
|
||||
Type_handler_hex_hybrid::m_name_hex_hybrid(STRING_WITH_LEN("hex_hybrid")),
|
||||
Type_handler_tiny_blob::m_name_tinyblob(STRING_WITH_LEN("tinyblob")),
|
||||
Type_handler_medium_blob::m_name_mediumblob(STRING_WITH_LEN("mediumblob")),
|
||||
Type_handler_long_blob::m_name_longblob(STRING_WITH_LEN("longblob")),
|
||||
@ -6357,64 +6362,92 @@ bool Type_handler_general_purpose_string::
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
bool Type_handler_null::Item_basic_value_eq(const Item_basic_value *a,
|
||||
const Item_basic_value *b)
|
||||
const
|
||||
bool Type_handler_null::Item_const_eq(const Item_const *a,
|
||||
const Item_const *b,
|
||||
bool binary_cmp) const
|
||||
{
|
||||
return a->basic_const_item() &&
|
||||
b->basic_const_item();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler_real_result::Item_basic_value_eq(const Item_basic_value *a,
|
||||
const Item_basic_value *b)
|
||||
const
|
||||
bool Type_handler_real_result::Item_const_eq(const Item_const *a,
|
||||
const Item_const *b,
|
||||
bool binary_cmp) const
|
||||
{
|
||||
return a->basic_const_item() &&
|
||||
b->basic_const_item() &&
|
||||
const_cast<Item_basic_value*>(a)->val_real() ==
|
||||
const_cast<Item_basic_value*>(b)->val_real();
|
||||
const double *va= a->const_ptr_double();
|
||||
const double *vb= b->const_ptr_double();
|
||||
return va[0] == vb[0];
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler_int_result::Item_basic_value_eq(const Item_basic_value *a,
|
||||
const Item_basic_value *b)
|
||||
const
|
||||
bool Type_handler_int_result::Item_const_eq(const Item_const *a,
|
||||
const Item_const *b,
|
||||
bool binary_cmp) const
|
||||
{
|
||||
longlong value;
|
||||
return a->basic_const_item() &&
|
||||
b->basic_const_item() &&
|
||||
(value= const_cast<Item_basic_value*>(a)->val_int()) ==
|
||||
const_cast<Item_basic_value*>(b)->val_int() &&
|
||||
(value >= 0 || a->unsigned_flag == b->unsigned_flag);
|
||||
const longlong *va= a->const_ptr_longlong();
|
||||
const longlong *vb= b->const_ptr_longlong();
|
||||
bool res= va[0] == vb[0] &&
|
||||
(va[0] >= 0 ||
|
||||
(a->get_type_all_attributes_from_const()->unsigned_flag ==
|
||||
b->get_type_all_attributes_from_const()->unsigned_flag));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler_string_result::Item_basic_value_eq(const Item_basic_value *a,
|
||||
const Item_basic_value *b)
|
||||
const
|
||||
bool Type_handler_string_result::Item_const_eq(const Item_const *a,
|
||||
const Item_const *b,
|
||||
bool binary_cmp) const
|
||||
{
|
||||
if (!a->basic_const_item() ||
|
||||
!b->basic_const_item() ||
|
||||
a->collation.collation != b->collation.collation)
|
||||
return false;
|
||||
String *sa= const_cast<Item_basic_value*>(a)->val_str(NULL);
|
||||
String *sb= const_cast<Item_basic_value*>(b)->val_str(NULL);
|
||||
return sa->eq(sb, a->collation.collation);
|
||||
const String *sa= a->const_ptr_string();
|
||||
const String *sb= b->const_ptr_string();
|
||||
return binary_cmp ? sa->bin_eq(sb) :
|
||||
a->get_type_all_attributes_from_const()->collation.collation ==
|
||||
b->get_type_all_attributes_from_const()->collation.collation &&
|
||||
sa->eq(sb, a->get_type_all_attributes_from_const()->collation.collation);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Type_handler_string_result::Item_basic_value_bin_eq(const Item_basic_value *a,
|
||||
const Item_basic_value *b)
|
||||
const
|
||||
Type_handler_decimal_result::Item_const_eq(const Item_const *a,
|
||||
const Item_const *b,
|
||||
bool binary_cmp) const
|
||||
{
|
||||
if (!a->basic_const_item() ||
|
||||
!b->basic_const_item())
|
||||
return false;
|
||||
String *sa= const_cast<Item_basic_value*>(a)->val_str(NULL);
|
||||
String *sb= const_cast<Item_basic_value*>(b)->val_str(NULL);
|
||||
return sa->bin_eq(sb);
|
||||
const my_decimal *da= a->const_ptr_my_decimal();
|
||||
const my_decimal *db= b->const_ptr_my_decimal();
|
||||
return !my_decimal_cmp(da, db) &&
|
||||
(!binary_cmp ||
|
||||
a->get_type_all_attributes_from_const()->decimals ==
|
||||
b->get_type_all_attributes_from_const()->decimals);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Type_handler_temporal_result::Item_const_eq(const Item_const *a,
|
||||
const Item_const *b,
|
||||
bool binary_cmp) const
|
||||
{
|
||||
const MYSQL_TIME *ta= a->const_ptr_mysql_time();
|
||||
const MYSQL_TIME *tb= b->const_ptr_mysql_time();
|
||||
return !my_time_compare(ta, tb) &&
|
||||
(!binary_cmp ||
|
||||
a->get_type_all_attributes_from_const()->decimals ==
|
||||
b->get_type_all_attributes_from_const()->decimals);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
const Type_handler *
|
||||
Type_handler_hex_hybrid::cast_to_int_type_handler() const
|
||||
{
|
||||
return &type_handler_longlong;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *
|
||||
Type_handler_hex_hybrid::type_handler_for_system_time() const
|
||||
{
|
||||
return &type_handler_longlong;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************/
|
||||
|
Reference in New Issue
Block a user