diff --git a/mysql-test/main/item_types.result b/mysql-test/main/item_types.result new file mode 100644 index 00000000000..865b4f612ae --- /dev/null +++ b/mysql-test/main/item_types.result @@ -0,0 +1,16 @@ +# +# MDEV-34634 Types mismatch when cloning items causes debug assertion +# +CREATE TABLE t1 (a DATETIME); +SET optimizer_switch='derived_merge=off'; +SELECT * FROM (SELECT * FROM t1) AS t1 WHERE a=''; +a +Warnings: +Warning 1292 Truncated incorrect datetime value: '' +DROP TABLE t1; +CREATE TABLE t1 (c YEAR); +CREATE TABLE t2 (c INT); +SELECT * FROM t1 JOIN t2 ON t1.c=t2.c WHERE t1.c<=>5; +c c +DROP TABLE t1, t2; +SET optimizer_switch=default; diff --git a/mysql-test/main/item_types.test b/mysql-test/main/item_types.test new file mode 100644 index 00000000000..f43bfe1a8ac --- /dev/null +++ b/mysql-test/main/item_types.test @@ -0,0 +1,15 @@ +--echo # +--echo # MDEV-34634 Types mismatch when cloning items causes debug assertion +--echo # + +CREATE TABLE t1 (a DATETIME); +SET optimizer_switch='derived_merge=off'; +SELECT * FROM (SELECT * FROM t1) AS t1 WHERE a=''; +DROP TABLE t1; + +CREATE TABLE t1 (c YEAR); +CREATE TABLE t2 (c INT); +SELECT * FROM t1 JOIN t2 ON t1.c=t2.c WHERE t1.c<=>5; +DROP TABLE t1, t2; + +SET optimizer_switch=default; diff --git a/sql/item.cc b/sql/item.cc index 9ba00944c85..35d7eaefd01 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3847,7 +3847,7 @@ void Item_decimal::set_decimal_value(my_decimal *value_par) } -Item *Item_decimal::do_clone_const_item(THD *thd) const +Item *Item_decimal::clone_item(THD *thd) const { return new (thd->mem_root) Item_decimal(thd, name.str, &decimal_value, decimals, max_length); @@ -3868,7 +3868,7 @@ my_decimal *Item_float::val_decimal(my_decimal *decimal_value) } -Item *Item_float::do_clone_const_item(THD *thd) const +Item *Item_float::clone_item(THD *thd) const { return new (thd->mem_root) Item_float(thd, name.str, value, decimals, max_length); @@ -4032,7 +4032,7 @@ Item *Item_null::safe_charset_converter(THD *thd, CHARSET_INFO *tocs) return this; } -Item *Item_null::do_clone_const_item(THD *thd) const +Item *Item_null::clone_item(THD *thd) const { return new (thd->mem_root) Item_null(thd, name.str); } @@ -4873,7 +4873,7 @@ Item *Item_param::value_clone_item(THD *thd) const /* see comments in the header file */ Item * -Item_param::do_clone_const_item(THD *thd) const +Item_param::clone_item(THD *thd) const { // There's no "default". See comments in Item_param::save_in_field(). switch (state) { @@ -6953,7 +6953,7 @@ int Item_string::save_in_field(Field *field, bool no_conversions) } -Item *Item_string::do_clone_const_item(THD *thd) const +Item *Item_string::clone_item(THD *thd) const { LEX_CSTRING val; str_value.get_value(&val); @@ -7017,7 +7017,7 @@ int Item_int::save_in_field(Field *field, bool no_conversions) } -Item *Item_int::do_clone_const_item(THD *thd) const +Item *Item_int::clone_item(THD *thd) const { return new (thd->mem_root) Item_int(thd, name.str, value, max_length, unsigned_flag); } @@ -7046,7 +7046,7 @@ int Item_decimal::save_in_field(Field *field, bool no_conversions) } -Item *Item_int_with_ref::do_clone_const_item(THD *thd) const +Item *Item_int_with_ref::clone_item(THD *thd) const { DBUG_ASSERT(ref->const_item()); /* @@ -7142,7 +7142,7 @@ Item *Item_uint::neg(THD *thd) } -Item *Item_uint::do_clone_const_item(THD *thd) const +Item *Item_uint::clone_item(THD *thd) const { return new (thd->mem_root) Item_uint(thd, name.str, value, max_length); } @@ -7380,7 +7380,7 @@ void Item_date_literal::print(String *str, enum_query_type query_type) } -Item *Item_date_literal::do_clone_const_item(THD *thd) const +Item *Item_date_literal::clone_item(THD *thd) const { return new (thd->mem_root) Item_date_literal(thd, &cached_time); } @@ -7405,7 +7405,7 @@ void Item_datetime_literal::print(String *str, enum_query_type query_type) } -Item *Item_datetime_literal::do_clone_const_item(THD *thd) const +Item *Item_datetime_literal::clone_item(THD *thd) const { return new (thd->mem_root) Item_datetime_literal(thd, &cached_time, decimals); } @@ -7430,7 +7430,7 @@ void Item_time_literal::print(String *str, enum_query_type query_type) } -Item *Item_time_literal::do_clone_const_item(THD *thd) const +Item *Item_time_literal::clone_item(THD *thd) const { return new (thd->mem_root) Item_time_literal(thd, &cached_time, decimals); } @@ -10389,7 +10389,7 @@ void Item_cache_temporal::store_packed(longlong val_arg, Item *example_arg) } -Item *Item_cache_temporal::do_clone_const_item(THD *thd) const +Item *Item_cache_temporal::clone_item(THD *thd) const { Item_cache *tmp= type_handler()->Item_get_cache(thd, this); Item_cache_temporal *item= static_cast(tmp); diff --git a/sql/item.h b/sql/item.h index 19f95c5875f..b531647e8bf 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1698,21 +1698,17 @@ public: } /* - Clones the constant item + Clones the constant item (not necessary returning the same item type) Return value: - pointer to a clone of the Item - - nullptr if the item is not clonable */ - Item *clone_const_item(THD *thd) const - { - Item *clone= do_clone_const_item(thd); - if (clone) - { - // Make sure the clone is of same type as this item - DBUG_ASSERT(typeid(*clone) == typeid(*this)); - } - return clone; - } + - nullptr if the item is not clonable + + Note: the clone may have item type different from this + (i.e., instance of another basic constant class may be returned). + For real clones look at build_clone()/get_copy() methods + */ + virtual Item *clone_item(THD *thd) const { return nullptr; } virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const @@ -2588,12 +2584,6 @@ protected: deep copies (clones) of the item where possible */ virtual Item* do_build_clone(THD *thd) const = 0; - - /* - Service function for public method clone_const_item(). See comments for - clone_const_item() above - */ - virtual Item *do_clone_const_item(THD *thd) const { return nullptr; } }; MEM_ROOT *get_thd_memroot(THD *thd); @@ -3820,7 +3810,7 @@ public: const Type_handler *type_handler() const override { return &type_handler_null; } bool basic_const_item() const override { return true; } - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; bool const_is_null() const override { return true; } bool is_null() override { return true; } @@ -4270,7 +4260,7 @@ public: basic_const_item returned TRUE. */ Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override; - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; void set_param_type_and_swap_value(Item_param *from); Rewritable_query_parameter *get_rewritable_query_parameter() override @@ -4369,7 +4359,7 @@ public: String *val_str(String*) override; int save_in_field(Field *field, bool no_conversions) override; bool is_order_clause_position() const override { return true; } - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; void print(String *str, enum_query_type query_type) override; Item *neg(THD *thd) override; uint decimal_precision() const override @@ -4417,7 +4407,7 @@ public: Item_uint(THD *thd, ulonglong i): Item_int(thd, i, 10) {} Item_uint(THD *thd, const char *str_arg, longlong i, uint length); double val_real() override { return ulonglong2double((ulonglong)value); } - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; Item *neg(THD *thd) override; uint decimal_precision() const override { return max_length; } Item *do_get_copy(THD *thd) const override @@ -4468,7 +4458,7 @@ public: const my_decimal *const_ptr_my_decimal() const override { return &decimal_value; } int save_in_field(Field *field, bool no_conversions) override; - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; void print(String *str, enum_query_type query_type) override { decimal_value.to_string(&str_value); @@ -4521,7 +4511,7 @@ public: } String *val_str(String*) override; my_decimal *val_decimal(my_decimal *) override; - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; Item *neg(THD *thd) override; void print(String *str, enum_query_type query_type) override; Item *do_get_copy(THD *thd) const override @@ -4644,7 +4634,7 @@ public: int save_in_field(Field *field, bool no_conversions) override; const Type_handler *type_handler() const override { return &type_handler_varchar; } - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override { return const_charset_converter(thd, tocs, true); @@ -5067,7 +5057,7 @@ public: { return cached_time.get_mysql_time(); } - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; longlong val_int() override { return update_null() ? 0 : cached_time.to_longlong(); @@ -5117,7 +5107,7 @@ public: { return cached_time.get_mysql_time(); } - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; longlong val_int() override { return cached_time.to_longlong(); } double val_real() override { return cached_time.to_double(); } String *val_str(String *to) override @@ -5168,7 +5158,7 @@ public: { return cached_time.get_mysql_time(); } - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; longlong val_int() override { return update_null() ? 0 : cached_time.to_longlong(); @@ -5256,6 +5246,9 @@ public: cached_time.copy_to_mysql_time(ltime); return (null_value= false); } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } }; @@ -6299,8 +6292,11 @@ public: { return ref->save_in_field(field, no_conversions); } - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; Item *real_item() override { return ref; } + Item *do_get_copy(THD *thd) const override + { return get_item_copy(thd, this); } + Item *do_build_clone(THD *thd) const override { return get_copy(thd); } }; #ifdef MYSQL_SERVER @@ -7209,7 +7205,7 @@ public: is a constant and need not be optimized further. Important when storing packed datetime values. */ - Item *do_clone_const_item(THD *thd) const override; + Item *clone_item(THD *thd) const override; Item *convert_to_basic_const_item(THD *thd) override; virtual Item *make_literal(THD *) =0; }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 92f0a8fa578..b86ffed8619 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16632,7 +16632,7 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, if (can_change_cond_ref_to_const(func, right_item, left_item, field_value_owner, field, value)) { - Item *tmp=value->clone_const_item(thd); + Item *tmp=value->clone_item(thd); if (tmp) { tmp->collation.set(right_item->collation); @@ -16662,7 +16662,7 @@ change_cond_ref_to_const(THD *thd, I_List *save_list, else if (can_change_cond_ref_to_const(func, left_item, right_item, field_value_owner, field, value)) { - Item *tmp= value->clone_const_item(thd); + Item *tmp= value->clone_item(thd); if (tmp) { tmp->collation.set(left_item->collation);