From: Jorgen Loland Date: February 21 2011 10:24am Subject: bzr commit into mysql-trunk branch (jorgen.loland:3685) Bug#11766642 List-Archive: http://lists.mysql.com/commits/131726 X-Bug: 11766642 Message-Id: <20110221102442.AD6294AD@atum21.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============4467625285775773548==" --===============4467625285775773548== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/home/jl208045/mysql/mysql-trunk-59793/ based on revid:sergey.vojtovich@stripped 3685 Jorgen Loland 2011-02-21 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. @ mysql-test/include/subquery_sj.inc Add test for BUG#11766642 @ mysql-test/r/subquery_sj_none.result Add test for BUG#11766642 @ mysql-test/t/negation_elimination.test Add tests for XOR @ sql/item_cmpfunc.cc Refactor XOR item: it is now a pure Item_func, inheriting from Item_bool_func2 instead of Item_cond. Also added neg_transformer() function to improve performance when XOR is negated. @ sql/item_cmpfunc.h Refactor XOR item: it is now a pure Item_func, inheriting from Item_bool_func2 instead of Item_cond. Also added neg_transformer() function to improve performance when XOR is negated. @ sql/item_func.h Refactor XOR item: it is now a pure Item_func, inheriting from Item_bool_func2 instead of Item_cond @ sql/sql_yacc.yy Refactor XOR item: it is now a pure Item_func, inheriting from Item_bool_func2 instead of Item_cond @ unittest/gunit/item-t.cc Add unit test for Item_func_xor modified: mysql-test/include/subquery_sj.inc mysql-test/r/subquery_sj_none.result mysql-test/t/negation_elimination.test sql/item_cmpfunc.cc sql/item_cmpfunc.h sql/item_func.h sql/sql_yacc.yy unittest/gunit/item-t.cc === modified file 'mysql-test/include/subquery_sj.inc' --- a/mysql-test/include/subquery_sj.inc 2011-01-27 11:38:22 +0000 +++ b/mysql-test/include/subquery_sj.inc 2011-02-21 10:24:39 +0000 @@ -3504,3 +3504,19 @@ deallocate prepare s; DROP TABLE ot1, ot2, ot3, it1; --echo # End of the test for bug#57623. + +--echo # +--echo # Bug#11766642: crash in Item_field::register_field_in_read_map with view +--echo # + +CREATE TABLE t1(a INT); +CREATE VIEW v1 AS SELECT a FROM t1; + +INSERT INTO t1 VALUES (0),(1),(2); + +SELECT a FROM t1 WHERE a IN + (SELECT a XOR a FROM v1) +ORDER BY a; + +DROP TABLE t1; +DROP VIEW v1; === modified file 'mysql-test/r/subquery_sj_none.result' --- a/mysql-test/r/subquery_sj_none.result 2011-02-14 11:21:26 +0000 +++ b/mysql-test/r/subquery_sj_none.result 2011-02-21 10:24:39 +0000 @@ -5538,4 +5538,17 @@ a a a deallocate prepare s; DROP TABLE ot1, ot2, ot3, it1; # End of the test for bug#57623. +# +# Bug#11766642: crash in Item_field::register_field_in_read_map with view +# +CREATE TABLE t1(a INT); +CREATE VIEW v1 AS SELECT a FROM t1; +INSERT INTO t1 VALUES (0),(1),(2); +SELECT a FROM t1 WHERE a IN +(SELECT a XOR a FROM v1) +ORDER BY a; +a +0 +DROP TABLE t1; +DROP VIEW v1; set optimizer_switch=default; === modified file 'mysql-test/t/negation_elimination.test' --- a/mysql-test/t/negation_elimination.test 2005-07-28 00:22:47 +0000 +++ b/mysql-test/t/negation_elimination.test 2011-02-21 10:24:39 +0000 @@ -65,6 +65,35 @@ select * from t1 where not((a < 5 and a explain select * from t1 where ((a between 5 and 15) and (not(a like 10))); select * from t1 where ((a between 5 and 15) and (not(a like 10))); +--echo # XOR (Note: XOR is negated by negating one of the operands) + +--echo # Should return 6,7 +SELECT * FROM t1 WHERE ((a > 5) XOR (a > 7)); + +--echo # Should return 0..5,8..19 +SELECT * FROM t1 WHERE ((NOT (a > 5)) XOR (a > 7)); +SELECT * FROM t1 WHERE ((a > 5) XOR (NOT (a > 7))); +SELECT * FROM t1 WHERE NOT ((a > 5) XOR (a > 7)); + +--echo # Should return 6,7 +SELECT * FROM t1 WHERE NOT ((NOT (a > 5)) XOR (a > 7)); +SELECT * FROM t1 WHERE NOT ((a > 5) XOR (NOT (a > 7))); + +--echo # Should return 0..5,8..19 +SELECT * FROM t1 WHERE NOT ((NOT (a > 5)) XOR (NOT (a > 7))); + +--echo # Should have empty result +SELECT * FROM t1 WHERE (NULL XOR (a > 7)); +SELECT * FROM t1 WHERE NOT (NULL XOR (a > 7)); + +--echo # Should be simplified to "...WHERE (a XOR a) +EXPLAIN EXTENDED SELECT * FROM t1 WHERE NOT ((NOT a) XOR (a)); + +--echo # Should be simplified to "...WHERE (a XOR a) +EXPLAIN EXTENDED SELECT * FROM t1 WHERE NOT (a XOR (NOT a)); + +--echo # End XOR + delete from t1 where a > 3; select a, not(not(a)) from t1; explain extended select a, not(not(a)), not(a <= 2 and not(a)), not(a not like "1"), not (a not in (1,2)), not(a != 2) from t1 where not(not(a)) having not(not(a)); === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2011-02-18 07:43:02 +0000 +++ b/sql/item_cmpfunc.cc 2011-02-21 10:24:39 +0000 @@ -5333,23 +5333,21 @@ bool Item_func_like::turboBM_matches(con very fast to use. */ -longlong Item_cond_xor::val_int() +longlong Item_func_xor::val_int() { DBUG_ASSERT(fixed == 1); - List_iterator 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; } /** @@ -5390,6 +5388,33 @@ Item *Item_bool_rowready_func2::neg_tran 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. === modified file 'sql/item_cmpfunc.h' --- a/sql/item_cmpfunc.h 2010-12-29 00:38:59 +0000 +++ b/sql/item_cmpfunc.h 2011-02-21 10:24:39 +0000 @@ -1,7 +1,7 @@ #ifndef ITEM_CMPFUNC_INCLUDED #define ITEM_CMPFUNC_INCLUDED -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -411,6 +411,22 @@ public: bool subst_argument_checker(uchar **arg) { return TRUE; } }; +/** + XOR inherits from Item_bool_func2 because it is not optimized yet. + Later, when XOR is optimized, it needs to inherit from + Item_cond instead. See WL#5800. +*/ +class Item_func_xor :public Item_bool_func2 +{ +public: + Item_func_xor(Item *i1, Item *i2) :Item_bool_func2(i1, i2) {} + enum Functype functype() const { return XOR_FUNC; } + const char *func_name() const { return "xor"; } + longlong val_int(); + void top_level_item() {} + Item *neg_transformer(THD *thd); +}; + class Item_func_not :public Item_bool_func { public: @@ -1759,45 +1775,6 @@ inline bool is_cond_or(Item *item) return (cond_item->functype() == Item_func::COND_OR_FUNC); } -/* - XOR is Item_cond, not an Item_int_func because we could like to - optimize (a XOR b) later on. It's low prio, though -*/ - -class Item_cond_xor :public Item_cond -{ -public: - Item_cond_xor(Item *i1,Item *i2) :Item_cond(i1,i2) - { - /* - Items must be stored in args[] as well because this Item_cond is - treated as a FUNC_ITEM (see type()). I.e., users of it will get - it's children by calling arguments(), not argument_list(). This - is a temporary solution until XOR is optimized and treated like - a full Item_cond citizen. - */ - arg_count= 2; - args= tmp_arg; - args[0]= i1; - args[1]= i2; - } - enum Functype functype() const { return COND_XOR_FUNC; } - /* TODO: remove the next line when implementing XOR optimization */ - enum Type type() const { return FUNC_ITEM; } - longlong val_int(); - const char *func_name() const { return "xor"; } - void top_level_item() {} - /* Since child Items are stored in args[], Items cannot be added. - However, since Item_cond_xor is treated as a FUNC_ITEM (see - type()), the methods below should never be called. - */ - bool add(Item *item) { DBUG_ASSERT(FALSE); return FALSE; } - bool add_at_head(Item *item) { DBUG_ASSERT(FALSE); return FALSE; } - bool add_at_head(List *nlist) { DBUG_ASSERT(FALSE); return FALSE; } - void copy_andor_arguments(THD *thd, Item_cond *item) { DBUG_ASSERT(FALSE); } -}; - - /* Some useful inline functions */ inline Item *and_conds(Item *a, Item *b) === modified file 'sql/item_func.h' --- a/sql/item_func.h 2011-02-08 15:54:12 +0000 +++ b/sql/item_func.h 2011-02-21 10:24:39 +0000 @@ -46,7 +46,7 @@ public: enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC, GE_FUNC,GT_FUNC,FT_FUNC, LIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC, - COND_AND_FUNC, COND_OR_FUNC, COND_XOR_FUNC, + COND_AND_FUNC, COND_OR_FUNC, XOR_FUNC, BETWEEN, IN_FUNC, MULT_EQUAL_FUNC, INTERVAL_FUNC, ISNOTNULLTEST_FUNC, SP_EQUALS_FUNC, SP_DISJOINT_FUNC,SP_INTERSECTS_FUNC, === modified file 'sql/sql_yacc.yy' --- a/sql/sql_yacc.yy 2011-02-16 17:13:30 +0000 +++ b/sql/sql_yacc.yy 2011-02-21 10:24:39 +0000 @@ -7620,7 +7620,7 @@ expr: | expr XOR expr %prec XOR { /* XOR is a proprietary extension */ - $$ = new (YYTHD->mem_root) Item_cond_xor($1, $3); + $$ = new (YYTHD->mem_root) Item_func_xor($1, $3); if ($$ == NULL) MYSQL_YYABORT; } === modified file 'unittest/gunit/item-t.cc' --- a/unittest/gunit/item-t.cc 2011-02-07 13:03:47 +0000 +++ b/unittest/gunit/item-t.cc 2011-02-21 10:24:39 +0000 @@ -183,4 +183,51 @@ TEST_F(ItemTest, ItemFuncDesDecrypt) EXPECT_LE(item_decrypt->max_length, length); } + +TEST_F(ItemTest, ItemFuncXor) +{ + const uint length= 1U; + Item_int *item_zero= new Item_int(0, length); + Item_int *item_one_a= new Item_int(1, length); + + Item_func_xor *item_xor= + new Item_func_xor(item_zero, item_one_a); + + EXPECT_FALSE(item_xor->fix_fields(m_thd, NULL)); + EXPECT_EQ(1, item_xor->val_int()); + EXPECT_EQ(1U, item_xor->decimal_precision()); + + Item_int *item_one_b= new Item_int(1, length); + + Item_func_xor *item_xor_same= + new Item_func_xor(item_one_a, item_one_b); + + EXPECT_FALSE(item_xor_same->fix_fields(m_thd, NULL)); + EXPECT_EQ(0, item_xor_same->val_int()); + EXPECT_FALSE(item_xor_same->val_bool()); + EXPECT_FALSE(item_xor_same->is_null()); + + String print_buffer; + item_xor->print(&print_buffer, QT_ORDINARY); + EXPECT_STREQ("(0 xor 1)", print_buffer.c_ptr_safe()); + + Item *neg_xor= item_xor->neg_transformer(m_thd); + EXPECT_FALSE(neg_xor->fix_fields(m_thd, NULL)); + EXPECT_EQ(0, neg_xor->val_int()); + EXPECT_DOUBLE_EQ(0.0, neg_xor->val_real()); + EXPECT_FALSE(neg_xor->val_bool()); + EXPECT_FALSE(neg_xor->is_null()); + + print_buffer= String(); + neg_xor->print(&print_buffer, QT_ORDINARY); + EXPECT_STREQ("((not(0)) xor 1)", print_buffer.c_ptr_safe()); + + Item_func_xor *item_xor_null= + new Item_func_xor(item_zero, new Item_null()); + EXPECT_FALSE(item_xor_null->fix_fields(m_thd, NULL)); + + EXPECT_EQ(0, item_xor_null->val_int()); + EXPECT_TRUE(item_xor_null->is_null()); +} + } --===============4467625285775773548== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/jorgen.loland@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: jorgen.loland@stripped\ # xx12z0linjgzg47p # target_branch: file:///export/home/jl208045/mysql/mysql-trunk-59793/ # testament_sha1: 6928aab4edf37325850d69c083d874570512dec4 # timestamp: 2011-02-21 11:24:42 +0100 # base_revision_id: sergey.vojtovich@stripped\ # wfel5gbwf9szr1gf # # Begin bundle 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 --===============4467625285775773548==--