diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2011-07-11 23:48:35 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2011-07-11 23:48:35 +0400 |
commit | 2c28412e2e6b8ca9a88b5e3c100393ebeedd46ca (patch) | |
tree | 4a492dd79f1e42ad8e46addc11f5e15408e4ba2a /sql/item_cmpfunc.cc | |
parent | 62cc4df4d36f027e0790a9a34720f0fa094c201b (diff) | |
download | mariadb-git-2c28412e2e6b8ca9a88b5e3c100393ebeedd46ca.tar.gz |
Port of code for: (part of testcase is in mysql-test/t/subquery*.test and will be ported separately)
Bug#11766642: crash in Item_field::register_field_in_read_map
with view
(Former 59793)
Prior to the refactoring in this patch, Item_cond_xor behaved
partially as an Item_cond and partially as an Item_func. The
reasoning behind this was that XOR is currently not optimized
(thus should be Item_func instead of Item_cond), but it was
planned optimize it in the future (thus, made Item_cond anyway
to ease optimization later).
Even though Item_cond inherits from Item_func, there are
differences between these two. One difference is that the
arguments are stored differently. Item_cond stores them in a
list while Item_func store them in an args[].
BUG no 45221 was caused by Item_cond_xor storing arguments in
the list while users of the objects would look for them in
args[]. The fix back then was to store the arguments in both
locations.
In this bug, Item_cond_xor initially gets two Item_field
arguments. These are stored in the list inherited from
Item_cond and in args[] inherited from Item_func. During
resolution, find_field_in_view() replaces the Item_fields
stored in the list with Item_direct_view_refs, but args[]
still points to the unresolved Item_fields. This shows that
the fix for 45221 was incorrect.
The refactoring performed in this patch removes the confusion
by making the XOR item an Item_func period. A neg_transformer()
is also implemented for Item_func_xor to improve performance
when negating XOR expressions. An XOR is negated by negating
one of the operands.
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 346ae243196..74a63337e49 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5065,23 +5065,21 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const very fast to use. */ -longlong Item_cond_xor::val_int() +longlong Item_func_xor::val_int() { DBUG_ASSERT(fixed == 1); - List_iterator<Item> li(list); - Item *item; - int result=0; - null_value=0; - while ((item=li++)) + int result= 0; + null_value= false; + for (uint i= 0; i < arg_count; i++) { - result^= (item->val_int() != 0); - if (item->null_value) + result^= (args[i]->val_int() != 0); + if (args[i]->null_value) { - null_value=1; + null_value= true; return 0; } } - return (longlong) result; + return result; } /** @@ -5122,6 +5120,33 @@ Item *Item_bool_rowready_func2::neg_transformer(THD *thd) return item; } +/** + XOR can be negated by negating one of the operands: + + NOT (a XOR b) => (NOT a) XOR b + => a XOR (NOT b) + + @param thd Thread handle + @return New negated item +*/ +Item *Item_func_xor::neg_transformer(THD *thd) +{ + Item *neg_operand; + Item_func_xor *new_item; + if ((neg_operand= args[0]->neg_transformer(thd))) + // args[0] has neg_tranformer + new_item= new(thd->mem_root) Item_func_xor(neg_operand, args[1]); + else if ((neg_operand= args[1]->neg_transformer(thd))) + // args[1] has neg_tranformer + new_item= new(thd->mem_root) Item_func_xor(args[0], neg_operand); + else + { + neg_operand= new(thd->mem_root) Item_func_not(args[0]); + new_item= new(thd->mem_root) Item_func_xor(neg_operand, args[1]); + } + return new_item; +} + /** a IS NULL -> a IS NOT NULL. |