From: Ole John Aske Date: January 14 2011 8:20am Subject: bzr commit into mysql-trunk branch (ole.john.aske:3503) Bug#58628 List-Archive: http://lists.mysql.com/commits/128698 X-Bug: 58628 Message-Id: <20110114082016.8CE3F1818C@loki43.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============2224358296478729295==" --===============2224358296478729295== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///net/fimafeng09/export/home/tmp/oleja/mysql/mysql-trunk/ based on revid:serge.kozlov@stripped 3503 Ole John Aske 2011-01-14 Fix for bug#58628: Incorrect result for 'WHERE NULL NOT IN () create_ref_for_key() allowed any constant part of a REF key to be evaluated and stored into the 'key_buff' during ::optimize(). These 'store_key*' was *not* kept in ref.key_copy[] as they where constant and we assumed we would not have to reevaluate them during JOIN::exec() However, during execute NULL values in REF key has to be detected as they may need special attention - as in 'Full scan on NULL key'. This is done by subselect_uniquesubquery_engine::copy_ref_key() which check if any keyparts evaluated to a NULL-value. As we didn't keep a store_key for a constant value, a NULL-constant was not detected by subselect_uniquesubquery_engine::copy_ref_key() ! This fixs modifies create_ref_for_key() to check if a NULL-value constant was produced - In these cases it keeps the store_key, which then will be reevaluated in JOIN::exec() and trigger correct handling of NULL-valued keys. @ mysql-test/r/update.result Update of result file due to changed (improved) behaviour when constructing a REF key from 'out of bound' values. As the main fix will cause failing const key value ::copy() to be reevaluate inside JOIN::exec(), we will detect out of bound values (which will form an illegal/undefined REF key) before executing the access request. Previously these const REF keys was produced by JOIN::optimize() and any conversion/range errors was ignored. - Possibly causing undefined keys to be produced. These access request may then be ignored wo/ a Handler_read_key request being executed. modified: mysql-test/include/func_in.inc mysql-test/r/func_in_icp.result mysql-test/r/func_in_icp_mrr.result mysql-test/r/func_in_mrr.result mysql-test/r/func_in_mrr_cost.result mysql-test/r/func_in_none.result mysql-test/r/update.result sql/sql_select.cc sql/sql_select.h === modified file 'mysql-test/include/func_in.inc' --- a/mysql-test/include/func_in.inc 2010-07-23 17:51:11 +0000 +++ b/mysql-test/include/func_in.inc 2011-01-14 08:20:08 +0000 @@ -555,5 +555,47 @@ SELECT CASE a WHEN a THEN a END FROM t1 DROP TABLE t1; --echo # +--echo # Bug#58628: Incorrect result for 'WHERE NULL NOT IN () +--echo # + +CREATE TABLE t1 (pk INT NOT NULL, i INT); +INSERT INTO t1 VALUES (0,NULL), (1,NULL), (2,NULL), (3,NULL); + +CREATE TABLE subq (pk INT NOT NULL, i INT NOT NULL, PRIMARY KEY(i,pk)); +INSERT INTO subq VALUES (0,0), (1,1), (2,2), (3,3); + +## Baseline queries: t1.i contains only NULL and should effectively +## be evaluated as 'WHERE NULL IN' +## .. These return correct resultset ! + +--sorted_result +SELECT * FROM t1 + WHERE t1.i NOT IN + (SELECT i FROM subq WHERE subq.pk = t1.pk); + +--sorted_result +SELECT * FROM t1 + WHERE t1.i IN + (SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; + +## Replaced 't1.i' with some constant expression which +## also evaluates to NULL. Expected to return same result as above: + +--sorted_result +SELECT * FROM t1 + WHERE NULL NOT IN + (SELECT i FROM subq WHERE subq.pk = t1.pk); + +--sorted_result +SELECT * FROM t1 + WHERE NULL IN + (SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; + +--sorted_result +SELECT * FROM t1 + WHERE 1+NULL NOT IN + (SELECT i FROM subq WHERE subq.pk = t1.pk); + +DROP TABLE t1,subq; --echo End of 5.1 tests === modified file 'mysql-test/r/func_in_icp.result' --- a/mysql-test/r/func_in_icp.result 2010-07-23 17:51:11 +0000 +++ b/mysql-test/r/func_in_icp.result 2011-01-14 08:20:08 +0000 @@ -771,5 +771,40 @@ CASE a WHEN a THEN a END NULL DROP TABLE t1; # +# Bug#58628: Incorrect result for 'WHERE NULL NOT IN () +# +CREATE TABLE t1 (pk INT NOT NULL, i INT); +INSERT INTO t1 VALUES (0,NULL), (1,NULL), (2,NULL), (3,NULL); +CREATE TABLE subq (pk INT NOT NULL, i INT NOT NULL, PRIMARY KEY(i,pk)); +INSERT INTO subq VALUES (0,0), (1,1), (2,2), (3,3); +SELECT * FROM t1 +WHERE t1.i NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE t1.i IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE NULL IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE 1+NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +DROP TABLE t1,subq; End of 5.1 tests set optimizer_switch=default; === modified file 'mysql-test/r/func_in_icp_mrr.result' --- a/mysql-test/r/func_in_icp_mrr.result 2010-11-30 13:55:22 +0000 +++ b/mysql-test/r/func_in_icp_mrr.result 2011-01-14 08:20:08 +0000 @@ -771,5 +771,40 @@ CASE a WHEN a THEN a END NULL DROP TABLE t1; # +# Bug#58628: Incorrect result for 'WHERE NULL NOT IN () +# +CREATE TABLE t1 (pk INT NOT NULL, i INT); +INSERT INTO t1 VALUES (0,NULL), (1,NULL), (2,NULL), (3,NULL); +CREATE TABLE subq (pk INT NOT NULL, i INT NOT NULL, PRIMARY KEY(i,pk)); +INSERT INTO subq VALUES (0,0), (1,1), (2,2), (3,3); +SELECT * FROM t1 +WHERE t1.i NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE t1.i IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE NULL IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE 1+NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +DROP TABLE t1,subq; End of 5.1 tests set optimizer_switch=default; === modified file 'mysql-test/r/func_in_mrr.result' --- a/mysql-test/r/func_in_mrr.result 2010-11-30 13:55:22 +0000 +++ b/mysql-test/r/func_in_mrr.result 2011-01-14 08:20:08 +0000 @@ -771,5 +771,40 @@ CASE a WHEN a THEN a END NULL DROP TABLE t1; # +# Bug#58628: Incorrect result for 'WHERE NULL NOT IN () +# +CREATE TABLE t1 (pk INT NOT NULL, i INT); +INSERT INTO t1 VALUES (0,NULL), (1,NULL), (2,NULL), (3,NULL); +CREATE TABLE subq (pk INT NOT NULL, i INT NOT NULL, PRIMARY KEY(i,pk)); +INSERT INTO subq VALUES (0,0), (1,1), (2,2), (3,3); +SELECT * FROM t1 +WHERE t1.i NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE t1.i IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE NULL IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE 1+NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +DROP TABLE t1,subq; End of 5.1 tests set optimizer_switch=default; === modified file 'mysql-test/r/func_in_mrr_cost.result' --- a/mysql-test/r/func_in_mrr_cost.result 2010-11-30 13:55:22 +0000 +++ b/mysql-test/r/func_in_mrr_cost.result 2011-01-14 08:20:08 +0000 @@ -771,5 +771,40 @@ CASE a WHEN a THEN a END NULL DROP TABLE t1; # +# Bug#58628: Incorrect result for 'WHERE NULL NOT IN () +# +CREATE TABLE t1 (pk INT NOT NULL, i INT); +INSERT INTO t1 VALUES (0,NULL), (1,NULL), (2,NULL), (3,NULL); +CREATE TABLE subq (pk INT NOT NULL, i INT NOT NULL, PRIMARY KEY(i,pk)); +INSERT INTO subq VALUES (0,0), (1,1), (2,2), (3,3); +SELECT * FROM t1 +WHERE t1.i NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE t1.i IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE NULL IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE 1+NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +DROP TABLE t1,subq; End of 5.1 tests set optimizer_switch=default; === modified file 'mysql-test/r/func_in_none.result' --- a/mysql-test/r/func_in_none.result 2010-07-23 17:51:11 +0000 +++ b/mysql-test/r/func_in_none.result 2011-01-14 08:20:08 +0000 @@ -770,5 +770,40 @@ CASE a WHEN a THEN a END NULL DROP TABLE t1; # +# Bug#58628: Incorrect result for 'WHERE NULL NOT IN () +# +CREATE TABLE t1 (pk INT NOT NULL, i INT); +INSERT INTO t1 VALUES (0,NULL), (1,NULL), (2,NULL), (3,NULL); +CREATE TABLE subq (pk INT NOT NULL, i INT NOT NULL, PRIMARY KEY(i,pk)); +INSERT INTO subq VALUES (0,0), (1,1), (2,2), (3,3); +SELECT * FROM t1 +WHERE t1.i NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE t1.i IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +SELECT * FROM t1 +WHERE NULL IN +(SELECT i FROM subq WHERE subq.pk = t1.pk) IS UNKNOWN; +pk i +0 NULL +1 NULL +2 NULL +3 NULL +SELECT * FROM t1 +WHERE 1+NULL NOT IN +(SELECT i FROM subq WHERE subq.pk = t1.pk); +pk i +DROP TABLE t1,subq; End of 5.1 tests set optimizer_switch=default; === modified file 'mysql-test/r/update.result' --- a/mysql-test/r/update.result 2010-08-25 19:00:38 +0000 +++ b/mysql-test/r/update.result 2011-01-14 08:20:08 +0000 @@ -410,7 +410,7 @@ user_id show status like '%Handler_read%'; Variable_name Value Handler_read_first 0 -Handler_read_key 1 +Handler_read_key 0 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 @@ -421,7 +421,7 @@ user_id show status like '%Handler_read%'; Variable_name Value Handler_read_first 0 -Handler_read_key 2 +Handler_read_key 0 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 @@ -431,7 +431,7 @@ UPDATE t1 SET user_id=null WHERE request show status like '%Handler_read%'; Variable_name Value Handler_read_first 0 -Handler_read_key 3 +Handler_read_key 1 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 @@ -441,7 +441,7 @@ UPDATE t1 SET user_id=null WHERE request show status like '%Handler_read%'; Variable_name Value Handler_read_first 0 -Handler_read_key 3 +Handler_read_key 1 Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2011-01-13 10:48:28 +0000 +++ b/sql/sql_select.cc 2011-01-14 08:20:08 +0000 @@ -8929,29 +8929,37 @@ static bool create_ref_for_key(JOIN *joi j->ref.null_rejecting |= 1 << i; keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables; + store_key* key= get_store_key(thd, + keyuse,join->const_table_map, + &keyinfo->key_part[i], + key_buff, maybe_null); + if (unlikely(!key || thd->is_fatal_error)) + DBUG_RETURN(TRUE); + if (keyuse->used_tables || thd->lex->describe) /* Comparing against a non-constant or executing an EXPLAIN query (which refers to this info when printing the 'ref' column of the query plan) */ - *ref_key++= get_store_key(thd, - keyuse,join->const_table_map, - &keyinfo->key_part[i], - key_buff, maybe_null); + *ref_key++= key; else - { // Compare against constant - store_key_item tmp(thd, keyinfo->key_part[i].field, - key_buff + maybe_null, - maybe_null ? key_buff : 0, - keyinfo->key_part[i].length, keyuse->val); - if (thd->is_fatal_error) - DBUG_RETURN(TRUE); - /* - The constant is the value to look for with this key. Copy - the value to ref->key_buff - */ - tmp.copy(); + { + /* key is const, copy value now and possibly skip it while ::exec() */ + enum store_key::store_key_result result= key->copy(); + + /* Depending on 'result' it should be reevaluated in ::exec(), if either: + * 1) '::copy()' failed, in case we reevaluate - and refail in + * JOIN::exec() where the error can be handled. + * 2) Constant evaluated to NULL value which we might need to + * handle as a special case during JOIN::exec() + * (As in : 'Full scan on NULL key') + */ + if (result!=store_key::STORE_KEY_OK || // 1) + key->null_key) // 2) + { + *ref_key++= key; // Reevaluate in JOIN::exec() + } } /* Remember if we are going to use REF_OR_NULL === modified file 'sql/sql_select.h' --- a/sql/sql_select.h 2010-12-29 00:38:59 +0000 +++ b/sql/sql_select.h 2011-01-14 08:20:08 +0000 @@ -2168,9 +2168,8 @@ public: store_key_const_item(THD *thd, Field *to_field_arg, uchar *ptr, uchar *null_ptr_arg, uint length, Item *item_arg) - :store_key_item(thd, to_field_arg,ptr, - null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? - &err : (uchar*) 0, length, item_arg), inited(0) + :store_key_item(thd, to_field_arg, ptr, + null_ptr_arg, length, item_arg), inited(0) { } const char *name() const { return "const"; } @@ -2178,27 +2177,13 @@ public: protected: enum store_key_result copy_inner() { - int res; if (!inited) { inited=1; - TABLE *table= to_field->table; - my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, - table->write_set); - if ((res= item->save_in_field(to_field, 1))) - { - if (!err) - err= res < 0 ? 1 : res; /* 1=STORE_KEY_FATAL */ - } - /* - Item::save_in_field() may call Item::val_xxx(). And if this is a subquery - we need to check for errors executing it and react accordingly - */ - if (!err && to_field->table->in_use->is_error()) - err= 1; /* STORE_KEY_FATAL */ - dbug_tmp_restore_column_map(table->write_set, old_map); + int res= store_key_item::copy_inner(); + if (res && !err) + err= res; } - null_key= to_field->is_null() || item->null_value; return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err); } }; --===============2224358296478729295== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/ole.john.aske@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: ole.john.aske@stripped\ # 77kfco4xs4geosam # target_branch: file:///net/fimafeng09/export/home/tmp/oleja/mysql\ # /mysql-trunk/ # testament_sha1: 38fecc49c38b63da05bd643cd14a6109ef89d7c9 # timestamp: 2011-01-14 09:20:16 +0100 # source_branch: file:///net/fimafeng09/export/home/tmp/oleja/mysql\ # /mysql-5.5/ # base_revision_id: serge.kozlov@stripped\ # 4qccnwyy72pxtnhh # # Begin bundle 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 /h2H//F3JFOFCQuqNufw --===============2224358296478729295==--