diff options
Diffstat (limited to 'sql/item.cc')
-rw-r--r-- | sql/item.cc | 125 |
1 files changed, 112 insertions, 13 deletions
diff --git a/sql/item.cc b/sql/item.cc index a9e99c65580..11e9acb1e55 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1207,6 +1207,22 @@ bool Item_name_const::is_null() return value_item->is_null(); } + +Item_name_const::Item_name_const(Item *name_arg, Item *val): + value_item(val), name_item(name_arg) +{ + if (!(valid_args= name_item->basic_const_item() && + (value_item->basic_const_item() || + ((value_item->type() == FUNC_ITEM) && + (((Item_func *) value_item)->functype() == + Item_func::NEG_FUNC) && + (((Item_func *) value_item)->key_item()->type() != + FUNC_ITEM))))) + my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); + Item::maybe_null= TRUE; +} + + Item::Type Item_name_const::type() const { /* @@ -1218,8 +1234,17 @@ Item::Type Item_name_const::type() const if (item->type() == FIELD_ITEM) ((Item_field *) item)->... we return NULL_ITEM in the case to avoid wrong casting. + + valid_args guarantees value_item->basic_const_item(); if type is + FUNC_ITEM, then we have a fudged item_func_neg() on our hands + and return the underlying type. */ - return valid_args ? value_item->type() : NULL_ITEM; + return valid_args ? + (((value_item->type() == FUNC_ITEM) && + (((Item_func *) value_item)->functype() == Item_func::NEG_FUNC)) ? + ((Item_func *) value_item)->key_item()->type() : + value_item->type()) : + NULL_ITEM; } @@ -3912,6 +3937,18 @@ bool Item_field::fix_fields(THD *thd, Item **reference) else if (!from_field) goto error; + if (!outer_fixed && cached_table && cached_table->select_lex && + context->select_lex && + cached_table->select_lex != context->select_lex) + { + int ret; + if ((ret= fix_outer_field(thd, &from_field, reference)) < 0) + goto error; + else if (!ret) + return FALSE; + outer_fixed= 1; + } + /* if it is not expression from merged VIEW we will set this field. @@ -3927,18 +3964,6 @@ bool Item_field::fix_fields(THD *thd, Item **reference) if (from_field == view_ref_found) return FALSE; - if (!outer_fixed && cached_table && cached_table->select_lex && - context->select_lex && - cached_table->select_lex != context->select_lex) - { - int ret; - if ((ret= fix_outer_field(thd, &from_field, reference)) < 0) - goto error; - else if (!ret) - return FALSE; - outer_fixed= 1; - } - set_field(from_field); if (thd->lex->in_sum_func && thd->lex->in_sum_func->nest_level == @@ -4092,6 +4117,30 @@ bool Item_field::subst_argument_checker(byte **arg) } +/** + Convert a numeric value to a zero-filled string + + @param[in,out] item the item to operate on + @param field The field that this value is equated to + + This function converts a numeric value to a string. In this conversion + the zero-fill flag of the field is taken into account. + This is required so the resulting string value can be used instead of + the field reference when propagating equalities. +*/ + +static void convert_zerofill_number_to_string(Item **item, Field_num *field) +{ + char buff[MAX_FIELD_WIDTH],*pos; + String tmp(buff,sizeof(buff), field->charset()), *res; + + res= (*item)->val_str(&tmp); + field->prepend_zeros(res); + pos= (char *) sql_strmake (res->ptr(), res->length()); + *item= new Item_string(pos, res->length(), field->charset()); +} + + /* Set a pointer to the multiple equality the field reference belongs to (if any) @@ -4140,6 +4189,13 @@ Item *Item_field::equal_fields_propagator(byte *arg) if (!item || (cmp_context != (Item_result)-1 && item->cmp_context != cmp_context)) item= this; + else if (field && (field->flags & ZEROFILL_FLAG) && IS_NUM(field->type())) + { + if (item && cmp_context != INT_RESULT) + convert_zerofill_number_to_string(&item, (Field_num *)field); + else + item= this; + } return item; } @@ -4311,6 +4367,49 @@ String *Item::check_well_formed_result(String *str, bool send_error) return str; } +/* + Compare two items using a given collation + + SYNOPSIS + eq_by_collation() + item item to compare with + binary_cmp TRUE <-> compare as binaries + cs collation to use when comparing strings + + DESCRIPTION + This method works exactly as Item::eq if the collation cs coincides with + the collation of the compared objects. Otherwise, first the collations that + differ from cs are replaced for cs and then the items are compared by + Item::eq. After the comparison the original collations of items are + restored. + + RETURN + 1 compared items has been detected as equal + 0 otherwise +*/ + +bool Item::eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs) +{ + CHARSET_INFO *save_cs= 0; + CHARSET_INFO *save_item_cs= 0; + if (collation.collation != cs) + { + save_cs= collation.collation; + collation.collation= cs; + } + if (item->collation.collation != cs) + { + save_item_cs= item->collation.collation; + item->collation.collation= cs; + } + bool res= eq(item, binary_cmp); + if (save_cs) + collation.collation= save_cs; + if (save_item_cs) + item->collation.collation= save_item_cs; + return res; +} + /* Create a field to hold a string value from an item |