diff options
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 80 |
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(); |