summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc125
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