diff options
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/sql/item.cc b/sql/item.cc index 823b8470f4a..7d7bced4872 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -422,7 +422,6 @@ Item::Item(THD *thd): maybe_null=null_value=with_sum_func=with_field=0; in_rollup= 0; with_subselect= 0; - cmp_context= IMPOSSIBLE_RESULT; /* Initially this item is not attached to any JOIN_TAB. */ join_tab_idx= MAX_TABLES; @@ -468,8 +467,7 @@ Item::Item(THD *thd, Item *item): with_field(item->with_field), fixed(item->fixed), is_autogenerated_name(item->is_autogenerated_name), - with_subselect(item->has_subquery()), - cmp_context(item->cmp_context) + with_subselect(item->has_subquery()) { next= thd->free_list; // Put in free list thd->free_list= this; @@ -5371,7 +5369,7 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) bool Item_field::can_be_substituted_to_equal_item(const Context &ctx, const Item_equal *item_equal) { - if (cmp_context == STRING_RESULT && + if (ctx.compare_type() == STRING_RESULT && ctx.compare_collation() != item_equal->compare_collation()) return false; return ctx.subst_constraint() == ANY_SUBST || @@ -5440,31 +5438,33 @@ Item *Item_field::propagate_equal_fields(THD *thd, { if (no_const_subst) return this; - item_equal= find_item_equal((COND_EQUAL *) arg); + item_equal= find_item_equal(arg); Item *item= 0; if (item_equal) { - if (!can_be_substituted_to_equal_item(ctx, item_equal)) + /* + Disable const propagation for items used in different comparison contexts. + This must be done because, for example, Item_hex_string->val_int() is not + the same as (Item_hex_string->val_str() in BINARY column)->val_int(). + We cannot simply disable the replacement in a particular context ( + e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>) since + Items don't know the context they are in and there are functions like + IF (<hex_string>, 'yes', 'no'). + */ + if (!can_be_substituted_to_equal_item(ctx, item_equal) || + !ctx.has_compatible_context(item_equal->compare_type())) { item_equal= NULL; return this; } item= item_equal->get_const(); } - /* - Disable const propagation for items used in different comparison contexts. - This must be done because, for example, Item_hex_string->val_int() is not - the same as (Item_hex_string->val_str() in BINARY column)->val_int(). - We cannot simply disable the replacement in a particular context ( - e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>) since - Items don't know the context they are in and there are functions like - IF (<hex_string>, 'yes', 'no'). - */ - if (!item || !has_compatible_context(item)) + if (!item) item= this; else if (field && (field->flags & ZEROFILL_FLAG) && IS_NUM(field->type())) { - if (item && (cmp_context == STRING_RESULT || cmp_context == IMPOSSIBLE_RESULT)) + DBUG_ASSERT(ctx.compare_type() != STRING_RESULT); + if (item && (ctx.subst_constraint() == IDENTITY_SUBST)) convert_zerofill_number_to_string(thd, &item, (Field_num *)field); else item= this; @@ -5521,8 +5521,19 @@ Item *Item_field::replace_equal_field(THD *thd, uchar *arg) Item *const_item2= item_equal->get_const(); if (const_item2) { - if (!has_compatible_context(const_item2)) - return this; + /* + Currently we don't allow to create Item_equal with compare_type() + different from its Item_field's cmp_type(). + Field_xxx::test_if_equality_guarantees_uniqueness() prevent this. + Also, Item_field::propagate_equal_fields() does not allow to assign + this->item_equal to any instances of Item_equal if "this" is used + in a non-native comparison context, or with an incompatible collation. + So the fact that we have (item_equal != NULL) means that the currently + processed function (the owner of "this") uses the field in its native + comparison context, and it's safe to replace it to the constant from + item_equal. + */ + DBUG_ASSERT(cmp_type() == item_equal->compare_type()); return const_item2; } Item_field *subst= |