summaryrefslogtreecommitdiff
path: root/sql/item_cmpfunc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r--sql/item_cmpfunc.cc80
1 files changed, 50 insertions, 30 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 66af96f671f..ab8acdd465f 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -145,7 +145,7 @@ void Item_func_not_all::print(String *str)
1 Item was replaced with an integer version of the item
*/
-static bool convert_constant_item(Field *field, Item **item)
+static bool convert_constant_item(THD *thd, Field *field, Item **item)
{
if ((*item)->const_item())
{
@@ -153,7 +153,7 @@ static bool convert_constant_item(Field *field, Item **item)
{
Item *tmp=new Item_int_with_ref(field->val_int(), *item);
if (tmp)
- *item=tmp;
+ thd->change_item_tree(item, tmp);
return 1; // Item was replaced
}
}
@@ -164,6 +164,7 @@ static bool convert_constant_item(Field *field, Item **item)
void Item_bool_func2::fix_length_and_dec()
{
max_length= 1; // Function returns 0 or 1
+ THD *thd= current_thd;
/*
As some compare functions are generated after sql_yacc,
@@ -188,17 +189,26 @@ void Item_bool_func2::fix_length_and_dec()
{
uint strong= 0;
uint weak= 0;
+ uint32 dummy_offset;
DTCollation coll;
if (args[0]->result_type() == STRING_RESULT &&
args[1]->result_type() == STRING_RESULT &&
- !my_charset_same(args[0]->collation.collation,
- args[1]->collation.collation) &&
+ String::needs_conversion(0, args[0]->collation.collation,
+ args[1]->collation.collation,
+ &dummy_offset) &&
!coll.set(args[0]->collation, args[1]->collation, TRUE))
{
Item* conv= 0;
+ Item_arena *arena= thd->current_arena, backup;
strong= coll.strong;
weak= strong ? 0 : 1;
+ /*
+ In case we're in statement prepare, create conversion item
+ in its memory: it will be reused on each execute.
+ */
+ if (arena->is_stmt_prepare())
+ thd->set_n_backup_item_arena(arena, &backup);
if (args[weak]->type() == STRING_ITEM)
{
String tmp, cstr;
@@ -211,26 +221,13 @@ void Item_bool_func2::fix_length_and_dec()
}
else
{
- THD *thd= current_thd;
- /*
- In case we're in prepared statement, create conversion
- item in its memory: it will be reused on each execute.
- (and don't juggle with mem_root's if it is ordinary statement).
- We come here only during first fix_fields() because after creating
- conversion item we will have arguments with compatible collations.
- */
- Item_arena *arena= thd->current_arena, backup;
- if (arena->is_conventional())
- arena= 0;
- else
- thd->set_n_backup_item_arena(arena, &backup);
conv= new Item_func_conv_charset(args[weak],
args[strong]->collation.collation);
- if (arena)
- thd->restore_backup_item_arena(arena, &backup);
conv->collation.set(args[weak]->collation.derivation);
conv->fix_fields(thd, 0, &conv);
}
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
if (args[weak]->type() == FIELD_ITEM)
((Item_field *)args[weak])->no_const_subst= 1;
args[weak]= conv ? conv : args[weak];
@@ -248,9 +245,9 @@ void Item_bool_func2::fix_length_and_dec()
if (args[0]->type() == FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
- if (field->store_for_compare())
+ if (field->can_be_compared_as_longlong())
{
- if (convert_constant_item(field,&args[1]))
+ if (convert_constant_item(thd, field,&args[1]))
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types.
@@ -261,9 +258,9 @@ void Item_bool_func2::fix_length_and_dec()
if (args[1]->type() == FIELD_ITEM /* && !args[1]->const_item() */)
{
Field *field=((Item_field*) args[1])->field;
- if (field->store_for_compare())
+ if (field->can_be_compared_as_longlong())
{
- if (convert_constant_item(field,&args[0]))
+ if (convert_constant_item(thd, field,&args[0]))
{
cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
INT_RESULT); // Works for all types.
@@ -841,6 +838,7 @@ longlong Item_func_interval::val_int()
void Item_func_between::fix_length_and_dec()
{
max_length= 1;
+ THD *thd= current_thd;
/*
As some compare functions are generated after sql_yacc,
@@ -861,11 +859,15 @@ void Item_func_between::fix_length_and_dec()
if (args[0]->type() == FIELD_ITEM)
{
Field *field=((Item_field*) args[0])->field;
- if (field->store_for_compare())
+ if (field->can_be_compared_as_longlong())
{
- if (convert_constant_item(field,&args[1]))
+ /*
+ The following can't be recoded with || as convert_constant_item
+ changes the argument
+ */
+ if (convert_constant_item(thd, field,&args[1]))
cmp_type=INT_RESULT; // Works for all types.
- if (convert_constant_item(field,&args[2]))
+ if (convert_constant_item(thd, field,&args[2]))
cmp_type=INT_RESULT; // Works for all types.
}
}
@@ -1167,6 +1169,15 @@ Item_func_nullif::val_str(String *str)
return res;
}
+
+bool
+Item_func_nullif::is_null()
+{
+ if (!cmp.compare())
+ return (null_value=1);
+ return 0;
+}
+
/*
CASE expression
Return the matching ITEM or NULL if all compares (including else) failed
@@ -1751,6 +1762,7 @@ void Item_func_in::fix_length_and_dec()
{
Item **arg, **arg_end;
uint const_itm= 1;
+ THD *thd= current_thd;
agg_cmp_type(&cmp_type, args, arg_count);
@@ -1788,6 +1800,9 @@ void Item_func_in::fix_length_and_dec()
Conversion is possible:
All IN arguments are constants.
*/
+ Item_arena *arena= thd->current_arena, backup;
+ if (arena->is_stmt_prepare())
+ thd->set_n_backup_item_arena(arena, &backup);
for (arg= args+1, arg_end= args+arg_count; arg < arg_end; arg++)
{
if (!my_charset_same(cmp_collation.collation,
@@ -1803,6 +1818,8 @@ void Item_func_in::fix_length_and_dec()
arg[0]= conv;
}
}
+ if (arena->is_stmt_prepare())
+ thd->restore_backup_item_arena(arena, &backup);
}
}
@@ -1830,7 +1847,7 @@ void Item_func_in::fix_length_and_dec()
DBUG_ASSERT(0);
return;
}
- if (array && !(current_thd->is_fatal_error)) // If not EOM
+ if (array && !(thd->is_fatal_error)) // If not EOM
{
uint j=0;
for (uint i=1 ; i < arg_count ; i++)
@@ -2048,7 +2065,8 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg)
}
-void Item_cond::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
+void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
+ List<Item> &fields)
{
List_iterator<Item> li(list);
Item *item;
@@ -2057,13 +2075,15 @@ void Item_cond::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
while ((item=li++))
{
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(ref_pointer_array, fields);
+ item->split_sum_func(thd, ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
+ Item **ref= li.ref();
uint el= fields.elements;
+ Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
fields.push_front(item);
ref_pointer_array[el]= item;
- li.replace(new Item_ref(ref_pointer_array + el, li.ref(), 0, item->name));
+ thd->change_item_tree(ref, new_item);
}
item->update_used_tables();
used_tables_cache|=item->used_tables();