From: Jorgen Loland Date: February 7 2011 2:07pm Subject: bzr commit into mysql-trunk branch (jorgen.loland:3605) Bug#59793 List-Archive: http://lists.mysql.com/commits/130582 X-Bug: 59793 Message-Id: <20110207140725.53BD395F@atum21.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0933923147213536066==" --===============0933923147213536066== 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:tor.didriksen@stripped 3605 Jorgen Loland 2011-02-07 Bug#59793: crash in Item_field::register_field_in_read_map with view 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. @ mysql-test/include/subquery.inc Add test for BUG#59793 @ mysql-test/r/negation_elimination.result Add tests for negation of XOR @ mysql-test/r/subquery_nomat_nosj.result Add test for BUG#59793 @ mysql-test/r/subquery_none.result Add test for BUG#59793 @ mysql-test/t/negation_elimination.test Add tests for negation of XOR @ sql/item_cmpfunc.cc Refactor XOR item: it is now a pure Item_func, inheriting from Item_bool_func2 instead of Item_cond @ sql/item_cmpfunc.h Refactor XOR item: it is now a pure Item_func, inheriting from Item_bool_func2 instead of Item_cond @ 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.inc mysql-test/r/negation_elimination.result mysql-test/r/subquery_nomat_nosj.result mysql-test/r/subquery_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.inc' --- a/mysql-test/include/subquery.inc 2011-02-02 09:04:55 +0000 +++ b/mysql-test/include/subquery.inc 2011-02-07 14:07:21 +0000 @@ -5286,3 +5286,19 @@ CREATE TABLE t(a VARCHAR(245) DEFAULT INSERT INTO t VALUES (''),(''),(''),(''),(''),(''),(''),(''),(''),(''),(''); SELECT * FROM (SELECT default(a) FROM t GROUP BY a) d; DROP TABLE t; + +--echo # +--echo # Bug#59793: 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/negation_elimination.result' --- a/mysql-test/r/negation_elimination.result 2010-04-20 07:22:51 +0000 +++ b/mysql-test/r/negation_elimination.result 2011-02-07 14:07:21 +0000 @@ -375,6 +375,122 @@ a 13 14 15 + +# XOR [ NOT (a XOR b) == (NOT a) XOR b == a XOR (NOT b) ] +# Should return 6,7 +SELECT * FROM t1 WHERE ((a > 5) XOR (a > 7)); +a +6 +7 +# Should return 0..5,8..19 +SELECT * FROM t1 WHERE ((NOT (a > 5)) XOR (a > 7)); +a +0 +1 +2 +3 +4 +5 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +SELECT * FROM t1 WHERE ((a > 5) XOR (NOT (a > 7))); +a +0 +1 +2 +3 +4 +5 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +SELECT * FROM t1 WHERE NOT ((a > 5) XOR (a > 7)); +a +0 +1 +2 +3 +4 +5 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +# Should return 6,7 +SELECT * FROM t1 WHERE NOT ((NOT (a > 5)) XOR (a > 7)); +a +6 +7 +SELECT * FROM t1 WHERE NOT ((a > 5) XOR (NOT (a > 7))); +a +6 +7 +# Should return 0..5,8..19 +SELECT * FROM t1 WHERE NOT (NOT (a > 5) XOR (NOT (a > 7))); +a +0 +1 +2 +3 +4 +5 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +SELECT * FROM t1 WHERE (NULL XOR (a > 7)); +a +SELECT * FROM t1 WHERE NOT (NULL XOR (a > 7)); +a +# Should be "...WHERE (a XOR a) +explain extended SELECT * FROM t1 WHERE NOT ((NOT a) XOR (a)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 index NULL a 5 NULL 21 100.00 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` xor `test`.`t1`.`a`) +# Should be "...WHERE (a XOR a) +explain extended SELECT * FROM t1 WHERE NOT (a XOR (NOT a)); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 index NULL a 5 NULL 21 100.00 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` xor `test`.`t1`.`a`) +# XOR End + delete from t1 where a > 3; select a, not(not(a)) from t1; a not(not(a)) === modified file 'mysql-test/r/subquery_nomat_nosj.result' --- a/mysql-test/r/subquery_nomat_nosj.result 2011-02-02 09:04:55 +0000 +++ b/mysql-test/r/subquery_nomat_nosj.result 2011-02-07 14:07:21 +0000 @@ -6442,4 +6442,17 @@ SELECT * FROM (SELECT default(a) FROM t default(a) aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DROP TABLE t; +# +# Bug#59793: 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/r/subquery_none.result' --- a/mysql-test/r/subquery_none.result 2011-02-02 09:04:55 +0000 +++ b/mysql-test/r/subquery_none.result 2011-02-07 14:07:21 +0000 @@ -6441,4 +6441,17 @@ SELECT * FROM (SELECT default(a) FROM t default(a) aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DROP TABLE t; +# +# Bug#59793: 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-07 14:07:21 +0000 @@ -65,10 +65,40 @@ 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 +--echo # XOR [ NOT (a XOR b) == (NOT a) XOR b == a XOR (NOT b) ] + +--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))); + +SELECT * FROM t1 WHERE (NULL XOR (a > 7)); +SELECT * FROM t1 WHERE NOT (NULL XOR (a > 7)); + +--echo # Should be "...WHERE (a XOR a) +explain extended SELECT * FROM t1 WHERE NOT ((NOT a) XOR (a)); + +--echo # Should be "...WHERE (a XOR a) +explain extended SELECT * FROM t1 WHERE NOT (a XOR (NOT a)); + +--echo # XOR End +--echo + 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)); drop table t1; -# End of 4.1 tests + === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2011-01-19 14:39:13 +0000 +++ b/sql/item_cmpfunc.cc 2011-02-07 14:07:21 +0000 @@ -5330,17 +5330,15 @@ 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; + int result=0; null_value=0; - while ((item=li++)) + 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; return 0; @@ -5387,6 +5385,27 @@ Item *Item_bool_rowready_func2::neg_tran return item; } +/* + NOT (a XOR b) == (NOT a) XOR b == a XOR (NOT b) + */ +Item *Item_func_xor::neg_transformer(THD *thd) +{ + Item *neg_argument; + Item_func_xor *new_item; + if ((neg_argument= args[0]->neg_transformer(thd))) + // args[0] has neg_tranformer + new_item= new Item_func_xor(neg_argument, args[1]); + else if ((neg_argument= args[1]->neg_transformer(thd))) + // args[0] has neg_tranformer + new_item= new Item_func_xor(args[0], neg_argument); + else + { + neg_argument= new Item_func_not(args[0]); + new_item= new Item_func_xor(neg_argument, 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-07 14:07:21 +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 (a XOR b) is optimized, it needs to inherit from + Item_cond instead. It's low prio, though */ +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; } + /* longlong val_int(); */ + 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-01-28 13:49:59 +0000 +++ b/sql/item_func.h 2011-02-07 14:07:21 +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-03 10:13:06 +0000 +++ b/sql/sql_yacc.yy 2011-02-07 14:07:21 +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-07 14:07:21 +0000 @@ -183,4 +183,31 @@ TEST_F(ItemTest, ItemFuncDesDecrypt) EXPECT_LE(item_decrypt->max_length, length); } +TEST_F(ItemTest, ItemFuncXor) +{ + const uint length= 1U; + Item_int *item_one= new Item_int(0, length); + Item_int *item_two= new Item_int(1, length); + + Item_func_xor *item_xor= + new Item_func_xor(item_two, item_one); + + item_xor->fix_fields(m_thd, NULL); + EXPECT_EQ(1, item_xor->val_int()); + + Item *neg_xor= item_xor->neg_transformer(m_thd); + neg_xor->fix_fields(m_thd, NULL); + EXPECT_EQ(0, neg_xor->val_int()); + EXPECT_EQ(0, neg_xor->val_real()); + EXPECT_EQ(0, neg_xor->val_bool()); + EXPECT_EQ(0, neg_xor->is_null()); + + Item_func_xor *item_xor_null= + new Item_func_xor(item_one, new Item_null()); + item_xor_null->fix_fields(m_thd, NULL); + + EXPECT_EQ(0, item_xor_null->val_int()); + EXPECT_EQ(1, item_xor_null->is_null()); +} + } --===============0933923147213536066== 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\ # yfsg5kraz61uxrcl # target_branch: file:///export/home/jl208045/mysql/mysql-trunk-59793/ # testament_sha1: 03afcf0daca3f0d0a30d8f5e97a8ab2323d1cf5d # timestamp: 2011-02-07 15:07:25 +0100 # base_revision_id: tor.didriksen@stripped\ # lmjksir7xpbf3sth # # Begin bundle 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 sSF3sMtVF9alQtjSmDH/hkP+LuSKcKEgwIsX/g== --===============0933923147213536066==--