3870 Guilhem Bichot 2012-02-09 [merge]
merge from trunk
modified:
mysql-test/r/events_restart.result
mysql-test/t/events_restart.test
sql/events.cc
3869 Guilhem Bichot 2012-02-09 [merge]
merge with trunk
modified:
mysql-test/include/icp_tests.inc
mysql-test/include/join_cache.inc
mysql-test/include/subquery.inc
mysql-test/include/subquery_mat.inc
mysql-test/r/innodb_icp.result
mysql-test/r/innodb_icp_all.result
mysql-test/r/innodb_icp_none.result
mysql-test/r/join_cache_bka.result
mysql-test/r/join_cache_bka_nixbnl.result
mysql-test/r/join_cache_bkaunique.result
mysql-test/r/join_cache_bnl.result
mysql-test/r/join_cache_nojb.result
mysql-test/r/myisam_icp.result
mysql-test/r/myisam_icp_all.result
mysql-test/r/myisam_icp_none.result
mysql-test/r/subquery_all.result
mysql-test/r/subquery_all_bka.result
mysql-test/r/subquery_all_bka_nixbnl.result
mysql-test/r/subquery_mat.result
mysql-test/r/subquery_mat_all.result
mysql-test/r/subquery_mat_none.result
mysql-test/r/subquery_nomat_nosj.result
mysql-test/r/subquery_nomat_nosj_bka.result
mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result
mysql-test/r/subquery_none.result
mysql-test/r/subquery_none_bka.result
mysql-test/r/subquery_none_bka_nixbnl.result
mysql-test/r/subquery_sj_all.result
mysql-test/r/subquery_sj_all_bka.result
mysql-test/r/subquery_sj_all_bka_nixbnl.result
mysql-test/r/subquery_sj_all_bkaunique.result
mysql-test/r/subquery_sj_mat.result
mysql-test/r/subquery_sj_mat_bka.result
mysql-test/r/subquery_sj_mat_bka_nixbnl.result
mysql-test/r/subquery_sj_mat_bkaunique.result
mysql-test/r/subquery_sj_mat_nosj.result
mysql-test/suite/innodb/r/innodb_mysql.result
mysql-test/suite/opt_trace/include/general.inc
mysql-test/suite/opt_trace/r/bugs_no_prot_all.result
mysql-test/suite/opt_trace/r/bugs_no_prot_none.result
mysql-test/suite/opt_trace/r/bugs_ps_prot_all.result
mysql-test/suite/opt_trace/r/bugs_ps_prot_none.result
mysql-test/suite/opt_trace/r/general2_no_prot.result
mysql-test/suite/opt_trace/r/general2_ps_prot.result
mysql-test/suite/opt_trace/r/general_no_prot_all.result
mysql-test/suite/opt_trace/r/general_no_prot_none.result
mysql-test/suite/opt_trace/r/general_ps_prot_all.result
mysql-test/suite/opt_trace/r/general_ps_prot_none.result
mysql-test/suite/opt_trace/r/subquery_no_prot.result
mysql-test/suite/opt_trace/r/subquery_ps_prot.result
sql/item_cmpfunc.cc
sql/item_cmpfunc.h
sql/item_subselect.cc
sql/item_subselect.h
sql/sql_class.cc
sql/sql_optimizer.cc
sql/sql_resolver.cc
sql/sql_select.cc
3868 Venkata Sidagam 2012-02-09
Bug #11755870-47704: HASH INDEX ON VARCHAR PREFIX NOT WORKING CORRECTLY.
Brief description: Insert some rows to MEMORY table with HASH key on varchar field.
A select on specific existing tuple is showing empty set.
Problem Analysis/solution: In hp_key_cmp() when the seg->type == HA_KEYTYPE_VARTEXT1
the char_length_rec is the length of pos string and it is compared with key string for
char_length_key bytes. Here both char_length_rec and char_length_key will be of different
values when we have hash index on column prefix. So the comparition is failing and
the result set is empty.
So the fix is, if char_length_rec has more value than the char_length_key make
char_length_rec as same as char_length_key
@ storage/heap/hp_hash.c
Modified hp_key_cmp() function
modified:
mysql-test/r/heap.result
mysql-test/t/heap.test
storage/heap/hp_hash.c
3867 Dmitry Shulga 2012-02-09
Patch for bug#11764747 (formerly known as 57612): SET GLOBAL READ_ONLY=1 cannot
progress when a table is locked with LOCK TABLES.
The reason for the bug was that mysql server makes a flush of all open tables
during handling of statement 'SET GLOBAL READ_ONLY=1'. Therefore if some of
these tables were locked by "LOCK TABLE ... READ" from a different connection,
then execution of statement 'SET GLOBAL READ_ONLY=1' would be waiting for
the lock for such table even if the table was locked in a compatible read mode.
Flushing of all open tables before setting of read_only system variable
is inherited from 5.1 implementation since this was the only possible approach
to ensure that there isn't any pending write operations on open tables.
Start from version 5.5 and above such behaviour is guaranteed by the fact
that we acquire global_read_lock before setting read_only flag. Since
acquiring of global_read_lock is successful only when there isn't any
active write operation then we can remove flushing of open tables from
processing of SET GLOBAL READ_ONLY=1.
This modification changes the server behavior so that read locks held
by other connections (LOCK TABLE ... READ) no longer will block attempts
to enable read_only.
@ mysql-test/t/read_only.test
Modified testcase in order to takes into account the changed behaviour
in processing of 'set read_only' statement.
@ sql/sys_vars.cc
Removed flushing of open tables from processing of
SET GLOBAL READ_ONLY=1.
modified:
mysql-test/r/read_only.result
mysql-test/t/read_only.test
sql/sys_vars.cc
3866 Jorgen Loland 2012-02-09
Bug#13354910 - MAKE_JOIN_STATISTICS() INVOKES
RECORDS_IN_RANGE(MIN_KEY=0X0, MAX_KEY=0X0)
Some range predicates that by them selves make up partial
ranges are merged into a full range by the range optimizer.
An example is the query for this bug:
"WHERE col IN (1,2,6) OR col NOT IN (1)"
This predicate is always true and is correctly merged into
the range [-inf <= col <= +inf]. However, although the range
optimizer did make a full range, it did not realize that it's
meaningless to use this as a range predicate since that will
be the same as doing an index scan.
For the query in the bug the problem was that
SEL_ARG::copy_max() had a bug: When checking if the range was
a full range, it was checked if max_flag was set to
(NO_MAX_RANGE | NO_MIN_RANGE). But the NO_MIN_FLAG is stored
in min_flag, so the test is changed to
(max_flag & NO_MAX_FLAG) and (min_flag & NO_MIN_FLAG).
Enabling the DBUG_ASSERT(max_key || min_key) in
ha_innobase::records_in_range() then showed another related
bug: innodb_icp started failing because SEL_ARG::copy_min()
had the very same bug as copy_max(). This was fixed as well.
In an attempt at unittesting SEL_ARG, copy_min() and copy_max()
have now been added to the opt_range-t gunit test.
To see the assert, add "DBUG_ASSERT(min_key || max_key);"
to the beginning of ha_innobase::records_in_range().
@ mysql-test/include/index_merge1.inc
Added a new test to test the intended behavior of a
query that changed due to the bugfix.
@ mysql-test/r/index_merge_myisam.result
Updated result file because an invalid execution plan changed.
Also added a new test to test the intended behavior of the
query that changed.
@ sql/opt_range.cc
SEL_ARG::copy_min() and copy_max() now checks if the NO_MIN_RANGE
flag is set in min_flag and the NO_MAX_FLAG in max_flag.
@ unittest/gunit/opt_range-t.cc
Add tests for SEL_ARG::copy_min() and SEL_ARG::copy_max().
modified:
mysql-test/include/index_merge1.inc
mysql-test/r/index_merge_myisam.result
sql/opt_range.cc
unittest/gunit/opt_range-t.cc
3865 Guilhem Bichot 2012-02-08
Fix for
Bug #13688248 CRASH IN DIAGNOSTICS_AREA::SET_OK_STATUS WHEN USING DEBUG_SYNC.
And, to test the above, I had to fix
Bug #13688015 THE OPTION --LOOSE-DEBUG-SYNC-TIMEOUT IS PLACED WRONG
@ mysql-test/mysql-test-run.pl
Options specified in .opt files should be added last so they can
override defaults of mtr (fixes Bug#13688015)
@ mysql-test/t/debug_sync2.test
test for bug, used to assert
@ sql/debug_sync.cc
In the scenario of debug_sync2.test, debug sync point timed out;
thus a warning was raised, but because sql_mode=traditional,
push_warning() changed it to an error. But code in mysql_insert()
(container of the debug sync point) didn't handle this error,
finally an OK was sent, which triggered an assertion (you can't
have an OK *and* an error at the same time).
Fix: warnings of debug_sync should never be errors (sql_mode=traditional
is, per the doc, for *bad data* errors; a debug sync timeout
will not cause bad data; and debug_sync is only meant for our QA and devs,
and we only ship it in debug builds).
So: disable abort_on_warning.
added:
mysql-test/r/debug_sync2.result
mysql-test/t/debug_sync2-master.opt
mysql-test/t/debug_sync2.test
modified:
mysql-test/mysql-test-run.pl
sql/debug_sync.cc
3864 Jorgen Loland 2012-02-09
BUG#13354910 - MAKE_JOIN_STATISTICS() INVOKES
RECORDS_IN_RANGE(MIN_KEY=0X0, MAX_KEY=0X0)
Preparation patch: improve readability of key_or() by using more
descriptive variable names.
@ sql/opt_range.cc
Improve readability of key_or() by using more descriptive
variable names.
modified:
sql/opt_range.cc
=== modified file 'mysql-test/include/icp_tests.inc'
--- a/mysql-test/include/icp_tests.inc 2012-02-01 09:59:13 +0000
+++ b/mysql-test/include/icp_tests.inc 2012-02-08 15:25:17 +0000
@@ -862,6 +862,15 @@ CREATE TABLE t2 (
INSERT INTO t2 VALUES (1,7,'f');
+# Bug was specific of IN->EXISTS:
+set @old_opt_switch=@@optimizer_switch;
+--disable_query_log
+if (`select locate('materialization', @@optimizer_switch) > 0`)
+{
+ set optimizer_switch='materialization=off';
+}
+--enable_query_log
+
let query=
SELECT t1.i1
FROM t1
@@ -877,6 +886,7 @@ WHERE t1.i1 NOT IN
eval EXPLAIN $query;
eval $query;
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1,t2;
--echo #
@@ -909,6 +919,15 @@ CREATE TABLE t3 (
INSERT INTO t3 VALUES (NULL,'w'), (1,NULL), (2,'d');
+# Bug was specific of IN->EXISTS:
+set @old_opt_switch=@@optimizer_switch;
+--disable_query_log
+if (`select locate('materialization', @@optimizer_switch) > 0`)
+{
+ set optimizer_switch='materialization=off';
+}
+--enable_query_log
+
let query=
SELECT i1
FROM t3
@@ -923,6 +942,7 @@ WHERE c1 IN
eval EXPLAIN $query;
eval $query;
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
--echo #
=== modified file 'mysql-test/include/index_merge1.inc'
--- a/mysql-test/include/index_merge1.inc 2011-11-03 07:01:49 +0000
+++ b/mysql-test/include/index_merge1.inc 2012-02-09 11:22:17 +0000
@@ -167,8 +167,14 @@ explain select * from t0 where
explain select * from t0 where
((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
or
- ((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6));
+ ((key3 >5 or key5 < 2) and (key5 < 5 or key6 < 6));
+explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where
+ ((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+ or
+ ((key3 >5 or key5 < 2) and (key5 < 5 or key6 < 6));
+
+# Can't merge any indexes here (predicate on key3 is always true)
explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where
((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
or
=== modified file 'mysql-test/include/join_cache.inc'
--- a/mysql-test/include/join_cache.inc 2012-01-26 15:42:39 +0000
+++ b/mysql-test/include/join_cache.inc 2012-02-08 15:25:17 +0000
@@ -1713,6 +1713,15 @@ CREATE TABLE t3 (
INSERT INTO t3 VALUES (NULL), (NULL);
+# Bug was specific of IN->EXISTS:
+set @old_opt_switch=@@optimizer_switch;
+--disable_query_log
+if (`select locate('materialization', @@optimizer_switch) > 0`)
+{
+ set optimizer_switch='materialization=off';
+}
+--enable_query_log
+
--echo
let query_in=
@@ -1752,6 +1761,7 @@ eval $query_in_toplevel;
--echo
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
set @@join_buffer_size=default;
=== modified file 'mysql-test/include/subquery.inc'
--- a/mysql-test/include/subquery.inc 2012-02-07 14:50:31 +0000
+++ b/mysql-test/include/subquery.inc 2012-02-08 15:25:17 +0000
@@ -3223,7 +3223,7 @@ INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
---echo # should have eq_ref for t1
+--echo # should have eq_ref for t1, unless subquery materialization is used
--replace_column 1 x 2 x 5 x 6 x 7 x 8 x 9 x 10 x
EXPLAIN
SELECT * FROM t2 outr
@@ -5804,3 +5804,21 @@ eval EXPLAIN SELECT * FROM ( $subq ) AS
eval SELECT * FROM ( $subq ) AS alias3;
DROP TABLE t1,t2;
+
+--echo #
+--echo # Test that indexsubquery_engine only does one lookup if
+--echo # the technique is unique_subquery: does not try to read the
+--echo # next row if the first row failed the subquery's WHERE
+--echo # condition (here: b=3).
+--echo #
+
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+let $query=select * from t1 where a in (select a from t2 where b=3);
+eval explain $query;
+flush status;
+eval $query;
+show status like "handler_read%";
+drop table t1,t2;
=== modified file 'mysql-test/include/subquery_mat.inc'
--- a/mysql-test/include/subquery_mat.inc 2012-01-20 09:07:08 +0000
+++ b/mysql-test/include/subquery_mat.inc 2012-02-08 15:25:17 +0000
@@ -910,7 +910,6 @@ DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;
-
--echo #
--echo # Bug#13419028 - SUBQUERY MATERIALIZATION NOT USED IN CREATE
--echo # SELECT
@@ -1021,5 +1020,327 @@ eval $query;
DROP TABLE t1, t2;
--echo # End of test for bug#13607423.
+
+--echo
+--echo Test of WL#6094 "Allow subquery materialization in NOT IN if all
+--echo columns are not nullable"
+--echo
+
+# We want to test WL#6094 only, not WL#6095, so we use 2 columns.
+
+create table t1(a int not null);
+create table t2(a int not null);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+
+--echo Test in SELECT list
+
+--echo
+let $query=select a, (a,a) in (select a,a from t2) from t1;
+
+--echo cols not nullable => subq materialization
+eval explain extended $query;
+eval $query;
+
+--echo
+let $query=select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+--echo cols not nullable => subq materialization
+eval explain extended $query;
+eval $query;
+
+--echo
+let $query=select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+
+--echo t2.a is not nullable, but in the query it may appear as NULL
+--echo as it's in an outer join. So, no materialization.
+eval explain extended $query;
+eval $query;
+
+--echo
+alter table t2 modify a int;
+let $query=select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+--echo two nullable inner cols => no subq materialization
+eval explain extended $query;
+eval $query;
+alter table t2 modify a int not null;
+
+--echo
+--echo Test in WHERE
+--echo
+let $query=select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) in (select a,a from t2 as t3);
+--echo top-level => subq materialization. With one exception: if
+--echo semijoin is enabled in @@optimizer_switch, semijoin is chosen,
+--echo then rejected (due to outer join), and in that case, the
+--echo fallback is IN->EXISTS, subq-materialization is not tried...
+eval explain extended $query;
+eval $query;
+
+--echo
+let $query=select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) not in (select a,a from t2 as t3);
+--echo cols not nullable => subq materialization
+eval explain extended $query;
+eval $query;
+
+drop table t1,t2;
+
+--echo
+--echo Test of WL6095 "Allow subquery materialization in NOT IN if
+--echo single-column subquery"
+--echo
+
+# We want to test WL#6095 only, not WL#6094, so we use nullable columns.
+
+create table t1(a int null);
+create table t2(a int null);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+
+--echo
+let $query=select a, a in (select a from t2) from t1;
+
+--echo one col => subq materialization
+eval explain extended $query;
+eval $query;
+
+--echo
+let $query=select t1.a, t2.a, t2.a in (select * from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+
+--echo t2.a is not nullable, but in the query it may appear as NULL
+--echo as it's in an outer join. But there is only one inner column so
+--echo materialization is possible
+eval explain extended $query;
+eval $query;
+
+--echo
+let $query=select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+
+--echo _two_ outer columns, nullable => no materialization
+eval explain extended $query;
+eval $query;
+
+drop table t1,t2;
+
+--echo
+--echo Test in HAVING
+
+create table t1(a int, b int);
+create table t2(a int);
+insert into t1 values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3);
+insert into t2 values(10),(20);
+
+let $query=select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+
+--echo no NULLs.
+
+eval explain extended $query;
+eval $query;
+
+--echo one outer NULL
+insert into t1 values(null,null);
+
+eval explain extended $query;
+eval $query;
+
+--echo one outer NULL and one inner NULL
+insert into t2 values(null);
+
+eval explain extended $query;
+eval $query;
+
+--echo one inner NULL
+delete from t1 where a is null;
+
+eval explain extended $query;
+eval $query;
+
+drop table t1,t2;
+
+--echo
+--echo Verify that an inner NULL is looked up only once (result is
+--echo cached).
+
+create table t1(a int);
+create table t2(a int);
+insert into t1 values(1),(2),(3),(4),(5),(6);
+insert into t1 select * from t1; # t1 has 12 rows
+insert into t2 values(10),(20),(NULL);
+
+let $query=select a, (a in (select * from t2)) from t1;
+
+eval explain extended $query;
+flush status;
+eval $query;
+--echo There will be one look-up in the temporary table for each row
+--echo of t1 (12), plus one additional look-up to check whether table
+--echo contains a NULL value.
+show status like "handler_read_key";
+
+drop table t1,t2;
+
+--echo #
+--echo # Bug#13495157 - SUBQUERY MATERIALIZATION NOT USED FOR CERTAIN
+--echo # STATEMENTS
+--echo #
+
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1),(2),(3);
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES(1),(2),(4);
+
+--echo # subquery materialization used for SELECT:
+EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+
+--echo # Also used for INSERT SELECT:
+# a) all different tables:
+CREATE TABLE t3 SELECT * FROM t1;
+EXPLAIN INSERT INTO t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+INSERT INTO t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+--sorted_result
+SELECT * FROM t3;
+
+# b) insert into subquery's selected table
+EXPLAIN INSERT INTO t2 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+INSERT INTO t2 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+--sorted_result
+SELECT * FROM t2;
+
+# c) insert into subquery's and query's selected table
+EXPLAIN INSERT INTO t2 SELECT * FROM t2 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+INSERT INTO t2 SELECT * FROM t2 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+--sorted_result
+SELECT * FROM t2;
+
+--echo # Not used for single-table UPDATE, DELETE:
+# a) all different tables
+EXPLAIN SELECT * FROM t2 WHERE a IN (SELECT * FROM t1);
+EXPLAIN UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t1);
+UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t1);
+--sorted_result
+SELECT * FROM t2;
+EXPLAIN DELETE FROM t2 WHERE a IN (SELECT * FROM t1);
+DELETE FROM t2 WHERE a IN (SELECT * FROM t1);
+--sorted_result
+SELECT * FROM t2;
+
+# b) update/delete in subquery's selected table: forbidden
+--error ER_UPDATE_TABLE_USED
+EXPLAIN UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t2);
+--error ER_UPDATE_TABLE_USED
+EXPLAIN DELETE FROM t2 WHERE a IN (SELECT * FROM t2);
+
+# Put some content so that future queries have rows to modify:
+UPDATE t2 SET a=3 WHERE a=0;
+
+--echo # Used for multi-table UPDATE, DELETE:
+
+# a) all different tables
+EXPLAIN SELECT * FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+EXPLAIN UPDATE t2,t3 SET t2.a=t2.a-2 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+UPDATE t2,t3 SET t2.a=t2.a-2 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+--sorted_result
+SELECT * FROM t2;
+EXPLAIN DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+--sorted_result
+SELECT * FROM t2;
+
+# b) update/delete in subquery's selected table: forbidden
+--error ER_UPDATE_TABLE_USED
+EXPLAIN UPDATE t2,t3 SET t2.a=10 WHERE t2.a IN (SELECT * FROM t2 WHERE a <> 2);
+--error ER_UPDATE_TABLE_USED
+EXPLAIN DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t2 WHERE a <> 2);
+
+DROP TABLE t1,t2,t3;
+
+--echo #
+--echo # Test that subquery materialization only does one lookup: does
+--echo # not try to read the next row if the first row failed the
+--echo # subquery's WHERE. We use a case where index lookup is not
+--echo # enough to satisfy IN(), because index has length two when the
+--echo # outer value has length three, and thus the post-filtering
+--echo # WHERE added by subselect_hash_sj_engine::setup() makes the
+--echo # decision.
+--echo #
+create table t1 (a varchar(3));
+create table t2 (a varchar(2));
+insert into t1 values('aaa'), ('aaa');
+insert into t2 values('aa'), ('aa');
+let $query=select * from t1 where a in (select a from t2);
+eval explain $query;
+flush status;
+eval $query;
+show status like "handler_read%";
+drop table t1,t2;
+
+--echo #
+--echo # Bug#13655791 DIFFERENT RESULT WITH WL6094 ON QUERY WITH XOR
+--echo # IN WHERE CLAUSE + MYISAM
+--echo #
+
+CREATE TABLE t1 (
+ pk int NOT NULL,
+ col_varchar_nokey varchar(1) DEFAULT NULL,
+ PRIMARY KEY (pk)
+);
+
+INSERT INTO t1 VALUES (10,'x');
+
+CREATE TABLE t2 (
+ pk int NOT NULL,
+ col_varchar_nokey varchar(1) DEFAULT NULL,
+ PRIMARY KEY (pk)
+);
+
+INSERT INTO t2 VALUES (1,'v'), (5,'x'), (11,'z'), (12,'c'), (15,'y');
+
+CREATE TABLE t3 (
+ pk int NOT NULL,
+ col_int_key int DEFAULT NULL,
+ PRIMARY KEY (pk),
+ KEY col_int_key (col_int_key)
+);
+
+INSERT INTO t3 VALUES (10,8);
+
+CREATE TABLE t4 (
+ pk int NOT NULL,
+ col_varchar_nokey varchar(1) DEFAULT NULL,
+ PRIMARY KEY (pk)
+);
+
+INSERT INTO t4 VALUES (1,'x');
+
+let $query=
+SELECT OUTR.pk, OUTR.col_varchar_nokey, OUTR2.col_varchar_nokey
+FROM t2 AS OUTR2
+ JOIN t4 AS OUTR
+ ON (OUTR2.col_varchar_nokey > OUTR.col_varchar_nokey)
+WHERE
+ OUTR.col_varchar_nokey IN (
+ SELECT INNR.col_varchar_nokey
+ FROM t3 AS INNR2
+ LEFT JOIN t1 AS INNR
+ ON (INNR2.col_int_key >= INNR.pk)
+ )
+ XOR OUTR.pk < 6
+;
+
+eval EXPLAIN $query;
+FLUSH STATUS;
+eval $query;
+SHOW STATUS LIKE "HANDLER_READ%";
+
+DROP TABLE t1,t2,t3,t4;
--echo # End of 5.6 tests
=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl 2012-01-31 16:18:20 +0000
+++ b/mysql-test/mysql-test-run.pl 2012-02-08 20:52:22 +0000
@@ -4865,6 +4865,14 @@ sub mysqld_arguments ($$$) {
mtr_add_arg($args, "--gdb");
}
+ # Enable the debug sync facility, set default wait timeout.
+ # Facility stays disabled if timeout value is zero.
+ mtr_add_arg($args, "--loose-debug-sync-timeout=%s",
+ $opt_debug_sync_timeout) unless $opt_user_args;
+
+ # Options specified in .opt files should be added last so they can
+ # override defaults above.
+
my $found_skip_core= 0;
foreach my $arg ( @$extra_opts )
{
@@ -4900,11 +4908,6 @@ sub mysqld_arguments ($$$) {
{
mtr_add_arg($args, "%s", "--core-file");
}
-
- # Enable the debug sync facility, set default wait timeout.
- # Facility stays disabled if timeout value is zero.
- mtr_add_arg($args, "--loose-debug-sync-timeout=%s",
- $opt_debug_sync_timeout) unless $opt_user_args;
return $args;
}
=== added file 'mysql-test/r/debug_sync2.result'
--- a/mysql-test/r/debug_sync2.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/debug_sync2.result 2012-02-08 20:52:22 +0000
@@ -0,0 +1,13 @@
+#
+# Bug#13688248 CRASH IN DIAGNOSTICS_AREA::SET_OK_STATUS WHEN USING DEBUG_SYNC
+#
+SET SESSION DEBUG_SYNC= 'RESET';
+CREATE TABLE t1 (pk INT, PRIMARY KEY(pk));
+SET SESSION sql_mode=TRADITIONAL;
+SET SESSION autocommit=1;
+INSERT INTO t1 VALUES(1);
+SET SESSION debug_sync='write_row_replace SIGNAL go_ahead1 WAIT_FOR comes_never ';
+REPLACE INTO t1 ( pk ) VALUES ( 1 );
+Warnings:
+Warning 1639 debug sync point wait timed out
+DROP TABLE t1;
=== modified file 'mysql-test/r/events_restart.result'
--- a/mysql-test/r/events_restart.result 2011-05-04 12:59:24 +0000
+++ b/mysql-test/r/events_restart.result 2012-02-09 14:56:44 +0000
@@ -65,3 +65,26 @@ select @@event_scheduler;
ON
drop table execution_log;
drop database events_test;
+#
+# Test for bug#11748899 -- EVENT SET TO DISABLED AND ON COMPLETION
+# NOT PRESERVE IS DELETED AT SERVER
+#
+SELECT @@event_scheduler;
+@@event_scheduler
+ON
+USE test;
+DROP EVENT IF EXISTS e1;
+CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO SELECT 1;
+SHOW EVENTS;
+Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
+test e1 root@localhost SYSTEM RECURRING # 1 SECOND # # DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
+"Now we restart the server"
+USE test;
+SELECT @@event_scheduler;
+@@event_scheduler
+ON
+SHOW EVENTS;
+Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
+test e1 root@localhost SYSTEM RECURRING # 1 SECOND # # DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
+DROP EVENT e1;
+# end test for bug#11748899
=== modified file 'mysql-test/r/heap.result'
--- a/mysql-test/r/heap.result 2011-09-27 12:17:43 +0000
+++ b/mysql-test/r/heap.result 2012-02-09 12:17:37 +0000
@@ -775,3 +775,17 @@ id select_type table type possible_keys
3 DERIVED t1 range PRIMARY PRIMARY 4 NULL 1 Using index condition; Using where
DROP TABLE t1,t2,h1;
DROP VIEW v1;
+CREATE TABLE t1 (
+c1 VARCHAR(10) NOT NULL,
+KEY i1 (c1(3))
+) ENGINE=MEMORY DEFAULT CHARSET=latin1;
+INSERT INTO t1 VALUES ('foo1'), ('bar2'), ('baz3');
+SELECT * FROM t1 WHERE c1='bar2';
+c1
+bar2
+#should show one tuple!
+SELECT * FROM t1 IGNORE INDEX (i1) WHERE c1='bar2';
+c1
+bar2
+#should show one tuple!
+DROP TABLE t1;
=== modified file 'mysql-test/r/index_merge_myisam.result'
--- a/mysql-test/r/index_merge_myisam.result 2012-01-30 13:13:15 +0000
+++ b/mysql-test/r/index_merge_myisam.result 2012-02-09 11:22:17 +0000
@@ -170,15 +170,21 @@ id select_type table type possible_keys
explain select * from t0 where
((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
or
-((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6));
+((key3 >5 or key5 < 2) and (key5 < 5 or key6 < 6));
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL i1,i2,i3,i5,i6 NULL NULL NULL 1024 Using where
explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where
((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
or
+((key3 >5 or key5 < 2) and (key5 < 5 or key6 < 6));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 4,4 NULL 1024 Using sort_union(i3,i5); Using where
+explain select * from t0 force index(i1, i2, i3, i4, i5, i6 ) where
+((key3 <5 or key5 < 4) and (key1 < 4 or key2 < 4))
+or
((key3 >=5 or key5 < 2) and (key5 < 5 or key6 < 6));
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t0 index_merge i1,i2,i3,i5,i6 i3,i5 0,4 NULL 1024 Using sort_union(i3,i5); Using where
+1 SIMPLE t0 ALL i1,i2,i3,i5,i6 NULL NULL NULL 1024 Using where
select * from t0 where key1 < 5 or key8 < 4 order by key1;
key1 key2 key3 key4 key5 key6 key7 key8
1 1 1 1 1 1 1 1023
=== modified file 'mysql-test/r/innodb_icp.result'
--- a/mysql-test/r/innodb_icp.result 2012-02-01 09:59:13 +0000
+++ b/mysql-test/r/innodb_icp.result 2012-02-08 15:25:17 +0000
@@ -794,6 +794,7 @@ PRIMARY KEY (pk),
KEY col_int_key (i1)
);
INSERT INTO t2 VALUES (1,7,'f');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT t1.i1
FROM t1
WHERE t1.i1 NOT IN
@@ -821,6 +822,7 @@ OR SUBQUERY_t2.c1 = 'a'
i1
NULL
133
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1,t2;
#
# Bug#11876420 "MISSING ROW IN RESULT WITH SUBQUERY + IN + XOR +
@@ -845,6 +847,7 @@ c1 VARCHAR(1),
KEY col_varchar_key (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL,'w'), (1,NULL), (2,'d');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT i1
FROM t3
WHERE c1 IN
@@ -870,6 +873,7 @@ XOR i1;
i1
1
2
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
#
# Bug#12355958 "FAILING ASSERTION: TRX->LOCK.N_ACTIVE_THRS == 1"
=== modified file 'mysql-test/r/innodb_icp_all.result'
--- a/mysql-test/r/innodb_icp_all.result 2012-02-01 09:59:13 +0000
+++ b/mysql-test/r/innodb_icp_all.result 2012-02-08 15:25:17 +0000
@@ -794,6 +794,7 @@ PRIMARY KEY (pk),
KEY col_int_key (i1)
);
INSERT INTO t2 VALUES (1,7,'f');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT t1.i1
FROM t1
WHERE t1.i1 NOT IN
@@ -821,6 +822,7 @@ OR SUBQUERY_t2.c1 = 'a'
i1
NULL
133
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1,t2;
#
# Bug#11876420 "MISSING ROW IN RESULT WITH SUBQUERY + IN + XOR +
@@ -845,6 +847,7 @@ c1 VARCHAR(1),
KEY col_varchar_key (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL,'w'), (1,NULL), (2,'d');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT i1
FROM t3
WHERE c1 IN
@@ -870,6 +873,7 @@ XOR i1;
i1
1
2
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
#
# Bug#12355958 "FAILING ASSERTION: TRX->LOCK.N_ACTIVE_THRS == 1"
=== modified file 'mysql-test/r/innodb_icp_none.result'
--- a/mysql-test/r/innodb_icp_none.result 2012-02-01 09:59:13 +0000
+++ b/mysql-test/r/innodb_icp_none.result 2012-02-08 15:25:17 +0000
@@ -793,6 +793,7 @@ PRIMARY KEY (pk),
KEY col_int_key (i1)
);
INSERT INTO t2 VALUES (1,7,'f');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT t1.i1
FROM t1
WHERE t1.i1 NOT IN
@@ -820,6 +821,7 @@ OR SUBQUERY_t2.c1 = 'a'
i1
NULL
133
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1,t2;
#
# Bug#11876420 "MISSING ROW IN RESULT WITH SUBQUERY + IN + XOR +
@@ -844,6 +846,7 @@ c1 VARCHAR(1),
KEY col_varchar_key (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL,'w'), (1,NULL), (2,'d');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT i1
FROM t3
WHERE c1 IN
@@ -869,6 +872,7 @@ XOR i1;
i1
1
2
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
#
# Bug#12355958 "FAILING ASSERTION: TRX->LOCK.N_ACTIVE_THRS == 1"
=== modified file 'mysql-test/r/join_cache_bka.result'
--- a/mysql-test/r/join_cache_bka.result 2012-01-30 13:13:15 +0000
+++ b/mysql-test/r/join_cache_bka.result 2012-02-08 15:25:17 +0000
@@ -2380,6 +2380,7 @@ c1 INTEGER,
KEY k1 (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL), (NULL);
+set @old_opt_switch=@@optimizer_switch;
explain SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
@@ -2411,9 +2412,9 @@ id select_type table type possible_keys
explain SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start materialize; Scan
-1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where; End materialize; Using join buffer (Block Nested Loop)
-1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start temporary
+1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where; Using join buffer (Block Nested Loop)
+1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index; End temporary
SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
XOR TRUE;
@@ -2433,6 +2434,7 @@ SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
c1
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
set @@join_buffer_size=default;
=== modified file 'mysql-test/r/join_cache_bka_nixbnl.result'
--- a/mysql-test/r/join_cache_bka_nixbnl.result 2012-01-30 13:13:15 +0000
+++ b/mysql-test/r/join_cache_bka_nixbnl.result 2012-02-08 15:25:17 +0000
@@ -2380,6 +2380,7 @@ c1 INTEGER,
KEY k1 (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL), (NULL);
+set @old_opt_switch=@@optimizer_switch;
explain SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
@@ -2411,9 +2412,9 @@ id select_type table type possible_keys
explain SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start materialize; Scan
-1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where; End materialize
-1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start temporary
+1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where
+1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index; End temporary
SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
XOR TRUE;
@@ -2433,6 +2434,7 @@ SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
c1
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
set @@join_buffer_size=default;
=== modified file 'mysql-test/r/join_cache_bkaunique.result'
--- a/mysql-test/r/join_cache_bkaunique.result 2012-01-30 13:13:15 +0000
+++ b/mysql-test/r/join_cache_bkaunique.result 2012-02-08 15:25:17 +0000
@@ -2381,6 +2381,7 @@ c1 INTEGER,
KEY k1 (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL), (NULL);
+set @old_opt_switch=@@optimizer_switch;
explain SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
@@ -2412,9 +2413,9 @@ id select_type table type possible_keys
explain SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start materialize; Scan
-1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where; End materialize; Using join buffer (Block Nested Loop)
-1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start temporary
+1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where; Using join buffer (Block Nested Loop)
+1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index; End temporary
SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
XOR TRUE;
@@ -2434,6 +2435,7 @@ SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
c1
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
set @@join_buffer_size=default;
=== modified file 'mysql-test/r/join_cache_bnl.result'
--- a/mysql-test/r/join_cache_bnl.result 2012-01-30 13:13:15 +0000
+++ b/mysql-test/r/join_cache_bnl.result 2012-02-08 15:25:17 +0000
@@ -2381,6 +2381,7 @@ c1 INTEGER,
KEY k1 (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL), (NULL);
+set @old_opt_switch=@@optimizer_switch;
explain SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
@@ -2412,9 +2413,9 @@ id select_type table type possible_keys
explain SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start materialize; Scan
-1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where; End materialize; Using join buffer (Block Nested Loop)
-1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start temporary
+1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where; Using join buffer (Block Nested Loop)
+1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index; End temporary
SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
XOR TRUE;
@@ -2434,6 +2435,7 @@ SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
c1
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
set @@join_buffer_size=default;
=== modified file 'mysql-test/r/join_cache_nojb.result'
--- a/mysql-test/r/join_cache_nojb.result 2012-02-01 09:59:13 +0000
+++ b/mysql-test/r/join_cache_nojb.result 2012-02-08 15:25:17 +0000
@@ -2381,6 +2381,7 @@ c1 INTEGER,
KEY k1 (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL), (NULL);
+set @old_opt_switch=@@optimizer_switch;
explain SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
@@ -2412,9 +2413,9 @@ id select_type table type possible_keys
explain SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start materialize; Scan
-1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where; End materialize
-1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index
+1 PRIMARY t2 index PRIMARY PRIMARY 4 NULL 1 Using index; Start temporary
+1 PRIMARY t1 ALL col_int_key NULL NULL NULL 1 Using where
+1 PRIMARY t3 ref k1 k1 5 test.t1.c2_key 1 Using index; End temporary
SELECT t3.c1 FROM t3
WHERE t3.c1 = SOME (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1)
XOR TRUE;
@@ -2434,6 +2435,7 @@ SELECT t3.c1 FROM t3
WHERE t3.c1 IN (SELECT t1.c2_key FROM t2 JOIN t1 ON t2.pk < t1.c1);
c1
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
set @@join_buffer_size=default;
=== modified file 'mysql-test/r/myisam_icp.result'
--- a/mysql-test/r/myisam_icp.result 2012-02-01 09:59:13 +0000
+++ b/mysql-test/r/myisam_icp.result 2012-02-08 15:25:17 +0000
@@ -792,6 +792,7 @@ PRIMARY KEY (pk),
KEY col_int_key (i1)
);
INSERT INTO t2 VALUES (1,7,'f');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT t1.i1
FROM t1
WHERE t1.i1 NOT IN
@@ -819,6 +820,7 @@ OR SUBQUERY_t2.c1 = 'a'
i1
NULL
133
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1,t2;
#
# Bug#11876420 "MISSING ROW IN RESULT WITH SUBQUERY + IN + XOR +
@@ -843,6 +845,7 @@ c1 VARCHAR(1),
KEY col_varchar_key (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL,'w'), (1,NULL), (2,'d');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT i1
FROM t3
WHERE c1 IN
@@ -867,6 +870,7 @@ XOR i1;
i1
1
2
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
#
# Bug#12355958 "FAILING ASSERTION: TRX->LOCK.N_ACTIVE_THRS == 1"
=== modified file 'mysql-test/r/myisam_icp_all.result'
--- a/mysql-test/r/myisam_icp_all.result 2012-02-01 09:59:13 +0000
+++ b/mysql-test/r/myisam_icp_all.result 2012-02-08 15:25:17 +0000
@@ -792,6 +792,7 @@ PRIMARY KEY (pk),
KEY col_int_key (i1)
);
INSERT INTO t2 VALUES (1,7,'f');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT t1.i1
FROM t1
WHERE t1.i1 NOT IN
@@ -819,6 +820,7 @@ OR SUBQUERY_t2.c1 = 'a'
i1
NULL
133
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1,t2;
#
# Bug#11876420 "MISSING ROW IN RESULT WITH SUBQUERY + IN + XOR +
@@ -843,6 +845,7 @@ c1 VARCHAR(1),
KEY col_varchar_key (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL,'w'), (1,NULL), (2,'d');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT i1
FROM t3
WHERE c1 IN
@@ -867,6 +870,7 @@ XOR i1;
i1
1
2
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
#
# Bug#12355958 "FAILING ASSERTION: TRX->LOCK.N_ACTIVE_THRS == 1"
=== modified file 'mysql-test/r/myisam_icp_none.result'
--- a/mysql-test/r/myisam_icp_none.result 2012-02-01 09:59:13 +0000
+++ b/mysql-test/r/myisam_icp_none.result 2012-02-08 15:25:17 +0000
@@ -791,6 +791,7 @@ PRIMARY KEY (pk),
KEY col_int_key (i1)
);
INSERT INTO t2 VALUES (1,7,'f');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT t1.i1
FROM t1
WHERE t1.i1 NOT IN
@@ -818,6 +819,7 @@ OR SUBQUERY_t2.c1 = 'a'
i1
NULL
133
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1,t2;
#
# Bug#11876420 "MISSING ROW IN RESULT WITH SUBQUERY + IN + XOR +
@@ -842,6 +844,7 @@ c1 VARCHAR(1),
KEY col_varchar_key (c1)
) ENGINE=InnoDB;
INSERT INTO t3 VALUES (NULL,'w'), (1,NULL), (2,'d');
+set @old_opt_switch=@@optimizer_switch;
EXPLAIN SELECT i1
FROM t3
WHERE c1 IN
@@ -866,6 +869,7 @@ XOR i1;
i1
1
2
+set @@optimizer_switch=@old_opt_switch;
DROP TABLE t1, t2, t3;
#
# Bug#12355958 "FAILING ASSERTION: TRX->LOCK.N_ACTIVE_THRS == 1"
=== modified file 'mysql-test/r/read_only.result'
--- a/mysql-test/r/read_only.result 2010-08-30 06:38:09 +0000
+++ b/mysql-test/r/read_only.result 2012-02-09 12:57:42 +0000
@@ -75,18 +75,16 @@ connection default;
set global read_only=1;
ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
unlock tables ;
-send set global read_only=1;
set global read_only=1;
-connection con1;
select @@global.read_only;
@@global.read_only
-0
-unlock tables ;
+1
+connection con1;
select @@global.read_only;
@@global.read_only
1
+unlock tables ;
connection default;
-reap;
connection default;
set global read_only=0;
BEGIN;
=== modified file 'mysql-test/r/subquery_all.result'
--- a/mysql-test/r/subquery_all.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_all.result 2012-02-08 15:25:17 +0000
@@ -890,9 +890,9 @@ a t1.a in (select t2.a from t2)
explain extended SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
+2 SUBQUERY t2 index NULL a 5 NULL 3 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -904,10 +904,10 @@ a t1.a in (select t2.a from t2,t3 where
explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
-2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t2 index a a 5 NULL 3 100.00 Using index
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (Block Nested Loop)
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where (`test`.`t3`.`a` = `test`.`t2`.`a`) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
create table t1 (a float);
select 10.5 IN (SELECT * from t1 LIMIT 1);
@@ -1368,27 +1368,27 @@ a3 1
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
+2 SUBQUERY t2 index s1 s1 6 NULL 2 50.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < 'a2') having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` where (`test`.`t2`.`s1` < 'a2') ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int);
create table t3 (a int);
@@ -1641,9 +1641,9 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 SUBQUERY t1 range PRIMARY PRIMARY 4 NULL 7 100.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where ((`test`.`t1`.`id` < 8) and (<cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))))))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`id`,`test`.`t1`.`id` in ( <materialize> (/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where (`test`.`t1`.`id` < 8) ), <primary_index_lookup>(`test`.`t1`.`id` in <temporary table> on distinct_key where ((`test`.`t1`.`id` = `materialized subselect`.`id`)))))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
@@ -2829,7 +2829,7 @@ INSERT INTO t2 VALUES (1),(2),(3);
EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
-2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index; Full scan on NULL key
+2 SUBQUERY t1 index NULL a 5 NULL 5 Using index
SELECT a, a IN (SELECT a FROM t1) FROM t2;
a a IN (SELECT a FROM t1)
1 1
@@ -4180,14 +4180,14 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
ORDER BY outr.pk;
id select_type table type possible_keys key key_len ref rows Extra
x x outr ALL x x x x x x
-x x t1 eq_ref x x x x x x
+x x t1 index x x x x x x
x x t2 index x x x x x x
# should not crash on debug binaries
SELECT * FROM t2 outr
@@ -4264,9 +4264,9 @@ Z
explain extended select a in (select max(ie) from t1 where oref=4 group by grp) from t3;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary; Using filesort
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 /* select#1 */ select <in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where (`test`.`t1`.`oref` = 4) group by `test`.`t1`.`grp` having trigcond_if(outer_field_is_not_null, (<cache>(`test`.`t3`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`))), true))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
+Note 1003 /* select#1 */ select <in_optimizer>(`test`.`t3`.`a`,`test`.`t3`.`a` in ( <materialize> (/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where (`test`.`t1`.`oref` = 4) group by `test`.`t1`.`grp` ), <primary_index_lookup>(`test`.`t3`.`a` in <temporary table> on distinct_key where ((`test`.`t3`.`a` = `materialized subselect`.`max(ie)`))))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
drop table t1, t2, t3;
create table t1 (a int, oref int, key(a));
insert into t1 values
@@ -4900,9 +4900,9 @@ SELECT a FROM t1, t2 WHERE a=b AND (b NO
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 100.00 Using index
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (not(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t1` where ((<cache>(`test`.`t2`.`b`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`)) having <is_not_null_test>(`test`.`t1`.`a`))))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (not(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))))))
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1));
a
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1 WHERE a > 4));
@@ -4922,8 +4922,8 @@ WHERE t1.id NOT IN (SELECT t2.id FROM t2
WHERE t3.name='xxx' AND t2.id=t3.id);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY PRIMARY 4 func 1 Using where; Using index; Full scan on NULL key
-2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 func 1 Using where; Full scan on NULL key
+2 SUBQUERY t2 index PRIMARY PRIMARY 4 NULL 3 Using index
+2 SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t2.id 1 Using where
SELECT * FROM t1
WHERE t1.id NOT IN (SELECT t2.id FROM t2,t3
WHERE t3.name='xxx' AND t2.id=t3.id);
@@ -4956,7 +4956,7 @@ a
EXPLAIN SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
+2 SUBQUERY t2 index NULL PRIMARY 4 NULL 2 Using index
DROP TABLE t1, t2;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES(1);
@@ -6280,8 +6280,8 @@ INSERT INTO t2 VALUES (1), (2);
EXPLAIN
SELECT i FROM t1 WHERE (1) NOT IN (SELECT i FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY t2 index_subquery k k 5 const 2 Using index
+1 PRIMARY t1 system NULL NULL NULL NULL 1
+2 SUBQUERY t2 index NULL k 5 NULL 2 Using index
DROP TABLE t2;
DROP TABLE t1;
#
@@ -7045,7 +7045,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY,col_varchar_key NULL NULL NULL 1
+2 UNCACHEABLE SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
SELECT sq4_alias1.*
FROM t1 AS sq4_alias1
WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
@@ -7068,7 +7068,7 @@ OR c_sq1_alias1.pk != @var3)) ) AS alias
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
-3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY,col_varchar_key NULL NULL NULL 1
+3 UNCACHEABLE SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
SELECT * FROM ( SELECT sq4_alias1.*
FROM t1 AS sq4_alias1
WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
@@ -7080,4 +7080,31 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_all_bka.result'
--- a/mysql-test/r/subquery_all_bka.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_all_bka.result 2012-02-08 15:25:17 +0000
@@ -891,9 +891,9 @@ a t1.a in (select t2.a from t2)
explain extended SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
+2 SUBQUERY t2 index NULL a 5 NULL 3 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -905,10 +905,10 @@ a t1.a in (select t2.a from t2,t3 where
explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
-2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t2 index a a 5 NULL 3 100.00 Using index
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (Block Nested Loop)
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where (`test`.`t3`.`a` = `test`.`t2`.`a`) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
create table t1 (a float);
select 10.5 IN (SELECT * from t1 LIMIT 1);
@@ -1369,27 +1369,27 @@ a3 1
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
+2 SUBQUERY t2 index s1 s1 6 NULL 2 50.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < 'a2') having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` where (`test`.`t2`.`s1` < 'a2') ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int);
create table t3 (a int);
@@ -1642,9 +1642,9 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 SUBQUERY t1 range PRIMARY PRIMARY 4 NULL 7 100.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where ((`test`.`t1`.`id` < 8) and (<cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))))))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`id`,`test`.`t1`.`id` in ( <materialize> (/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where (`test`.`t1`.`id` < 8) ), <primary_index_lookup>(`test`.`t1`.`id` in <temporary table> on distinct_key where ((`test`.`t1`.`id` = `materialized subselect`.`id`)))))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
@@ -2830,7 +2830,7 @@ INSERT INTO t2 VALUES (1),(2),(3);
EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
-2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index; Full scan on NULL key
+2 SUBQUERY t1 index NULL a 5 NULL 5 Using index
SELECT a, a IN (SELECT a FROM t1) FROM t2;
a a IN (SELECT a FROM t1)
1 1
@@ -4181,14 +4181,14 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
ORDER BY outr.pk;
id select_type table type possible_keys key key_len ref rows Extra
x x outr ALL x x x x x x
-x x t1 eq_ref x x x x x x
+x x t1 index x x x x x x
x x t2 index x x x x x x
# should not crash on debug binaries
SELECT * FROM t2 outr
@@ -4265,9 +4265,9 @@ Z
explain extended select a in (select max(ie) from t1 where oref=4 group by grp) from t3;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary; Using filesort
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 /* select#1 */ select <in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where (`test`.`t1`.`oref` = 4) group by `test`.`t1`.`grp` having trigcond_if(outer_field_is_not_null, (<cache>(`test`.`t3`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`))), true))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
+Note 1003 /* select#1 */ select <in_optimizer>(`test`.`t3`.`a`,`test`.`t3`.`a` in ( <materialize> (/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where (`test`.`t1`.`oref` = 4) group by `test`.`t1`.`grp` ), <primary_index_lookup>(`test`.`t3`.`a` in <temporary table> on distinct_key where ((`test`.`t3`.`a` = `materialized subselect`.`max(ie)`))))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
drop table t1, t2, t3;
create table t1 (a int, oref int, key(a));
insert into t1 values
@@ -4901,9 +4901,9 @@ SELECT a FROM t1, t2 WHERE a=b AND (b NO
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 100.00 Using index
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (not(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t1` where ((<cache>(`test`.`t2`.`b`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`)) having <is_not_null_test>(`test`.`t1`.`a`))))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (not(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))))))
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1));
a
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1 WHERE a > 4));
@@ -4923,8 +4923,8 @@ WHERE t1.id NOT IN (SELECT t2.id FROM t2
WHERE t3.name='xxx' AND t2.id=t3.id);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY PRIMARY 4 func 1 Using where; Using index; Full scan on NULL key
-2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 func 1 Using where; Full scan on NULL key
+2 SUBQUERY t2 index PRIMARY PRIMARY 4 NULL 3 Using index
+2 SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t2.id 1 Using where; Using join buffer (Batched Key Access)
SELECT * FROM t1
WHERE t1.id NOT IN (SELECT t2.id FROM t2,t3
WHERE t3.name='xxx' AND t2.id=t3.id);
@@ -4957,7 +4957,7 @@ a
EXPLAIN SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
+2 SUBQUERY t2 index NULL PRIMARY 4 NULL 2 Using index
DROP TABLE t1, t2;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES(1);
@@ -6281,8 +6281,8 @@ INSERT INTO t2 VALUES (1), (2);
EXPLAIN
SELECT i FROM t1 WHERE (1) NOT IN (SELECT i FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY t2 index_subquery k k 5 const 2 Using index
+1 PRIMARY t1 system NULL NULL NULL NULL 1
+2 SUBQUERY t2 index NULL k 5 NULL 2 Using index
DROP TABLE t2;
DROP TABLE t1;
#
@@ -7046,7 +7046,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY,col_varchar_key NULL NULL NULL 1
+2 UNCACHEABLE SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
SELECT sq4_alias1.*
FROM t1 AS sq4_alias1
WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
@@ -7069,7 +7069,7 @@ OR c_sq1_alias1.pk != @var3)) ) AS alias
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
-3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY,col_varchar_key NULL NULL NULL 1
+3 UNCACHEABLE SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
SELECT * FROM ( SELECT sq4_alias1.*
FROM t1 AS sq4_alias1
WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
@@ -7081,5 +7081,32 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where; Using join buffer (Batched Key Access)
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 2
+Handler_read_prev 0
+Handler_read_rnd 2
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_all_bka_nixbnl.result'
--- a/mysql-test/r/subquery_all_bka_nixbnl.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_all_bka_nixbnl.result 2012-02-08 15:25:17 +0000
@@ -891,9 +891,9 @@ a t1.a in (select t2.a from t2)
explain extended SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery a a 5 func 2 100.00 Using index
+2 SUBQUERY t2 index NULL a 5 NULL 3 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`a`) in t2 on a checking NULL having <is_not_null_test>(`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `t1.a in (select t2.a from t2)` from `test`.`t1`
CREATE TABLE t3 (a int(11) default '0');
INSERT INTO t3 VALUES (1),(2),(3);
SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -905,10 +905,10 @@ a t1.a in (select t2.a from t2,t3 where
explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 100.00 Using index
-2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 100.00 Using where; Using index
-2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 SUBQUERY t2 ref a a 5 test.t3.a 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having <is_not_null_test>(`test`.`t2`.`a`))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` join `test`.`t3` where (`test`.`t2`.`a` = `test`.`t3`.`a`) ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1`
drop table t1,t2,t3;
create table t1 (a float);
select 10.5 IN (SELECT * from t1 LIMIT 1);
@@ -1369,27 +1369,27 @@ a3 1
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Full scan on NULL key
+2 SUBQUERY t2 index NULL s1 6 NULL 2 100.00 Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL s1 6 NULL 3 100.00 Using index
-2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 100.00 Using index; Using where; Full scan on NULL key
+2 SUBQUERY t2 index s1 s1 6 NULL 2 50.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < 'a2') having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`s1`), true)))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
+Note 1003 /* select#1 */ select `test`.`t1`.`s1` AS `s1`,(not(<in_optimizer>(`test`.`t1`.`s1`,`test`.`t1`.`s1` in ( <materialize> (/* select#2 */ select `test`.`t2`.`s1` from `test`.`t2` where (`test`.`t2`.`s1` < 'a2') ), <primary_index_lookup>(`test`.`t1`.`s1` in <temporary table> on distinct_key where ((`test`.`t1`.`s1` = `materialized subselect`.`s1`))))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
drop table t1,t2;
create table t2 (a int, b int);
create table t3 (a int);
@@ -1642,9 +1642,9 @@ id text
explain extended select * from t1 where id not in (select id from t1 where id < 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00 Using where
-2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 100.00 Using index; Using where
+2 SUBQUERY t1 range PRIMARY PRIMARY 4 NULL 7 100.00 Using where; Using index
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`id`,<exists>(<primary_index_lookup>(<cache>(`test`.`t1`.`id`) in t1 on PRIMARY where ((`test`.`t1`.`id` < 8) and (<cache>(`test`.`t1`.`id`) = `test`.`t1`.`id`)))))))
+Note 1003 /* select#1 */ select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`id`,`test`.`t1`.`id` in ( <materialize> (/* select#2 */ select `test`.`t1`.`id` from `test`.`t1` where (`test`.`t1`.`id` < 8) ), <primary_index_lookup>(`test`.`t1`.`id` in <temporary table> on distinct_key where ((`test`.`t1`.`id` = `materialized subselect`.`id`)))))))
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 12 100.00 Using where
@@ -2830,7 +2830,7 @@ INSERT INTO t2 VALUES (1),(2),(3);
EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
-2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index; Full scan on NULL key
+2 SUBQUERY t1 index NULL a 5 NULL 5 Using index
SELECT a, a IN (SELECT a FROM t1) FROM t2;
a a IN (SELECT a FROM t1)
1 1
@@ -4181,14 +4181,14 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
ORDER BY outr.pk;
id select_type table type possible_keys key key_len ref rows Extra
x x outr ALL x x x x x x
-x x t1 eq_ref x x x x x x
+x x t1 index x x x x x x
x x t2 index x x x x x x
# should not crash on debug binaries
SELECT * FROM t2 outr
@@ -4265,9 +4265,9 @@ Z
explain extended select a in (select max(ie) from t1 where oref=4 group by grp) from t3;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary; Using filesort
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using temporary; Using filesort
Warnings:
-Note 1003 /* select#1 */ select <in_optimizer>(`test`.`t3`.`a`,<exists>(/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where (`test`.`t1`.`oref` = 4) group by `test`.`t1`.`grp` having trigcond_if(outer_field_is_not_null, (<cache>(`test`.`t3`.`a`) = <ref_null_helper>(max(`test`.`t1`.`ie`))), true))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
+Note 1003 /* select#1 */ select <in_optimizer>(`test`.`t3`.`a`,`test`.`t3`.`a` in ( <materialize> (/* select#2 */ select max(`test`.`t1`.`ie`) from `test`.`t1` where (`test`.`t1`.`oref` = 4) group by `test`.`t1`.`grp` ), <primary_index_lookup>(`test`.`t3`.`a` in <temporary table> on distinct_key where ((`test`.`t3`.`a` = `materialized subselect`.`max(ie)`))))) AS `a in (select max(ie) from t1 where oref=4 group by grp)` from `test`.`t3`
drop table t1, t2, t3;
create table t1 (a int, oref int, key(a));
insert into t1 values
@@ -4901,9 +4901,9 @@ SELECT a FROM t1, t2 WHERE a=b AND (b NO
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 100.00 Using index
-2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (not(<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t1` where ((<cache>(`test`.`t2`.`b`) = `test`.`t1`.`a`) or isnull(`test`.`t1`.`a`)) having <is_not_null_test>(`test`.`t1`.`a`))))))
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (not(<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t1`.`a` from `test`.`t1` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))))))
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1));
a
SELECT a FROM t1, t2 WHERE a=b AND (b NOT IN (SELECT a FROM t1 WHERE a > 4));
@@ -4923,8 +4923,8 @@ WHERE t1.id NOT IN (SELECT t2.id FROM t2
WHERE t3.name='xxx' AND t2.id=t3.id);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY t2 eq_ref PRIMARY PRIMARY 4 func 1 Using where; Using index; Full scan on NULL key
-2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 func 1 Using where; Full scan on NULL key
+2 SUBQUERY t2 index PRIMARY PRIMARY 4 NULL 3 Using index
+2 SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t2.id 1 Using where; Using join buffer (Batched Key Access)
SELECT * FROM t1
WHERE t1.id NOT IN (SELECT t2.id FROM t2,t3
WHERE t3.name='xxx' AND t2.id=t3.id);
@@ -4957,7 +4957,7 @@ a
EXPLAIN SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
-2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where
+2 SUBQUERY t2 index NULL PRIMARY 4 NULL 2 Using index
DROP TABLE t1, t2;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES(1);
@@ -6281,8 +6281,8 @@ INSERT INTO t2 VALUES (1), (2);
EXPLAIN
SELECT i FROM t1 WHERE (1) NOT IN (SELECT i FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY t2 index_subquery k k 5 const 2 Using index
+1 PRIMARY t1 system NULL NULL NULL NULL 1
+2 SUBQUERY t2 index NULL k 5 NULL 2 Using index
DROP TABLE t2;
DROP TABLE t1;
#
@@ -7046,7 +7046,7 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY,col_varchar_key NULL NULL NULL 1
+2 UNCACHEABLE SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
SELECT sq4_alias1.*
FROM t1 AS sq4_alias1
WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
@@ -7069,7 +7069,7 @@ OR c_sq1_alias1.pk != @var3)) ) AS alias
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
-3 DEPENDENT SUBQUERY c_sq1_alias1 system PRIMARY,col_varchar_key NULL NULL NULL 1
+3 UNCACHEABLE SUBQUERY c_sq1_alias1 system PRIMARY NULL NULL NULL 1
SELECT * FROM ( SELECT sq4_alias1.*
FROM t1 AS sq4_alias1
WHERE (sq4_alias1.col_varchar_key , sq4_alias1.col_varchar_nokey)
@@ -7081,5 +7081,32 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where; Using join buffer (Batched Key Access)
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 2
+Handler_read_prev 0
+Handler_read_rnd 2
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_mat.result'
--- a/mysql-test/r/subquery_mat.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_mat.result 2012-02-08 15:25:17 +0000
@@ -1294,5 +1294,485 @@ pk pk
1 NULL
DROP TABLE t1, t2;
# End of test for bug#13607423.
+
+Test of WL#6094 "Allow subquery materialization in NOT IN if all
+columns are not nullable"
+
+create table t1(a int not null);
+create table t2(a int not null);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+Test in SELECT list
+
+cols not nullable => subq materialization
+explain extended select a, (a,a) in (select a,a from t2) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),(`test`.`t1`.`a`,`test`.`t1`.`a`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`a`,`test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`) and (`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `(a,a) in (select a,a from t2)` from `test`.`t1`
+select a, (a,a) in (select a,a from t2) from t1;
+a (a,a) in (select a,a from t2)
+1 1
+2 1
+
+cols not nullable => subq materialization
+explain extended select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),(`test`.`t1`.`a`,`test`.`t1`.`a`) in ( <materialize> (/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`) and (`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `(t1.a,t1.a) in (select a,a from t2 as t3)` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)
+select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+a a (t1.a,t1.a) in (select a,a from t2 as t3)
+
+t2.a is not nullable, but in the query it may appear as NULL
+as it's in an outer join. So, no materialization.
+explain extended select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or <cache>(isnull(`test`.`t3`.`a`))), true) and trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or <cache>(isnull(`test`.`t3`.`a`))), true)) having (trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true) and trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true)))) AS `(t2.a,t2.a) in (select a,a from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a (t2.a,t2.a) in (select a,a from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+
+alter table t2 modify a int;
+two nullable inner cols => no subq materialization
+explain extended select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (((<cache>(`test`.`t1`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)) and ((<cache>(`test`.`t1`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`))) having (<is_not_null_test>(`test`.`t3`.`a`) and <is_not_null_test>(`test`.`t3`.`a`)))) AS `(t1.a,t1.a) in (select a,a from t2 as t3)` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)
+select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+a a (t1.a,t1.a) in (select a,a from t2 as t3)
+alter table t2 modify a int not null;
+
+Test in WHERE
+
+top-level => subq materialization. With one exception: if
+semijoin is enabled in @@optimizer_switch, semijoin is chosen,
+then rejected (due to outer join), and in that case, the
+fallback is IN->EXISTS, subq-materialization is not tried...
+explain extended select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) in (select a,a from t2 as t3);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where (<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),(`test`.`t2`.`a`,`test`.`t2`.`a`) in ( <materialize> (/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`) and (`test`.`t2`.`a` = `materialized subselect`.`a`))))) and ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 3))
+select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) in (select a,a from t2 as t3);
+a a
+2 1
+1 2
+
+cols not nullable => subq materialization
+explain extended select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) not in (select a,a from t2 as t3);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((not(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),(`test`.`t2`.`a`,`test`.`t2`.`a`) in ( <materialize> (/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`) and (`test`.`t2`.`a` = `materialized subselect`.`a`))))))) and ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 3))
+select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) not in (select a,a from t2 as t3);
+a a
+drop table t1,t2;
+
+Test of WL6095 "Allow subquery materialization in NOT IN if
+single-column subquery"
+
+create table t1(a int null);
+create table t2(a int null);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+
+one col => subq materialization
+explain extended select a, a in (select a from t2) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `a in (select a from t2)` from `test`.`t1`
+select a, a in (select a from t2) from t1;
+a a in (select a from t2)
+1 1
+2 1
+
+t2.a is not nullable, but in the query it may appear as NULL
+as it's in an outer join. But there is only one inner column so
+materialization is possible
+explain extended select t1.a, t2.a, t2.a in (select * from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (/* select#2 */ select `test`.`t3`.`a` from `test`.`t2` `t3` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`))))) AS `t2.a in (select * from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, t2.a in (select * from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a t2.a in (select * from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+
+_two_ outer columns, nullable => no materialization
+explain extended select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)), true) and trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)), true)) having (trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true) and trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true)))) AS `(t2.a,t2.a) in (select a,a from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a (t2.a,t2.a) in (select a,a from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+drop table t1,t2;
+
+Test in HAVING
+create table t1(a int, b int);
+create table t2(a int);
+insert into t1 values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3);
+insert into t2 values(10),(20);
+no NULLs.
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,`z` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`z` in <temporary table> on distinct_key where ((`z` = `materialized subselect`.`a`))))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+one outer NULL
+insert into t1 values(null,null);
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using temporary; Using filesort
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,`z` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`z` in <temporary table> on distinct_key where ((`z` = `materialized subselect`.`a`))))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+NULL NULL
+one outer NULL and one inner NULL
+insert into t2 values(null);
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using temporary; Using filesort
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,`z` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`z` in <temporary table> on distinct_key where ((`z` = `materialized subselect`.`a`))))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+NULL NULL
+1 6
+2 6
+one inner NULL
+delete from t1 where a is null;
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,`z` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`z` in <temporary table> on distinct_key where ((`z` = `materialized subselect`.`a`))))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+1 6
+2 6
+drop table t1,t2;
+
+Verify that an inner NULL is looked up only once (result is
+cached).
+create table t1(a int);
+create table t2(a int);
+insert into t1 values(1),(2),(3),(4),(5),(6);
+insert into t1 select * from t1;
+insert into t2 values(10),(20),(NULL);
+explain extended select a, (a in (select * from t2)) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `(a in (select * from t2))` from `test`.`t1`
+flush status;
+select a, (a in (select * from t2)) from t1;
+a (a in (select * from t2))
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+6 NULL
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+6 NULL
+There will be one look-up in the temporary table for each row
+of t1 (12), plus one additional look-up to check whether table
+contains a NULL value.
+show status like "handler_read_key";
+Variable_name Value
+Handler_read_key 13
+drop table t1,t2;
+#
+# Bug#13495157 - SUBQUERY MATERIALIZATION NOT USED FOR CERTAIN
+# STATEMENTS
+#
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1),(2),(3);
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES(1),(2),(4);
+# subquery materialization used for SELECT:
+EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+a
+1
+# Also used for INSERT SELECT:
+CREATE TABLE t3 SELECT * FROM t1;
+EXPLAIN INSERT INTO t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+INSERT INTO t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t3;
+a
+1
+1
+2
+3
+EXPLAIN INSERT INTO t2 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using temporary
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+INSERT INTO t2 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+2
+4
+EXPLAIN INSERT INTO t2 SELECT * FROM t2 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where
+INSERT INTO t2 SELECT * FROM t2 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+1
+1
+2
+4
+4
+# Not used for single-table UPDATE, DELETE:
+EXPLAIN SELECT * FROM t2 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3
+EXPLAIN UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t1);
+SELECT * FROM t2;
+a
+0
+0
+0
+0
+1
+4
+4
+EXPLAIN DELETE FROM t2 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+DELETE FROM t2 WHERE a IN (SELECT * FROM t1);
+SELECT * FROM t2;
+a
+0
+0
+0
+0
+4
+4
+EXPLAIN UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+EXPLAIN DELETE FROM t2 WHERE a IN (SELECT * FROM t2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+UPDATE t2 SET a=3 WHERE a=0;
+# Used for multi-table UPDATE, DELETE:
+EXPLAIN SELECT * FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+EXPLAIN UPDATE t2,t3 SET t2.a=t2.a-2 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+UPDATE t2,t3 SET t2.a=t2.a-2 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+1
+1
+4
+4
+EXPLAIN DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+SELECT * FROM t2;
+a
+4
+4
+EXPLAIN UPDATE t2,t3 SET t2.a=10 WHERE t2.a IN (SELECT * FROM t2 WHERE a <> 2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+EXPLAIN DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t2 WHERE a <> 2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+DROP TABLE t1,t2,t3;
+#
+# Test that subquery materialization only does one lookup: does
+# not try to read the next row if the first row failed the
+# subquery's WHERE. We use a case where index lookup is not
+# enough to satisfy IN(), because index has length two when the
+# outer value has length three, and thus the post-filtering
+# WHERE added by subselect_hash_sj_engine::setup() makes the
+# decision.
+#
+create table t1 (a varchar(3));
+create table t2 (a varchar(2));
+insert into t1 values('aaa'), ('aaa');
+insert into t2 values('aa'), ('aa');
+explain select * from t1 where a in (select a from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2
+flush status;
+select * from t1 where a in (select a from t2);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 1
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 6
+drop table t1,t2;
+#
+# Bug#13655791 DIFFERENT RESULT WITH WL6094 ON QUERY WITH XOR
+# IN WHERE CLAUSE + MYISAM
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t1 VALUES (10,'x');
+CREATE TABLE t2 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t2 VALUES (1,'v'), (5,'x'), (11,'z'), (12,'c'), (15,'y');
+CREATE TABLE t3 (
+pk int NOT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key)
+);
+INSERT INTO t3 VALUES (10,8);
+CREATE TABLE t4 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t4 VALUES (1,'x');
+EXPLAIN SELECT OUTR.pk, OUTR.col_varchar_nokey, OUTR2.col_varchar_nokey
+FROM t2 AS OUTR2
+JOIN t4 AS OUTR
+ON (OUTR2.col_varchar_nokey > OUTR.col_varchar_nokey)
+WHERE
+OUTR.col_varchar_nokey IN (
+SELECT INNR.col_varchar_nokey
+FROM t3 AS INNR2
+LEFT JOIN t1 AS INNR
+ON (INNR2.col_int_key >= INNR.pk)
+)
+XOR OUTR.pk < 6
+;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY OUTR system NULL NULL NULL NULL 1
+1 PRIMARY OUTR2 ALL NULL NULL NULL NULL 5 Using where
+2 SUBQUERY INNR2 system NULL NULL NULL NULL 1
+2 SUBQUERY INNR system PRIMARY NULL NULL NULL 1
+FLUSH STATUS;
+SELECT OUTR.pk, OUTR.col_varchar_nokey, OUTR2.col_varchar_nokey
+FROM t2 AS OUTR2
+JOIN t4 AS OUTR
+ON (OUTR2.col_varchar_nokey > OUTR.col_varchar_nokey)
+WHERE
+OUTR.col_varchar_nokey IN (
+SELECT INNR.col_varchar_nokey
+FROM t3 AS INNR2
+LEFT JOIN t1 AS INNR
+ON (INNR2.col_int_key >= INNR.pk)
+)
+XOR OUTR.pk < 6
+;
+pk col_varchar_nokey col_varchar_nokey
+SHOW STATUS LIKE "HANDLER_READ%";
+Variable_name Value
+Handler_read_first 3
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 9
+DROP TABLE t1,t2,t3,t4;
# End of 5.6 tests
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_mat_all.result'
--- a/mysql-test/r/subquery_mat_all.result 2012-01-20 15:30:14 +0000
+++ b/mysql-test/r/subquery_mat_all.result 2012-02-08 15:25:17 +0000
@@ -1293,5 +1293,485 @@ pk pk
1 NULL
DROP TABLE t1, t2;
# End of test for bug#13607423.
+
+Test of WL#6094 "Allow subquery materialization in NOT IN if all
+columns are not nullable"
+
+create table t1(a int not null);
+create table t2(a int not null);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+Test in SELECT list
+
+cols not nullable => subq materialization
+explain extended select a, (a,a) in (select a,a from t2) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),(`test`.`t1`.`a`,`test`.`t1`.`a`) in ( <materialize> (/* select#2 */ select `test`.`t2`.`a`,`test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`) and (`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `(a,a) in (select a,a from t2)` from `test`.`t1`
+select a, (a,a) in (select a,a from t2) from t1;
+a (a,a) in (select a,a from t2)
+1 1
+2 1
+
+cols not nullable => subq materialization
+explain extended select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),(`test`.`t1`.`a`,`test`.`t1`.`a`) in ( <materialize> (/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`) and (`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `(t1.a,t1.a) in (select a,a from t2 as t3)` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)
+select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+a a (t1.a,t1.a) in (select a,a from t2 as t3)
+
+t2.a is not nullable, but in the query it may appear as NULL
+as it's in an outer join. So, no materialization.
+explain extended select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or <cache>(isnull(`test`.`t3`.`a`))), true) and trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or <cache>(isnull(`test`.`t3`.`a`))), true)) having (trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true) and trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true)))) AS `(t2.a,t2.a) in (select a,a from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a (t2.a,t2.a) in (select a,a from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+
+alter table t2 modify a int;
+two nullable inner cols => no subq materialization
+explain extended select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (((<cache>(`test`.`t1`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)) and ((<cache>(`test`.`t1`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`))) having (<is_not_null_test>(`test`.`t3`.`a`) and <is_not_null_test>(`test`.`t3`.`a`)))) AS `(t1.a,t1.a) in (select a,a from t2 as t3)` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)
+select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+a a (t1.a,t1.a) in (select a,a from t2 as t3)
+alter table t2 modify a int not null;
+
+Test in WHERE
+
+top-level => subq materialization. With one exception: if
+semijoin is enabled in @@optimizer_switch, semijoin is chosen,
+then rejected (due to outer join), and in that case, the
+fallback is IN->EXISTS, subq-materialization is not tried...
+explain extended select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) in (select a,a from t2 as t3);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where (<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) and (<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`)))) and ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 3))
+select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) in (select a,a from t2 as t3);
+a a
+2 1
+1 2
+
+cols not nullable => subq materialization
+explain extended select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) not in (select a,a from t2 as t3);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((not(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),(`test`.`t2`.`a`,`test`.`t2`.`a`) in ( <materialize> (/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`) and (`test`.`t2`.`a` = `materialized subselect`.`a`))))))) and ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 3))
+select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) not in (select a,a from t2 as t3);
+a a
+drop table t1,t2;
+
+Test of WL6095 "Allow subquery materialization in NOT IN if
+single-column subquery"
+
+create table t1(a int null);
+create table t2(a int null);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+
+one col => subq materialization
+explain extended select a, a in (select a from t2) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `a in (select a from t2)` from `test`.`t1`
+select a, a in (select a from t2) from t1;
+a a in (select a from t2)
+1 1
+2 1
+
+t2.a is not nullable, but in the query it may appear as NULL
+as it's in an outer join. But there is only one inner column so
+materialization is possible
+explain extended select t1.a, t2.a, t2.a in (select * from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>(`test`.`t2`.`a`,`test`.`t2`.`a` in ( <materialize> (/* select#2 */ select `test`.`t3`.`a` from `test`.`t2` `t3` ), <primary_index_lookup>(`test`.`t2`.`a` in <temporary table> on distinct_key where ((`test`.`t2`.`a` = `materialized subselect`.`a`))))) AS `t2.a in (select * from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, t2.a in (select * from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a t2.a in (select * from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+
+_two_ outer columns, nullable => no materialization
+explain extended select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)), true) and trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)), true)) having (trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true) and trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true)))) AS `(t2.a,t2.a) in (select a,a from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a (t2.a,t2.a) in (select a,a from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+drop table t1,t2;
+
+Test in HAVING
+create table t1(a int, b int);
+create table t2(a int);
+insert into t1 values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3);
+insert into t2 values(10),(20);
+no NULLs.
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,`z` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`z` in <temporary table> on distinct_key where ((`z` = `materialized subselect`.`a`))))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+one outer NULL
+insert into t1 values(null,null);
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using temporary; Using filesort
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,`z` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`z` in <temporary table> on distinct_key where ((`z` = `materialized subselect`.`a`))))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+NULL NULL
+one outer NULL and one inner NULL
+insert into t2 values(null);
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using temporary; Using filesort
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,`z` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`z` in <temporary table> on distinct_key where ((`z` = `materialized subselect`.`a`))))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+NULL NULL
+1 6
+2 6
+one inner NULL
+delete from t1 where a is null;
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,`z` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`z` in <temporary table> on distinct_key where ((`z` = `materialized subselect`.`a`))))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+1 6
+2 6
+drop table t1,t2;
+
+Verify that an inner NULL is looked up only once (result is
+cached).
+create table t1(a int);
+create table t2(a int);
+insert into t1 values(1),(2),(3),(4),(5),(6);
+insert into t1 select * from t1;
+insert into t2 values(10),(20),(NULL);
+explain extended select a, (a in (select * from t2)) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in ( <materialize> (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a` in <temporary table> on distinct_key where ((`test`.`t1`.`a` = `materialized subselect`.`a`))))) AS `(a in (select * from t2))` from `test`.`t1`
+flush status;
+select a, (a in (select * from t2)) from t1;
+a (a in (select * from t2))
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+6 NULL
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+6 NULL
+There will be one look-up in the temporary table for each row
+of t1 (12), plus one additional look-up to check whether table
+contains a NULL value.
+show status like "handler_read_key";
+Variable_name Value
+Handler_read_key 13
+drop table t1,t2;
+#
+# Bug#13495157 - SUBQUERY MATERIALIZATION NOT USED FOR CERTAIN
+# STATEMENTS
+#
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1),(2),(3);
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES(1),(2),(4);
+# subquery materialization used for SELECT:
+EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1); Using join buffer (Block Nested Loop)
+SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+a
+1
+# Also used for INSERT SELECT:
+CREATE TABLE t3 SELECT * FROM t1;
+EXPLAIN INSERT INTO t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1); Using join buffer (Block Nested Loop)
+INSERT INTO t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t3;
+a
+1
+1
+2
+3
+EXPLAIN INSERT INTO t2 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using temporary
+1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1); Using join buffer (Block Nested Loop)
+INSERT INTO t2 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+2
+4
+EXPLAIN INSERT INTO t2 SELECT * FROM t2 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; FirstMatch(t2); Using join buffer (Block Nested Loop)
+INSERT INTO t2 SELECT * FROM t2 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+1
+1
+2
+4
+4
+# Not used for single-table UPDATE, DELETE:
+EXPLAIN SELECT * FROM t2 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Materialize; Scan
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where; Using join buffer (Block Nested Loop)
+EXPLAIN UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t1);
+SELECT * FROM t2;
+a
+0
+0
+0
+0
+1
+4
+4
+EXPLAIN DELETE FROM t2 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+DELETE FROM t2 WHERE a IN (SELECT * FROM t1);
+SELECT * FROM t2;
+a
+0
+0
+0
+0
+4
+4
+EXPLAIN UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+EXPLAIN DELETE FROM t2 WHERE a IN (SELECT * FROM t2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+UPDATE t2 SET a=3 WHERE a=0;
+# Used for multi-table UPDATE, DELETE:
+EXPLAIN SELECT * FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Materialize; Scan
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4 Using join buffer (Block Nested Loop)
+EXPLAIN UPDATE t2,t3 SET t2.a=t2.a-2 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Materialize; Scan
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4 Using join buffer (Block Nested Loop)
+UPDATE t2,t3 SET t2.a=t2.a-2 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+1
+1
+4
+4
+EXPLAIN DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Materialize; Scan
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4 Using join buffer (Block Nested Loop)
+DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+SELECT * FROM t2;
+a
+4
+4
+EXPLAIN UPDATE t2,t3 SET t2.a=10 WHERE t2.a IN (SELECT * FROM t2 WHERE a <> 2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+EXPLAIN DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t2 WHERE a <> 2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+DROP TABLE t1,t2,t3;
+#
+# Test that subquery materialization only does one lookup: does
+# not try to read the next row if the first row failed the
+# subquery's WHERE. We use a case where index lookup is not
+# enough to satisfy IN(), because index has length two when the
+# outer value has length three, and thus the post-filtering
+# WHERE added by subselect_hash_sj_engine::setup() makes the
+# decision.
+#
+create table t1 (a varchar(3));
+create table t2 (a varchar(2));
+insert into t1 values('aaa'), ('aaa');
+insert into t2 values('aa'), ('aa');
+explain select * from t1 where a in (select a from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t1); Using join buffer (Block Nested Loop)
+flush status;
+select * from t1 where a in (select a from t2);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 0
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 6
+drop table t1,t2;
+#
+# Bug#13655791 DIFFERENT RESULT WITH WL6094 ON QUERY WITH XOR
+# IN WHERE CLAUSE + MYISAM
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t1 VALUES (10,'x');
+CREATE TABLE t2 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t2 VALUES (1,'v'), (5,'x'), (11,'z'), (12,'c'), (15,'y');
+CREATE TABLE t3 (
+pk int NOT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key)
+);
+INSERT INTO t3 VALUES (10,8);
+CREATE TABLE t4 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t4 VALUES (1,'x');
+EXPLAIN SELECT OUTR.pk, OUTR.col_varchar_nokey, OUTR2.col_varchar_nokey
+FROM t2 AS OUTR2
+JOIN t4 AS OUTR
+ON (OUTR2.col_varchar_nokey > OUTR.col_varchar_nokey)
+WHERE
+OUTR.col_varchar_nokey IN (
+SELECT INNR.col_varchar_nokey
+FROM t3 AS INNR2
+LEFT JOIN t1 AS INNR
+ON (INNR2.col_int_key >= INNR.pk)
+)
+XOR OUTR.pk < 6
+;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY OUTR system NULL NULL NULL NULL 1
+1 PRIMARY OUTR2 ALL NULL NULL NULL NULL 5 Using where
+2 SUBQUERY INNR2 system NULL NULL NULL NULL 1
+2 SUBQUERY INNR system PRIMARY NULL NULL NULL 1
+FLUSH STATUS;
+SELECT OUTR.pk, OUTR.col_varchar_nokey, OUTR2.col_varchar_nokey
+FROM t2 AS OUTR2
+JOIN t4 AS OUTR
+ON (OUTR2.col_varchar_nokey > OUTR.col_varchar_nokey)
+WHERE
+OUTR.col_varchar_nokey IN (
+SELECT INNR.col_varchar_nokey
+FROM t3 AS INNR2
+LEFT JOIN t1 AS INNR
+ON (INNR2.col_int_key >= INNR.pk)
+)
+XOR OUTR.pk < 6
+;
+pk col_varchar_nokey col_varchar_nokey
+SHOW STATUS LIKE "HANDLER_READ%";
+Variable_name Value
+Handler_read_first 3
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 9
+DROP TABLE t1,t2,t3,t4;
# End of 5.6 tests
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_mat_none.result'
--- a/mysql-test/r/subquery_mat_none.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_mat_none.result 2012-02-08 15:25:17 +0000
@@ -1292,5 +1292,484 @@ pk pk
1 NULL
DROP TABLE t1, t2;
# End of test for bug#13607423.
+
+Test of WL#6094 "Allow subquery materialization in NOT IN if all
+columns are not nullable"
+
+create table t1(a int not null);
+create table t2(a int not null);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+Test in SELECT list
+
+cols not nullable => subq materialization
+explain extended select a, (a,a) in (select a,a from t2) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),<exists>(/* select#2 */ select `test`.`t2`.`a`,`test`.`t2`.`a` from `test`.`t2` where ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) and (<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`)) having (<is_not_null_test>(`test`.`t2`.`a`) and <is_not_null_test>(`test`.`t2`.`a`)))) AS `(a,a) in (select a,a from t2)` from `test`.`t1`
+select a, (a,a) in (select a,a from t2) from t1;
+a (a,a) in (select a,a from t2)
+1 1
+2 1
+
+cols not nullable => subq materialization
+explain extended select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where ((<cache>(`test`.`t1`.`a`) = `test`.`t3`.`a`) and (<cache>(`test`.`t1`.`a`) = `test`.`t3`.`a`)) having (<is_not_null_test>(`test`.`t3`.`a`) and <is_not_null_test>(`test`.`t3`.`a`)))) AS `(t1.a,t1.a) in (select a,a from t2 as t3)` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)
+select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+a a (t1.a,t1.a) in (select a,a from t2 as t3)
+
+t2.a is not nullable, but in the query it may appear as NULL
+as it's in an outer join. So, no materialization.
+explain extended select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or <cache>(isnull(`test`.`t3`.`a`))), true) and trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or <cache>(isnull(`test`.`t3`.`a`))), true)) having (trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true) and trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true)))) AS `(t2.a,t2.a) in (select a,a from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a (t2.a,t2.a) in (select a,a from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+
+alter table t2 modify a int;
+two nullable inner cols => no subq materialization
+explain extended select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t1`.`a`,`test`.`t1`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (((<cache>(`test`.`t1`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)) and ((<cache>(`test`.`t1`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`))) having (<is_not_null_test>(`test`.`t3`.`a`) and <is_not_null_test>(`test`.`t3`.`a`)))) AS `(t1.a,t1.a) in (select a,a from t2 as t3)` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)
+select t1.a, t2.a, (t1.a,t1.a) in (select a,a from t2 as t3)
+from t1 join t2 on t1.a+t2.a=1000;
+a a (t1.a,t1.a) in (select a,a from t2 as t3)
+alter table t2 modify a int not null;
+
+Test in WHERE
+
+top-level => subq materialization. With one exception: if
+semijoin is enabled in @@optimizer_switch, semijoin is chosen,
+then rejected (due to outer join), and in that case, the
+fallback is IN->EXISTS, subq-materialization is not tried...
+explain extended select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) in (select a,a from t2 as t3);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where (<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) and (<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`)))) and ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 3))
+select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) in (select a,a from t2 as t3);
+a a
+2 1
+1 2
+
+cols not nullable => subq materialization
+explain extended select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) not in (select a,a from t2 as t3);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a` from `test`.`t1` join `test`.`t2` where ((not(<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) and (<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`)) having (<is_not_null_test>(`test`.`t3`.`a`) and <is_not_null_test>(`test`.`t3`.`a`)))))) and ((`test`.`t1`.`a` + `test`.`t2`.`a`) = 3))
+select t1.a, t2.a
+from t1 join t2 on t1.a+t2.a=3
+where (t2.a,t2.a) not in (select a,a from t2 as t3);
+a a
+drop table t1,t2;
+
+Test of WL6095 "Allow subquery materialization in NOT IN if
+single-column subquery"
+
+create table t1(a int null);
+create table t2(a int null);
+insert into t1 values(1),(2);
+insert into t2 values(1),(2);
+
+one col => subq materialization
+explain extended select a, a in (select a from t2) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t2` where trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`)), true) having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a`), true))) AS `a in (select a from t2)` from `test`.`t1`
+select a, a in (select a from t2) from t1;
+a a in (select a from t2)
+1 1
+2 1
+
+t2.a is not nullable, but in the query it may appear as NULL
+as it's in an outer join. But there is only one inner column so
+materialization is possible
+explain extended select t1.a, t2.a, t2.a in (select * from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>(`test`.`t2`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t2` `t3` where trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)), true) having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true))) AS `t2.a in (select * from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, t2.a in (select * from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a t2.a in (select * from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+
+_two_ outer columns, nullable => no materialization
+explain extended select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,<in_optimizer>((`test`.`t2`.`a`,`test`.`t2`.`a`),<exists>(/* select#2 */ select `test`.`t3`.`a`,`test`.`t3`.`a` from `test`.`t2` `t3` where (trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)), true) and trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t2`.`a`) = `test`.`t3`.`a`) or isnull(`test`.`t3`.`a`)), true)) having (trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true) and trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t3`.`a`), true)))) AS `(t2.a,t2.a) in (select a,a from t2 as t3)` from `test`.`t1` left join `test`.`t2` on(((`test`.`t1`.`a` + `test`.`t2`.`a`) = 1000)) where 1
+select t1.a, t2.a, (t2.a,t2.a) in (select a,a from t2 as t3)
+from t1 left join t2 on t1.a+t2.a=1000;
+a a (t2.a,t2.a) in (select a,a from t2 as t3)
+1 NULL NULL
+2 NULL NULL
+drop table t1,t2;
+
+Test in HAVING
+create table t1(a int, b int);
+create table t2(a int);
+insert into t1 values(1,1),(1,2),(1,3),(2,1),(2,2),(2,3);
+insert into t2 values(10),(20);
+no NULLs.
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,<exists>(/* select#2 */ select 1 from `test`.`t2` where trigcond_if(outer_field_is_not_null, ((<cache>(`z`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`)), true) having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a`), true))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+one outer NULL
+insert into t1 values(null,null);
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using temporary; Using filesort
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,<exists>(/* select#2 */ select 1 from `test`.`t2` where trigcond_if(outer_field_is_not_null, ((<cache>(`z`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`)), true) having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a`), true))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+NULL NULL
+one outer NULL and one inner NULL
+insert into t2 values(null);
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using temporary; Using filesort
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,<exists>(/* select#2 */ select 1 from `test`.`t2` where trigcond_if(outer_field_is_not_null, ((<cache>(`z`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`)), true) having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a`), true))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+NULL NULL
+1 6
+2 6
+one inner NULL
+delete from t1 where a is null;
+explain extended select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using temporary; Using filesort
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `z`,sum(`test`.`t1`.`b`) AS `sum(t1.b)` from `test`.`t1` group by `test`.`t1`.`a` having isnull(<in_optimizer>(`z`,<exists>(/* select#2 */ select 1 from `test`.`t2` where trigcond_if(outer_field_is_not_null, ((<cache>(`z`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`)), true) having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a`), true))))
+select t1.a as z, sum(t1.b) from t1 group by t1.a
+having (z in (select * from t2)) is null;
+z sum(t1.b)
+1 6
+2 6
+drop table t1,t2;
+
+Verify that an inner NULL is looked up only once (result is
+cached).
+create table t1(a int);
+create table t2(a int);
+insert into t1 values(1),(2),(3),(4),(5),(6);
+insert into t1 select * from t1;
+insert into t2 values(10),(20),(NULL);
+explain extended select a, (a in (select * from t2)) from t1;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 100.00
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
+Warnings:
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,<in_optimizer>(`test`.`t1`.`a`,<exists>(/* select#2 */ select 1 from `test`.`t2` where trigcond_if(outer_field_is_not_null, ((<cache>(`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`)), true) having trigcond_if(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`a`), true))) AS `(a in (select * from t2))` from `test`.`t1`
+flush status;
+select a, (a in (select * from t2)) from t1;
+a (a in (select * from t2))
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+6 NULL
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+6 NULL
+There will be one look-up in the temporary table for each row
+of t1 (12), plus one additional look-up to check whether table
+contains a NULL value.
+show status like "handler_read_key";
+Variable_name Value
+Handler_read_key 0
+drop table t1,t2;
+#
+# Bug#13495157 - SUBQUERY MATERIALIZATION NOT USED FOR CERTAIN
+# STATEMENTS
+#
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES(1),(2),(3);
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES(1),(2),(4);
+# subquery materialization used for SELECT:
+EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+a
+1
+# Also used for INSERT SELECT:
+CREATE TABLE t3 SELECT * FROM t1;
+EXPLAIN INSERT INTO t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+INSERT INTO t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t3;
+a
+1
+1
+2
+3
+EXPLAIN INSERT INTO t2 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using temporary
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
+INSERT INTO t2 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+2
+4
+EXPLAIN INSERT INTO t2 SELECT * FROM t2 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where
+INSERT INTO t2 SELECT * FROM t2 WHERE a IN (SELECT * FROM t2 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+1
+1
+2
+4
+4
+# Not used for single-table UPDATE, DELETE:
+EXPLAIN SELECT * FROM t2 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+EXPLAIN UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t1);
+SELECT * FROM t2;
+a
+0
+0
+0
+0
+1
+4
+4
+EXPLAIN DELETE FROM t2 WHERE a IN (SELECT * FROM t1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7 Using where
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+DELETE FROM t2 WHERE a IN (SELECT * FROM t1);
+SELECT * FROM t2;
+a
+0
+0
+0
+0
+4
+4
+EXPLAIN UPDATE t2 SET a=a-1 WHERE a IN (SELECT * FROM t2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+EXPLAIN DELETE FROM t2 WHERE a IN (SELECT * FROM t2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+UPDATE t2 SET a=3 WHERE a=0;
+# Used for multi-table UPDATE, DELETE:
+EXPLAIN SELECT * FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+EXPLAIN UPDATE t2,t3 SET t2.a=t2.a-2 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+UPDATE t2,t3 SET t2.a=t2.a-2 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+SELECT * FROM t2;
+a
+1
+1
+1
+1
+4
+4
+EXPLAIN DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 4
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 Using where; Using join buffer (Block Nested Loop)
+2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 Using where
+DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t1 WHERE a <> 2);
+SELECT * FROM t2;
+a
+4
+4
+EXPLAIN UPDATE t2,t3 SET t2.a=10 WHERE t2.a IN (SELECT * FROM t2 WHERE a <> 2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+EXPLAIN DELETE t2.* FROM t2,t3 WHERE t2.a IN (SELECT * FROM t2 WHERE a <> 2);
+ERROR HY000: You can't specify target table 't2' for update in FROM clause
+DROP TABLE t1,t2,t3;
+#
+# Test that subquery materialization only does one lookup: does
+# not try to read the next row if the first row failed the
+# subquery's WHERE. We use a case where index lookup is not
+# enough to satisfy IN(), because index has length two when the
+# outer value has length three, and thus the post-filtering
+# WHERE added by subselect_hash_sj_engine::setup() makes the
+# decision.
+#
+create table t1 (a varchar(3));
+create table t2 (a varchar(2));
+insert into t1 values('aaa'), ('aaa');
+insert into t2 values('aa'), ('aa');
+explain select * from t1 where a in (select a from t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
+flush status;
+select * from t1 where a in (select a from t2);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 0
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 9
+drop table t1,t2;
+#
+# Bug#13655791 DIFFERENT RESULT WITH WL6094 ON QUERY WITH XOR
+# IN WHERE CLAUSE + MYISAM
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t1 VALUES (10,'x');
+CREATE TABLE t2 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t2 VALUES (1,'v'), (5,'x'), (11,'z'), (12,'c'), (15,'y');
+CREATE TABLE t3 (
+pk int NOT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key)
+);
+INSERT INTO t3 VALUES (10,8);
+CREATE TABLE t4 (
+pk int NOT NULL,
+col_varchar_nokey varchar(1) DEFAULT NULL,
+PRIMARY KEY (pk)
+);
+INSERT INTO t4 VALUES (1,'x');
+EXPLAIN SELECT OUTR.pk, OUTR.col_varchar_nokey, OUTR2.col_varchar_nokey
+FROM t2 AS OUTR2
+JOIN t4 AS OUTR
+ON (OUTR2.col_varchar_nokey > OUTR.col_varchar_nokey)
+WHERE
+OUTR.col_varchar_nokey IN (
+SELECT INNR.col_varchar_nokey
+FROM t3 AS INNR2
+LEFT JOIN t1 AS INNR
+ON (INNR2.col_int_key >= INNR.pk)
+)
+XOR OUTR.pk < 6
+;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 DEPENDENT SUBQUERY INNR2 system NULL NULL NULL NULL 1
+2 DEPENDENT SUBQUERY INNR system PRIMARY NULL NULL NULL 1
+FLUSH STATUS;
+SELECT OUTR.pk, OUTR.col_varchar_nokey, OUTR2.col_varchar_nokey
+FROM t2 AS OUTR2
+JOIN t4 AS OUTR
+ON (OUTR2.col_varchar_nokey > OUTR.col_varchar_nokey)
+WHERE
+OUTR.col_varchar_nokey IN (
+SELECT INNR.col_varchar_nokey
+FROM t3 AS INNR2
+LEFT JOIN t1 AS INNR
+ON (INNR2.col_int_key >= INNR.pk)
+)
+XOR OUTR.pk < 6
+;
+pk col_varchar_nokey col_varchar_nokey
+SHOW STATUS LIKE "HANDLER_READ%";
+Variable_name Value
+Handler_read_first 3
+Handler_read_key 0
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 3
+DROP TABLE t1,t2,t3,t4;
# End of 5.6 tests
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_nomat_nosj.result'
--- a/mysql-test/r/subquery_nomat_nosj.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_nomat_nosj.result 2012-02-08 15:25:17 +0000
@@ -4180,7 +4180,7 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
@@ -7080,4 +7080,31 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using where
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_nomat_nosj_bka.result'
--- a/mysql-test/r/subquery_nomat_nosj_bka.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_nomat_nosj_bka.result 2012-02-08 15:25:17 +0000
@@ -4181,7 +4181,7 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
@@ -7081,5 +7081,32 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using where
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result'
--- a/mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result 2012-02-08 15:25:17 +0000
@@ -4181,7 +4181,7 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
@@ -7081,5 +7081,32 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using where
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_none.result'
--- a/mysql-test/r/subquery_none.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_none.result 2012-02-08 15:25:17 +0000
@@ -4179,7 +4179,7 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
@@ -7079,4 +7079,31 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using where
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_none_bka.result'
--- a/mysql-test/r/subquery_none_bka.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_none_bka.result 2012-02-08 15:25:17 +0000
@@ -4180,7 +4180,7 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
@@ -7080,5 +7080,32 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using where
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_none_bka_nixbnl.result'
--- a/mysql-test/r/subquery_none_bka_nixbnl.result 2012-02-07 14:50:31 +0000
+++ b/mysql-test/r/subquery_none_bka_nixbnl.result 2012-02-08 15:25:17 +0000
@@ -4180,7 +4180,7 @@ CREATE TABLE t1 (pk int PRIMARY KEY, int
INSERT INTO t1 VALUES (10,1), (14,1);
CREATE TABLE t2 (pk int PRIMARY KEY, int_key int);
INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3);
-# should have eq_ref for t1
+# should have eq_ref for t1, unless subquery materialization is used
EXPLAIN
SELECT * FROM t2 outr
WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2)
@@ -7080,5 +7080,32 @@ WHERE (c_sq1_alias1.col_int_nokey != @va
OR c_sq1_alias1.pk != @var3)) ) AS alias3;
pk col_int_nokey col_int_key col_time_key col_varchar_key col_varchar_nokey
DROP TABLE t1,t2;
+#
+# Test that indexsubquery_engine only does one lookup if
+# the technique is unique_subquery: does not try to read the
+# next row if the first row failed the subquery's WHERE
+# condition (here: b=3).
+#
+create table t1(a int);
+insert into t1 values(1),(2);
+create table t2(a int primary key, b int);
+insert into t2 values(1,10),(2,10);
+explain select * from t1 where a in (select a from t2 where b=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using where
+flush status;
+select * from t1 where a in (select a from t2 where b=3);
+a
+show status like "handler_read%";
+Variable_name Value
+Handler_read_first 0
+Handler_read_key 2
+Handler_read_last 0
+Handler_read_next 0
+Handler_read_prev 0
+Handler_read_rnd 0
+Handler_read_rnd_next 3
+drop table t1,t2;
set optimizer_switch=default;
set optimizer_switch=default;
=== modified file 'mysql-test/r/subquery_sj_all.result'
--- a/mysql-test/r/subquery_sj_all.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_all.result 2012-02-08 15:25:17 +0000
@@ -6706,9 +6706,9 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
-2 DEPENDENT SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
-2 DEPENDENT SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using index condition; Using where; End temporary
+2 SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
+2 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
+2 SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using index condition; End temporary
SELECT *
FROM t1
WHERE g1 NOT IN
@@ -7091,10 +7091,10 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY parent1 ref col_int_key col_int_key 4 func 2 Using index condition; Start temporary
-2 DEPENDENT SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using index condition; Using where; End temporary
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+2 SUBQUERY parent1 ALL col_int_key NULL NULL NULL 11 Start materialize
+2 SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; End materialize; Using join buffer (Block Nested Loop)
SELECT * FROM t3
WHERE g1 NOT IN
(SELECT grandparent1.col_int_nokey AS g1
=== modified file 'mysql-test/r/subquery_sj_all_bka.result'
--- a/mysql-test/r/subquery_sj_all_bka.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_all_bka.result 2012-02-08 15:25:17 +0000
@@ -6707,9 +6707,9 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
-2 DEPENDENT SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
-2 DEPENDENT SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using index condition; Using where; End temporary; Using join buffer (Batched Key Access)
+2 SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
+2 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
+2 SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using index condition; End temporary; Using join buffer (Batched Key Access)
SELECT *
FROM t1
WHERE g1 NOT IN
@@ -7092,10 +7092,10 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY parent1 ref col_int_key col_int_key 4 func 2 Using index condition; Start temporary
-2 DEPENDENT SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using index condition; Using where; End temporary; Using join buffer (Batched Key Access)
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+2 SUBQUERY parent1 ALL col_int_key NULL NULL NULL 11 Start materialize
+2 SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; End materialize; Using join buffer (Block Nested Loop)
SELECT * FROM t3
WHERE g1 NOT IN
(SELECT grandparent1.col_int_nokey AS g1
=== modified file 'mysql-test/r/subquery_sj_all_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_all_bka_nixbnl.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_all_bka_nixbnl.result 2012-02-08 15:25:17 +0000
@@ -6707,9 +6707,9 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
-2 DEPENDENT SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
-2 DEPENDENT SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using index condition; Using where; End temporary; Using join buffer (Batched Key Access)
+2 SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
+2 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
+2 SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using index condition; End temporary; Using join buffer (Batched Key Access)
SELECT *
FROM t1
WHERE g1 NOT IN
@@ -7092,10 +7092,10 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using index condition; Using where
-2 DEPENDENT SUBQUERY parent1 ref col_int_key col_int_key 4 func 2 Using index condition
-2 DEPENDENT SUBQUERY parent2 ref col_int_key col_int_key 4 test.parent1.col_int_nokey 2 Using index; FirstMatch(grandparent1)
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+2 SUBQUERY parent1 ALL col_int_key NULL NULL NULL 11 Start materialize
+2 SUBQUERY parent2 ref col_int_key col_int_key 4 test.parent1.col_int_nokey 2 Using index; End materialize
SELECT * FROM t3
WHERE g1 NOT IN
(SELECT grandparent1.col_int_nokey AS g1
=== modified file 'mysql-test/r/subquery_sj_all_bkaunique.result'
--- a/mysql-test/r/subquery_sj_all_bkaunique.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_all_bkaunique.result 2012-02-08 15:25:17 +0000
@@ -6708,9 +6708,9 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
-2 DEPENDENT SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
-2 DEPENDENT SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using index condition; Using where; End temporary; Using join buffer (Batched Key Access (unique))
+2 SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
+2 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
+2 SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using index condition; End temporary; Using join buffer (Batched Key Access (unique))
SELECT *
FROM t1
WHERE g1 NOT IN
@@ -7093,10 +7093,10 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY parent1 ref col_int_key col_int_key 4 func 2 Using index condition; Start temporary
-2 DEPENDENT SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using index condition; Using where; End temporary; Using join buffer (Batched Key Access (unique))
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+2 SUBQUERY parent1 ALL col_int_key NULL NULL NULL 11 Start materialize
+2 SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; End materialize; Using join buffer (Block Nested Loop)
SELECT * FROM t3
WHERE g1 NOT IN
(SELECT grandparent1.col_int_nokey AS g1
=== modified file 'mysql-test/r/subquery_sj_mat.result'
--- a/mysql-test/r/subquery_sj_mat.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_mat.result 2012-02-08 15:25:17 +0000
@@ -6706,9 +6706,9 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
-2 DEPENDENT SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
-2 DEPENDENT SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using where; End temporary
+2 SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
+2 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
+2 SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using where; End temporary
SELECT *
FROM t1
WHERE g1 NOT IN
@@ -7091,10 +7091,10 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY parent1 ref col_int_key col_int_key 4 func 2 Using where; Start temporary
-2 DEPENDENT SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using where; End temporary
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+2 SUBQUERY parent1 ALL col_int_key NULL NULL NULL 11 Start materialize
+2 SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; End materialize; Using join buffer (Block Nested Loop)
SELECT * FROM t3
WHERE g1 NOT IN
(SELECT grandparent1.col_int_nokey AS g1
=== modified file 'mysql-test/r/subquery_sj_mat_bka.result'
--- a/mysql-test/r/subquery_sj_mat_bka.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_mat_bka.result 2012-02-08 15:25:17 +0000
@@ -6707,9 +6707,9 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
-2 DEPENDENT SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
-2 DEPENDENT SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using where; End temporary
+2 SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
+2 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
+2 SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using where; End temporary
SELECT *
FROM t1
WHERE g1 NOT IN
@@ -7092,10 +7092,10 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY parent1 ref col_int_key col_int_key 4 func 2 Using where; Start temporary
-2 DEPENDENT SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using where; End temporary
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+2 SUBQUERY parent1 ALL col_int_key NULL NULL NULL 11 Start materialize
+2 SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; End materialize; Using join buffer (Block Nested Loop)
SELECT * FROM t3
WHERE g1 NOT IN
(SELECT grandparent1.col_int_nokey AS g1
=== modified file 'mysql-test/r/subquery_sj_mat_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_mat_bka_nixbnl.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_mat_bka_nixbnl.result 2012-02-08 15:25:17 +0000
@@ -6707,9 +6707,9 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
-2 DEPENDENT SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
-2 DEPENDENT SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using where; End temporary
+2 SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
+2 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
+2 SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using where; End temporary
SELECT *
FROM t1
WHERE g1 NOT IN
@@ -7092,10 +7092,10 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using where; Start temporary
-2 DEPENDENT SUBQUERY parent1 ref col_int_key col_int_key 4 func 2 Using where
-2 DEPENDENT SUBQUERY parent2 ref col_int_key col_int_key 4 test.parent1.col_int_nokey 2 Using index; End temporary
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+2 SUBQUERY parent1 ALL col_int_key NULL NULL NULL 11 Start materialize
+2 SUBQUERY parent2 ref col_int_key col_int_key 4 test.parent1.col_int_nokey 2 Using index; End materialize
SELECT * FROM t3
WHERE g1 NOT IN
(SELECT grandparent1.col_int_nokey AS g1
=== modified file 'mysql-test/r/subquery_sj_mat_bkaunique.result'
--- a/mysql-test/r/subquery_sj_mat_bkaunique.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_mat_bkaunique.result 2012-02-08 15:25:17 +0000
@@ -6708,9 +6708,9 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
-2 DEPENDENT SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
-2 DEPENDENT SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using where; End temporary
+2 SUBQUERY parent1 ALL NULL NULL NULL NULL 20 Start temporary
+2 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
+2 SUBQUERY grandparent1 ref col_varchar_key col_varchar_key 3 test.parent1.col_varchar_nokey 1 Using where; End temporary
SELECT *
FROM t1
WHERE g1 NOT IN
@@ -7093,10 +7093,10 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY parent1 ref col_int_key col_int_key 4 func 2 Using where; Start temporary
-2 DEPENDENT SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
-2 DEPENDENT SUBQUERY grandparent1 ref col_int_key col_int_key 4 func 2 Using where; End temporary
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+2 SUBQUERY parent1 ALL col_int_key NULL NULL NULL 11 Start materialize
+2 SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; End materialize; Using join buffer (Block Nested Loop)
SELECT * FROM t3
WHERE g1 NOT IN
(SELECT grandparent1.col_int_nokey AS g1
=== modified file 'mysql-test/r/subquery_sj_mat_nosj.result'
--- a/mysql-test/r/subquery_sj_mat_nosj.result 2012-01-31 11:19:25 +0000
+++ b/mysql-test/r/subquery_sj_mat_nosj.result 2012-02-08 15:25:17 +0000
@@ -6782,7 +6782,7 @@ AND grandparent1.col_varchar_key IS NOT
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 DEPENDENT SUBQUERY grandparent1 ALL col_varchar_key NULL NULL NULL 20 Using where
+2 SUBQUERY grandparent1 ALL col_varchar_key NULL NULL NULL 20 Using where
3 SUBQUERY parent1 ALL NULL NULL NULL NULL 20
3 SUBQUERY parent2 eq_ref PRIMARY PRIMARY 4 test.parent1.pk 1 Using index
SELECT *
@@ -7167,8 +7167,8 @@ ON parent1.col_int_nokey = parent2.col_i
AND grandparent1.col_int_key <> 3
);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
+1 PRIMARY t3 system NULL NULL NULL NULL 1
+2 SUBQUERY grandparent1 ALL col_int_key NULL NULL NULL 11 Using where
3 SUBQUERY parent1 ALL NULL NULL NULL NULL 11
3 SUBQUERY parent2 index col_int_key col_int_key 4 NULL 1 Using where; Using index; Using join buffer (Block Nested Loop)
SELECT * FROM t3
=== modified file 'mysql-test/suite/innodb/r/innodb_mysql.result'
--- a/mysql-test/suite/innodb/r/innodb_mysql.result 2012-01-30 13:13:15 +0000
+++ b/mysql-test/suite/innodb/r/innodb_mysql.result 2012-02-08 15:25:17 +0000
@@ -1436,7 +1436,8 @@ explain
select b from t1 where a not in (select b from t1,t2 group by a) group by a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+2 SUBQUERY t1 system NULL NULL NULL NULL 0 const row not found
+2 SUBQUERY t2 ALL NULL NULL NULL NULL 1
DROP TABLE t1,t2;
End of 5.0 tests
CREATE TABLE `t2` (
=== modified file 'mysql-test/suite/opt_trace/include/general.inc'
--- a/mysql-test/suite/opt_trace/include/general.inc 2011-11-18 14:51:40 +0000
+++ b/mysql-test/suite/opt_trace/include/general.inc 2012-02-08 15:25:17 +0000
@@ -82,12 +82,12 @@ select * from information_schema.OPTIMIZ
select (@query:=QUERY)+NULL, (@trace:=TRACE)+NULL from information_schema.OPTIMIZER_TRACE;
select length(@trace);
# The concatenation of query and trace above has length:
-# - >13900 in normal mode
-# - <13900 in ps-protocol mode (because IN->EXISTS is done at PREPARE
+# - >14100 in normal mode
+# - <14100 in ps-protocol mode (because IN->EXISTS is done at PREPARE
# and we trace only EXECUTE)
# - So in normal mode, the lines below verify truncation,
# whereas in ps-protocol mode they verify non-truncation.
-set optimizer_trace_max_mem_size=13900;
+set optimizer_trace_max_mem_size=14100;
select length(@query)+length(@trace) > @@optimizer_trace_max_mem_size;
SELECT * FROM t5 WHERE 5 IN (SELECT 1 FROM t6 WHERE d = ifnull(c,null) UNION SELECT 2 FROM t6 WHERE d = ifnull(c,null));
select (@missing_bytes:=missing_bytes_beyond_max_mem_size) from information_schema.OPTIMIZER_TRACE;
=== modified file 'mysql-test/suite/opt_trace/r/bugs_no_prot_all.result'
--- a/mysql-test/suite/opt_trace/r/bugs_no_prot_all.result 2012-01-30 13:13:15 +0000
+++ b/mysql-test/suite/opt_trace/r/bugs_no_prot_all.result 2012-02-08 15:25:17 +0000
@@ -190,7 +190,10 @@ WHERE sq2_alias1.col_varchar_nokey <= al
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": false,
+ "chosen": false,
+ "cause": "cannot_handle_partial_matches"
} /* transformation */
},
{
=== modified file 'mysql-test/suite/opt_trace/r/bugs_no_prot_none.result'
--- a/mysql-test/suite/opt_trace/r/bugs_no_prot_none.result 2012-01-26 13:09:59 +0000
+++ b/mysql-test/suite/opt_trace/r/bugs_no_prot_none.result 2012-02-08 15:25:17 +0000
@@ -174,14 +174,6 @@ WHERE sq2_alias1.col_varchar_nokey <= al
"transformation": {
"select#": 4,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 4,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -206,14 +198,6 @@ WHERE sq2_alias1.col_varchar_nokey <= al
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -383,14 +367,6 @@ FROM t1
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -816,14 +792,6 @@ ON table2 .col_int_key = table1 .col_int
"select#": 3,
"from": "IN (SELECT)",
"to": "semijoin",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 3,
- "from": "IN (SELECT)",
- "to": "materialization",
"chosen": false
} /* transformation */
},
=== modified file 'mysql-test/suite/opt_trace/r/bugs_ps_prot_all.result'
--- a/mysql-test/suite/opt_trace/r/bugs_ps_prot_all.result 2012-01-30 13:13:15 +0000
+++ b/mysql-test/suite/opt_trace/r/bugs_ps_prot_all.result 2012-02-08 15:25:17 +0000
@@ -190,7 +190,10 @@ WHERE sq2_alias1.col_varchar_nokey <= al
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": false,
+ "chosen": false,
+ "cause": "cannot_handle_partial_matches"
} /* transformation */
},
{
=== modified file 'mysql-test/suite/opt_trace/r/bugs_ps_prot_none.result'
--- a/mysql-test/suite/opt_trace/r/bugs_ps_prot_none.result 2012-01-30 08:57:24 +0000
+++ b/mysql-test/suite/opt_trace/r/bugs_ps_prot_none.result 2012-02-08 15:25:17 +0000
@@ -174,14 +174,6 @@ WHERE sq2_alias1.col_varchar_nokey <= al
"transformation": {
"select#": 4,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 4,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -206,14 +198,6 @@ WHERE sq2_alias1.col_varchar_nokey <= al
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -378,14 +362,6 @@ FROM t1
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -806,14 +782,6 @@ ON table2 .col_int_key = table1 .col_int
"select#": 3,
"from": "IN (SELECT)",
"to": "semijoin",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 3,
- "from": "IN (SELECT)",
- "to": "materialization",
"chosen": false
} /* transformation */
}
=== modified file 'mysql-test/suite/opt_trace/r/general2_no_prot.result'
--- a/mysql-test/suite/opt_trace/r/general2_no_prot.result 2012-01-26 13:09:59 +0000
+++ b/mysql-test/suite/opt_trace/r/general2_no_prot.result 2012-02-08 15:25:17 +0000
@@ -704,7 +704,10 @@ TRACE
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": false,
+ "chosen": false,
+ "cause": "cannot_handle_partial_matches"
} /* transformation */
},
{
@@ -2646,14 +2649,6 @@ from t0 where a in
"select#": 2,
"from": "IN (SELECT)",
"to": "semijoin",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
"chosen": false
} /* transformation */
},
=== modified file 'mysql-test/suite/opt_trace/r/general2_ps_prot.result'
--- a/mysql-test/suite/opt_trace/r/general2_ps_prot.result 2012-01-30 08:57:24 +0000
+++ b/mysql-test/suite/opt_trace/r/general2_ps_prot.result 2012-02-08 15:25:17 +0000
@@ -732,7 +732,8 @@ TRACE
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "already have strategy"
} /* transformation */
}
] /* steps */
@@ -2699,14 +2700,6 @@ from t0 where a in
"select#": 2,
"from": "IN (SELECT)",
"to": "semijoin",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
"chosen": false
} /* transformation */
},
=== modified file 'mysql-test/suite/opt_trace/r/general_no_prot_all.result'
--- a/mysql-test/suite/opt_trace/r/general_no_prot_all.result 2012-01-26 13:09:59 +0000
+++ b/mysql-test/suite/opt_trace/r/general_no_prot_all.result 2012-02-08 15:25:17 +0000
@@ -1005,7 +1005,8 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "in UNION"
} /* transformation */
},
{
@@ -1041,7 +1042,8 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"select#": 3,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "in UNION"
} /* transformation */
},
{
@@ -1230,7 +1232,8 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"select#": "fake",
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "in UNION"
} /* transformation */
}
] /* steps */
@@ -1341,8 +1344,8 @@ select (@query:=QUERY)+NULL, (@trace:=TR
NULL NULL
select length(@trace);
length(@trace)
-14543
-set optimizer_trace_max_mem_size=13900;
+14672
+set optimizer_trace_max_mem_size=14100;
select length(@query)+length(@trace) > @@optimizer_trace_max_mem_size;
length(@query)+length(@trace) > @@optimizer_trace_max_mem_size
1
@@ -1350,7 +1353,7 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
c
select (@missing_bytes:=missing_bytes_beyond_max_mem_size) from information_schema.OPTIMIZER_TRACE;
(@missing_bytes:=missing_bytes_beyond_max_mem_size)
-761
+681
select (@query2:=QUERY)+NULL,(@trace2:=TRACE)+NULL from information_schema.OPTIMIZER_TRACE;
(@query2:=QUERY)+NULL (@trace2:=TRACE)+NULL
NULL NULL
@@ -1358,7 +1361,7 @@ select length(@trace2),
(length(@trace2) + @missing_bytes) = length(@trace),
@query2 = @query;
length(@trace2) (length(@trace2) + @missing_bytes) = length(@trace) @query2 = @query
-13782 1 1
+13991 1 1
select length(@query2) + length(@trace2)
between (@@optimizer_trace_max_mem_size-200) and (@@optimizer_trace_max_mem_size+200);
length(@query2) + length(@trace2)
@@ -1721,6 +1724,8 @@ explain SELECT c FROM t5 where c+1 in (s
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": true,
"chosen": true
} /* transformation */
}
@@ -2504,14 +2509,6 @@ explain extended select * from t1 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -2780,14 +2777,6 @@ explain extended select * from t1 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -3395,7 +3384,7 @@ where a1 in (select b1 from t2_16 where
"from": "IN (SELECT)",
"to": "materialization",
"chosen": false,
- "cause": "field_types"
+ "cause": "inner blob"
} /* transformation */
},
{
@@ -4420,6 +4409,8 @@ concat(c1,'y') IN
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": true,
"chosen": true
} /* transformation */
}
@@ -4446,6 +4437,8 @@ concat(c1,'y') IN
"select#": 3,
"from": "IN (SELECT)",
"to": "materialization",
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": true,
"chosen": true
} /* transformation */
}
@@ -6101,7 +6094,10 @@ select * from t1 where (t1.a,t1.b) not i
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": false,
+ "chosen": false,
+ "cause": "cannot_handle_partial_matches"
} /* transformation */
},
{
=== modified file 'mysql-test/suite/opt_trace/r/general_no_prot_none.result'
--- a/mysql-test/suite/opt_trace/r/general_no_prot_none.result 2012-01-26 13:09:59 +0000
+++ b/mysql-test/suite/opt_trace/r/general_no_prot_none.result 2012-02-08 15:25:17 +0000
@@ -1003,14 +1003,6 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -1039,14 +1031,6 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"transformation": {
"select#": 3,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 3,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -1223,14 +1207,6 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": "fake",
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -1340,16 +1316,16 @@ select (@query:=QUERY)+NULL, (@trace:=TR
NULL NULL
select length(@trace);
length(@trace)
-14543
-set optimizer_trace_max_mem_size=13900;
+13668
+set optimizer_trace_max_mem_size=14100;
select length(@query)+length(@trace) > @@optimizer_trace_max_mem_size;
length(@query)+length(@trace) > @@optimizer_trace_max_mem_size
-1
+0
SELECT * FROM t5 WHERE 5 IN (SELECT 1 FROM t6 WHERE d = ifnull(c,null) UNION SELECT 2 FROM t6 WHERE d = ifnull(c,null));
c
select (@missing_bytes:=missing_bytes_beyond_max_mem_size) from information_schema.OPTIMIZER_TRACE;
(@missing_bytes:=missing_bytes_beyond_max_mem_size)
-761
+0
select (@query2:=QUERY)+NULL,(@trace2:=TRACE)+NULL from information_schema.OPTIMIZER_TRACE;
(@query2:=QUERY)+NULL (@trace2:=TRACE)+NULL
NULL NULL
@@ -1357,12 +1333,12 @@ select length(@trace2),
(length(@trace2) + @missing_bytes) = length(@trace),
@query2 = @query;
length(@trace2) (length(@trace2) + @missing_bytes) = length(@trace) @query2 = @query
-13782 1 1
+13668 1 1
select length(@query2) + length(@trace2)
between (@@optimizer_trace_max_mem_size-200) and (@@optimizer_trace_max_mem_size+200);
length(@query2) + length(@trace2)
between (@@optimizer_trace_max_mem_size-200) and (@@optimizer_trace_max_mem_size+200)
-1
+0
select instr(@trace, @trace2) = 1;
instr(@trace, @trace2) = 1
1
@@ -1412,14 +1388,6 @@ explain SELECT c FROM t5 where c+1 in (s
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -1702,14 +1670,6 @@ explain SELECT c FROM t5 where c+1 in (s
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -2465,14 +2425,6 @@ explain extended select * from t1 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -2741,14 +2693,6 @@ explain extended select * from t1 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -3354,14 +3298,6 @@ where a1 in (select b1 from t2_16 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -3639,14 +3575,6 @@ WHERE c2 IN ( SELECT c2 FROM t2 WHERE c2
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -4378,14 +4306,6 @@ concat(c1,'y') IN
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -4414,14 +4334,6 @@ concat(c1,'y') IN
"transformation": {
"select#": 3,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 3,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -4884,14 +4796,6 @@ trace
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -4933,14 +4837,6 @@ trace
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -5047,14 +4943,6 @@ trace
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -5356,14 +5244,6 @@ select * from t1 where (t1.a,t1.b) not i
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -7420,14 +7300,6 @@ select d into res from t6 where d in (se
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -9177,14 +9049,6 @@ select d into res from t6 where d in (se
"select#": 2,
"from": "IN (SELECT)",
"to": "semijoin",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
"chosen": false
} /* transformation */
},
=== modified file 'mysql-test/suite/opt_trace/r/general_ps_prot_all.result'
--- a/mysql-test/suite/opt_trace/r/general_ps_prot_all.result 2012-01-30 08:57:24 +0000
+++ b/mysql-test/suite/opt_trace/r/general_ps_prot_all.result 2012-02-08 15:25:17 +0000
@@ -1005,7 +1005,8 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "in UNION"
} /* transformation */
}
] /* steps */
@@ -1031,7 +1032,8 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"select#": 3,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "in UNION"
} /* transformation */
}
] /* steps */
@@ -1210,7 +1212,8 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"select#": "fake",
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "in UNION"
} /* transformation */
}
] /* steps */
@@ -1321,8 +1324,8 @@ select (@query:=QUERY)+NULL, (@trace:=TR
NULL NULL
select length(@trace);
length(@trace)
-13765
-set optimizer_trace_max_mem_size=13900;
+13894
+set optimizer_trace_max_mem_size=14100;
select length(@query)+length(@trace) > @@optimizer_trace_max_mem_size;
length(@query)+length(@trace) > @@optimizer_trace_max_mem_size
0
@@ -1338,7 +1341,7 @@ select length(@trace2),
(length(@trace2) + @missing_bytes) = length(@trace),
@query2 = @query;
length(@trace2) (length(@trace2) + @missing_bytes) = length(@trace) @query2 = @query
-13765 1 1
+13894 1 1
select length(@query2) + length(@trace2)
between (@@optimizer_trace_max_mem_size-200) and (@@optimizer_trace_max_mem_size+200);
length(@query2) + length(@trace2)
@@ -1701,6 +1704,8 @@ explain SELECT c FROM t5 where c+1 in (s
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": true,
"chosen": true
} /* transformation */
}
@@ -2484,14 +2489,6 @@ explain extended select * from t1 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -2760,14 +2757,6 @@ explain extended select * from t1 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -3375,7 +3364,7 @@ where a1 in (select b1 from t2_16 where
"from": "IN (SELECT)",
"to": "materialization",
"chosen": false,
- "cause": "field_types"
+ "cause": "inner blob"
} /* transformation */
},
{
@@ -4400,6 +4389,8 @@ concat(c1,'y') IN
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": true,
"chosen": true
} /* transformation */
}
@@ -4426,6 +4417,8 @@ concat(c1,'y') IN
"select#": 3,
"from": "IN (SELECT)",
"to": "materialization",
+ "has_nullable_expressions": true,
+ "treat_UNKNOWN_as_FALSE": true,
"chosen": true
} /* transformation */
}
@@ -6081,7 +6074,8 @@ select * from t1 where (t1.a,t1.b) not i
"select#": 2,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "already have strategy"
} /* transformation */
}
] /* steps */
=== modified file 'mysql-test/suite/opt_trace/r/general_ps_prot_none.result'
--- a/mysql-test/suite/opt_trace/r/general_ps_prot_none.result 2012-01-30 08:57:24 +0000
+++ b/mysql-test/suite/opt_trace/r/general_ps_prot_none.result 2012-02-08 15:25:17 +0000
@@ -998,14 +998,6 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -1024,14 +1016,6 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 3,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -1203,14 +1187,6 @@ SELECT * FROM t5 WHERE 5 IN (SELECT 1 FR
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": "fake",
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -1320,8 +1296,8 @@ select (@query:=QUERY)+NULL, (@trace:=TR
NULL NULL
select length(@trace);
length(@trace)
-13765
-set optimizer_trace_max_mem_size=13900;
+12890
+set optimizer_trace_max_mem_size=14100;
select length(@query)+length(@trace) > @@optimizer_trace_max_mem_size;
length(@query)+length(@trace) > @@optimizer_trace_max_mem_size
0
@@ -1337,12 +1313,12 @@ select length(@trace2),
(length(@trace2) + @missing_bytes) = length(@trace),
@query2 = @query;
length(@trace2) (length(@trace2) + @missing_bytes) = length(@trace) @query2 = @query
-13765 1 1
+12890 1 1
select length(@query2) + length(@trace2)
between (@@optimizer_trace_max_mem_size-200) and (@@optimizer_trace_max_mem_size+200);
length(@query2) + length(@trace2)
between (@@optimizer_trace_max_mem_size-200) and (@@optimizer_trace_max_mem_size+200)
-1
+0
select instr(@trace, @trace2) = 1;
instr(@trace, @trace2) = 1
1
@@ -1392,14 +1368,6 @@ explain SELECT c FROM t5 where c+1 in (s
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -1682,14 +1650,6 @@ explain SELECT c FROM t5 where c+1 in (s
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -2445,14 +2405,6 @@ explain extended select * from t1 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -2721,14 +2673,6 @@ explain extended select * from t1 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -3334,14 +3278,6 @@ where a1 in (select b1 from t2_16 where
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -3614,14 +3550,6 @@ WHERE c2 IN ( SELECT c2 FROM t2 WHERE c2
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -4348,14 +4276,6 @@ concat(c1,'y') IN
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -4384,14 +4304,6 @@ concat(c1,'y') IN
"transformation": {
"select#": 3,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 3,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -4854,14 +4766,6 @@ trace
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -4903,14 +4807,6 @@ trace
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -5017,14 +4913,6 @@ trace
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -5321,14 +5209,6 @@ select * from t1 where (t1.a,t1.b) not i
"to": "semijoin",
"chosen": false
} /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
}
] /* steps */
} /* join_preparation */
@@ -7340,14 +7220,6 @@ select d into res from t6 where d in (se
"transformation": {
"select#": 2,
"from": "IN (SELECT)",
- "to": "materialization",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
"to": "EXISTS (CORRELATED SELECT)",
"chosen": true,
"evaluating_constant_where_conditions": [
@@ -9111,14 +8983,6 @@ select d into res from t6 where d in (se
"select#": 2,
"from": "IN (SELECT)",
"to": "semijoin",
- "chosen": false
- } /* transformation */
- },
- {
- "transformation": {
- "select#": 2,
- "from": "IN (SELECT)",
- "to": "materialization",
"chosen": false
} /* transformation */
},
=== modified file 'mysql-test/suite/opt_trace/r/subquery_no_prot.result'
--- a/mysql-test/suite/opt_trace/r/subquery_no_prot.result 2012-01-26 13:09:59 +0000
+++ b/mysql-test/suite/opt_trace/r/subquery_no_prot.result 2012-02-08 15:25:17 +0000
@@ -996,7 +996,8 @@ field4,field5,field6 {
"select#": 6,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "correlated"
} /* transformation */
},
{
=== modified file 'mysql-test/suite/opt_trace/r/subquery_ps_prot.result'
--- a/mysql-test/suite/opt_trace/r/subquery_ps_prot.result 2012-01-30 08:57:24 +0000
+++ b/mysql-test/suite/opt_trace/r/subquery_ps_prot.result 2012-02-08 15:25:17 +0000
@@ -984,7 +984,8 @@ field4,field5,field6 {
"select#": 6,
"from": "IN (SELECT)",
"to": "materialization",
- "chosen": false
+ "chosen": false,
+ "cause": "correlated"
} /* transformation */
}
] /* steps */
=== added file 'mysql-test/t/debug_sync2-master.opt'
--- a/mysql-test/t/debug_sync2-master.opt 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/debug_sync2-master.opt 2012-02-08 20:52:22 +0000
@@ -0,0 +1 @@
+--loose-debug-sync-timeout=1
=== added file 'mysql-test/t/debug_sync2.test'
--- a/mysql-test/t/debug_sync2.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/debug_sync2.test 2012-02-08 20:52:22 +0000
@@ -0,0 +1,25 @@
+--source include/have_innodb.inc
+--source include/have_debug_sync.inc
+
+--echo #
+--echo # Bug#13688248 CRASH IN DIAGNOSTICS_AREA::SET_OK_STATUS WHEN USING DEBUG_SYNC
+--echo #
+
+SET SESSION DEBUG_SYNC= 'RESET';
+
+CREATE TABLE t1 (pk INT, PRIMARY KEY(pk));
+
+connect (con1,localhost,root,,);
+connection con1;
+SET SESSION sql_mode=TRADITIONAL;
+SET SESSION autocommit=1;
+
+INSERT INTO t1 VALUES(1);
+
+connection con1;
+SET SESSION debug_sync='write_row_replace SIGNAL go_ahead1 WAIT_FOR comes_never ';
+--send
+REPLACE INTO t1 ( pk ) VALUES ( 1 );
+--reap;
+
+DROP TABLE t1;
=== modified file 'mysql-test/t/events_restart.test'
--- a/mysql-test/t/events_restart.test 2011-05-04 12:59:24 +0000
+++ b/mysql-test/t/events_restart.test 2012-02-09 14:56:44 +0000
@@ -106,3 +106,26 @@ let $wait_condition=
select count(*) = 0 from information_schema.processlist
where db='events_test' and command = 'Connect' and user=current_user();
--source include/wait_condition.inc
+
+--echo #
+--echo # Test for bug#11748899 -- EVENT SET TO DISABLED AND ON COMPLETION
+--echo # NOT PRESERVE IS DELETED AT SERVER
+--echo #
+SELECT @@event_scheduler;
+USE test;
+--disable_warnings
+DROP EVENT IF EXISTS e1;
+--enable_warnings
+CREATE EVENT e1 ON SCHEDULE EVERY 1 SECOND DISABLE DO SELECT 1;
+--replace_column 6 # 9 # 10 #
+SHOW EVENTS;
+
+--echo "Now we restart the server"
+--source include/restart_mysqld.inc
+USE test;
+SELECT @@event_scheduler;
+--replace_column 6 # 9 # 10 #
+SHOW EVENTS;
+DROP EVENT e1;
+
+--echo # end test for bug#11748899
=== modified file 'mysql-test/t/heap.test'
--- a/mysql-test/t/heap.test 2011-09-27 12:17:43 +0000
+++ b/mysql-test/t/heap.test 2012-02-09 12:17:37 +0000
@@ -516,3 +516,19 @@ WHERE ('h', 0) NOT IN ( SELECT * FROM v1
DROP TABLE t1,t2,h1;
DROP VIEW v1;
+
+#
+# BUG 11755870 - 47704: HASH INDEX ON VARCHAR PREFIX NOT WORKING CORRECTLY.
+#
+CREATE TABLE t1 (
+ c1 VARCHAR(10) NOT NULL,
+ KEY i1 (c1(3))
+) ENGINE=MEMORY DEFAULT CHARSET=latin1;
+INSERT INTO t1 VALUES ('foo1'), ('bar2'), ('baz3');
+
+SELECT * FROM t1 WHERE c1='bar2';
+--echo #should show one tuple!
+
+SELECT * FROM t1 IGNORE INDEX (i1) WHERE c1='bar2';
+--echo #should show one tuple!
+DROP TABLE t1;
=== modified file 'mysql-test/t/read_only.test'
--- a/mysql-test/t/read_only.test 2009-03-06 14:56:17 +0000
+++ b/mysql-test/t/read_only.test 2012-02-09 12:57:42 +0000
@@ -169,23 +169,19 @@ connection default;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
set global read_only=1;
unlock tables ;
-# The following call blocks until con1 releases the read lock.
-# Blocking is a limitation, and could be improved.
---echo send set global read_only=1;
-send set global read_only=1;
+
+# after unlock tables in current connection
+# the next command must be executed successfully
+set global read_only=1;
+select @@global.read_only;
--echo connection con1;
connection con1;
select @@global.read_only;
unlock tables ;
-let $wait_condition= SELECT @@global.read_only= 1;
---source include/wait_condition.inc
-select @@global.read_only;
--echo connection default;
connection default;
---echo reap;
-reap;
# pending transaction / READ_ONLY
# - is an error in the same connection
=== modified file 'sql/debug_sync.cc'
--- a/sql/debug_sync.cc 2012-01-24 11:24:54 +0000
+++ b/sql/debug_sync.cc 2012-02-08 20:52:22 +0000
@@ -1788,8 +1788,12 @@ static void debug_sync_execute(THD *thd,
sig_wait, sig_glob, error));});
if (error == ETIMEDOUT || error == ETIME)
{
+ // We should not make the statement fail, even if in strict mode.
+ const bool save_abort_on_warning= thd->abort_on_warning;
+ thd->abort_on_warning= false;
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_DEBUG_SYNC_TIMEOUT, ER(ER_DEBUG_SYNC_TIMEOUT));
+ thd->abort_on_warning= save_abort_on_warning;
break;
}
error= 0;
=== modified file 'sql/events.cc'
--- a/sql/events.cc 2011-10-27 08:43:56 +0000
+++ b/sql/events.cc 2012-02-09 14:56:44 +0000
@@ -825,7 +825,16 @@ Events::init(my_bool opt_noacl_or_bootst
*/
thd->thread_stack= (char*) &thd;
thd->store_globals();
-
+ /*
+ Set current time for the thread that handles events.
+ Current time is stored in data member start_time of THD class.
+ Subsequently, this value is used to check whether event was expired
+ when make loading events from storage. Check for event expiration time
+ is done at Event_queue_element::compute_next_execution_time() where
+ event's status set to Event_parse_data::DISABLED and dropped flag set
+ to true if event was expired.
+ */
+ thd->set_time();
/*
We will need Event_db_repository anyway, even if the scheduler is
disabled - to perform events DDL.
@@ -1109,7 +1118,6 @@ Events::load_events_from_db(THD *thd)
{
Event_queue_element *et;
bool created;
- bool drop_on_completion;
if (!(et= new Event_queue_element))
goto end;
@@ -1124,9 +1132,6 @@ Events::load_events_from_db(THD *thd)
delete et;
goto end;
}
- drop_on_completion= (et->on_completion ==
- Event_parse_data::ON_COMPLETION_DROP);
-
if (event_queue->create_event(thd, et, &created))
{
@@ -1136,7 +1141,7 @@ Events::load_events_from_db(THD *thd)
}
if (created)
count++;
- else if (drop_on_completion)
+ else if (et->dropped)
{
/*
If not created, a stale event - drop if immediately if
=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc 2012-02-08 10:33:37 +0000
+++ b/sql/item_cmpfunc.cc 2012-02-08 15:25:17 +0000
@@ -1943,8 +1943,11 @@ void Item_in_optimizer::fix_after_pullou
/**
The implementation of optimized \<outer expression\> [NOT] IN \<subquery\>
- predicates. The implementation works as follows.
+ predicates. It applies to predicates which have gone through the IN->EXISTS
+ transformation in in_to_exists_transformer functions; not to subquery
+ materialization (which has no triggered conditions).
+ The implementation works as follows.
For the current value of the outer expression
- If it contains only NULL values, the original (before rewrite by the
@@ -2021,12 +2024,14 @@ longlong Item_in_optimizer::val_int()
if (cache->null_value)
{
+ Item_in_subselect * const item_subs=
+ static_cast<Item_in_subselect *>(args[1]);
/*
We're evaluating
"<outer_value_list> [NOT] IN (SELECT <inner_value_list>...)"
where one or more of the outer values is NULL.
*/
- if (((Item_in_subselect*)args[1])->is_top_level_item())
+ if (item_subs->is_top_level_item())
{
/*
We're evaluating a top level item, e.g.
@@ -2049,7 +2054,6 @@ longlong Item_in_optimizer::val_int()
SELECT evaluated over the non-NULL values produces at least
one row, FALSE otherwise
*/
- Item_in_subselect *item_subs=(Item_in_subselect*)args[1];
bool all_left_cols_null= true;
const uint ncols= cache->cols();
@@ -2080,7 +2084,7 @@ longlong Item_in_optimizer::val_int()
{
/* The subquery has to be evaluated */
(void) item_subs->val_bool_result();
- if (item_subs->engine->no_rows())
+ if (!item_subs->value)
null_value= item_subs->null_value;
else
null_value= TRUE;
=== modified file 'sql/item_cmpfunc.h'
--- a/sql/item_cmpfunc.h 2012-02-08 10:33:37 +0000
+++ b/sql/item_cmpfunc.h 2012-02-08 15:25:17 +0000
@@ -255,7 +255,7 @@ class Item_cache;
class Item_in_optimizer: public Item_bool_func
{
-protected:
+private:
Item_cache *cache;
bool save_cache;
/*
@@ -1481,7 +1481,8 @@ class Item_in_subselect;
/*
This is like IS NOT NULL but it also remembers if it ever has
- encountered a NULL.
+ encountered a NULL; it remembers this in the "was_null" property of the
+ "owner" item.
*/
class Item_is_not_null_test :public Item_func_isnull
{
=== modified file 'sql/item_subselect.cc'
--- a/sql/item_subselect.cc 2012-01-17 09:45:08 +0000
+++ b/sql/item_subselect.cc 2012-02-08 15:25:17 +0000
@@ -151,7 +151,7 @@ void Item_in_subselect::cleanup()
delete left_expr_cache;
left_expr_cache= NULL;
}
- first_execution= TRUE;
+ left_expr_cache_filled= false;
need_expr_cache= TRUE;
Item_subselect::cleanup();
DBUG_VOID_RETURN;
@@ -452,20 +452,22 @@ bool Item_in_subselect::exec()
init_left_expr_cache())
DBUG_RETURN(TRUE);
- /* If the new left operand is already in the cache, reuse the old result. */
- if (left_expr_cache && test_if_item_cache_changed(*left_expr_cache) < 0)
+ if (left_expr_cache != NULL)
{
- /* Always compute IN for the first row as the cache is not valid for it. */
- if (!first_execution)
- DBUG_RETURN(FALSE);
- first_execution= FALSE;
+ const int result= test_if_item_cache_changed(*left_expr_cache);
+ if (left_expr_cache_filled && // cache was previously filled
+ result < 0) // new value is identical to previous cached value
+ {
+ /*
+ We needn't do a full execution, can just reuse "value", "was_null",
+ "null_value" of the previous execution.
+ */
+ DBUG_RETURN(false);
+ }
+ left_expr_cache_filled= true;
}
- /*
- The exec() method below updates item::value, and item::null_value, thus if
- we don't call it, the next call to item::val_int() will return whatever
- result was computed by its previous call.
- */
+ null_value= was_null= false;
const bool retval= Item_subselect::exec();
DBUG_RETURN(retval);
}
@@ -888,7 +890,7 @@ bool Item_in_subselect::test_limit(st_se
Item_in_subselect::Item_in_subselect(Item * left_exp,
st_select_lex *select_lex):
Item_exists_subselect(), left_expr(left_exp), left_expr_cache(NULL),
- first_execution(TRUE), need_expr_cache(TRUE), expr(NULL),
+ left_expr_cache_filled(false), need_expr_cache(TRUE), expr(NULL),
optimizer(NULL), was_null(FALSE), abort_on_null(FALSE),
pushed_cond_guards(NULL), upper_item(NULL)
{
@@ -1019,7 +1021,6 @@ double Item_in_subselect::val_real()
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
- null_value= was_null= FALSE;
if (exec())
{
reset();
@@ -1039,7 +1040,6 @@ longlong Item_in_subselect::val_int()
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
- null_value= was_null= FALSE;
if (exec())
{
reset();
@@ -1059,7 +1059,6 @@ String *Item_in_subselect::val_str(Strin
*/
DBUG_ASSERT(0);
DBUG_ASSERT(fixed == 1);
- null_value= was_null= FALSE;
if (exec())
{
reset();
@@ -1078,7 +1077,6 @@ String *Item_in_subselect::val_str(Strin
bool Item_in_subselect::val_bool()
{
DBUG_ASSERT(fixed == 1);
- null_value= was_null= FALSE;
if (exec())
{
reset();
@@ -1096,7 +1094,6 @@ my_decimal *Item_in_subselect::val_decim
method should not be used
*/
DBUG_ASSERT(0);
- null_value= was_null= FALSE;
DBUG_ASSERT(fixed == 1);
if (exec())
{
@@ -2230,28 +2227,6 @@ bool subselect_union_engine::is_executed
}
-/*
- Check if last execution of the subquery engine produced any rows
-
- SYNOPSIS
- subselect_union_engine::no_rows()
-
- DESCRIPTION
- Check if last execution of the subquery engine produced any rows. The
- return value is undefined if last execution ended in an error.
-
- RETURN
- TRUE - Last subselect execution has produced no rows
- FALSE - Otherwise
-*/
-
-bool subselect_union_engine::no_rows() const
-{
- /* Check if we got any rows when reading UNION result from temp. table: */
- return test(!unit->fake_select_lex->join->send_records);
-}
-
-
subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
select_result_interceptor *result_arg,
Item_subselect *item_arg)
@@ -2325,7 +2300,7 @@ bool subselect_union_engine::prepare()
}
-bool subselect_uniquesubquery_engine::prepare()
+bool subselect_indexsubquery_engine::prepare()
{
/* Should never be called. */
DBUG_ASSERT(FALSE);
@@ -2333,27 +2308,6 @@ bool subselect_uniquesubquery_engine::pr
}
-/*
- Check if last execution of the subquery engine produced any rows
-
- SYNOPSIS
- subselect_single_select_engine::no_rows()
-
- DESCRIPTION
- Check if last execution of the subquery engine produced any rows. The
- return value is undefined if last execution ended in an error.
-
- RETURN
- TRUE - Last subselect execution has produced no rows
- FALSE - Otherwise
-*/
-
-bool subselect_single_select_engine::no_rows() const
-{
- return !item->assigned();
-}
-
-
/*
makes storage for the output values for the subquery and calcuates
their data and column types and their nullability.
@@ -2407,7 +2361,7 @@ void subselect_union_engine::fix_length_
}
}
-void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row)
+void subselect_indexsubquery_engine::fix_length_and_dec(Item_cache **row)
{
//this never should be called
DBUG_ASSERT(0);
@@ -2548,29 +2502,23 @@ bool subselect_union_engine::exec()
}
-/*
- Search for at least one row satisfying select condition
-
- SYNOPSIS
- subselect_uniquesubquery_engine::scan_table()
+/**
+ Search, using a table scan, for at least one row satisfying select
+ condition.
- DESCRIPTION
- Scan the table using sequential access until we find at least one row
- satisfying select condition.
-
- The caller must set this->empty_result_set=FALSE before calling this
- function. This function will set it to TRUE if it finds a matching row.
+ The caller must set item's 'value' to 'false' before calling this
+ function. This function will set it to 'true' if it finds a matching row.
- RETURN
- FALSE - OK
- TRUE - Error
+ @returns false if ok, true if read error.
*/
-
-bool subselect_uniquesubquery_engine::scan_table()
+bool subselect_indexsubquery_engine::scan_table()
{
int error;
TABLE *table= tab->table;
- DBUG_ENTER("subselect_uniquesubquery_engine::scan_table");
+ DBUG_ENTER("subselect_indexsubquery_engine::scan_table");
+
+ // We never need to do a table scan of the materialized table.
+ DBUG_ASSERT(engine_type() != HASH_SJ_ENGINE);
if (table->file->inited)
table->file->ha_index_end();
@@ -2594,7 +2542,6 @@ bool subselect_uniquesubquery_engine::sc
if (!cond || cond->val_int())
{
static_cast<Item_in_subselect*>(item)->value= true;
- empty_result_set= FALSE;
break;
}
}
@@ -2640,7 +2587,7 @@ bool subselect_uniquesubquery_engine::sc
value of NULL, not rows that match if the "inner_col IS NULL"
condition is disabled. Index lookup can be used for this.
- @see subselect_uniquesubquery_engine::exec()
+ @see subselect_indexsubquery_engine::exec()
@see Item_in_optimizer::val_int()
@param[out] require_scan true if a NULL value is found that falls
@@ -2651,10 +2598,10 @@ bool subselect_uniquesubquery_engine::sc
otherwise.
*/
-void subselect_uniquesubquery_engine::copy_ref_key(bool *require_scan,
- bool *convert_error)
+void subselect_indexsubquery_engine::copy_ref_key(bool *require_scan,
+ bool *convert_error)
{
- DBUG_ENTER("subselect_uniquesubquery_engine::copy_ref_key");
+ DBUG_ENTER("subselect_indexsubquery_engine::copy_ref_key");
*require_scan= false;
*convert_error= false;
@@ -2669,6 +2616,15 @@ void subselect_uniquesubquery_engine::co
if (s_key->null_key)
{
+ /*
+ If we have materialized the subquery:
+ - this NULL ref item cannot be local to the subquery (any such
+ conditions was handled during materialization)
+ - neither can it be outer, because this case is
+ separately managed in subselect_hash_sj_engine::exec().
+ */
+ DBUG_ASSERT(engine_type() != HASH_SJ_ENGINE);
+
const bool *cond_guard= tab->ref.cond_guards[part_no];
/*
@@ -2711,100 +2667,6 @@ void subselect_uniquesubquery_engine::co
/*
- Execute subselect
-
- SYNOPSIS
- subselect_uniquesubquery_engine::exec()
-
- DESCRIPTION
- Find rows corresponding to the ref key using index access.
- If some part of the lookup key is NULL, then we're evaluating
- NULL IN (SELECT ... )
- This is a special case, we don't need to search for NULL in the table,
- instead, the result value is
- - NULL if select produces empty row set
- - FALSE otherwise.
-
- In some cases (IN subselect is a top level item, i.e. abort_on_null==TRUE)
- the caller doesn't distinguish between NULL and FALSE result and we just
- return FALSE.
- Otherwise we make a full table scan to see if there is at least one
- matching row.
-
- The result of this function (info about whether a row was found) is
- stored in this->empty_result_set.
- NOTE
-
- RETURN
- FALSE - ok
- TRUE - an error occured while scanning
-*/
-
-bool subselect_uniquesubquery_engine::exec()
-{
- DBUG_ENTER("subselect_uniquesubquery_engine::exec");
- int error;
- TABLE *table= tab->table;
- TABLE_LIST *tl= table->pos_in_table_list;
- empty_result_set= TRUE;
- table->status= 0;
-
- if (engine_type() == UNIQUESUBQUERY_ENGINE &&
- tl->uses_materialization() && !tl->materialized)
- {
- bool err= mysql_handle_single_derived(table->in_use->lex, tl,
- mysql_derived_create) ||
- mysql_handle_single_derived(table->in_use->lex, tl,
- mysql_derived_materialize);
- if (!tab->table->in_use->lex->describe)
- mysql_handle_single_derived(table->in_use->lex, tl,
- mysql_derived_cleanup);
- if (err)
- DBUG_RETURN(1);
- }
-
- /* Copy the ref key and check for nulls... */
- bool require_scan, convert_error;
- copy_ref_key(&require_scan, &convert_error);
- if (convert_error)
- {
- ((Item_in_subselect *) item)->value= 0;
- DBUG_RETURN(0);
- }
-
- if (require_scan)
- {
- const bool scan_result= scan_table();
- DBUG_RETURN(scan_result);
- }
- if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key, 0);
- error= table->file->ha_index_read_map(table->record[0],
- tab->ref.key_buff,
- make_prev_keypart_map(tab->ref.key_parts),
- HA_READ_KEY_EXACT);
- DBUG_PRINT("info", ("lookup result: %i", error));
- if (error &&
- error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
- error= report_error(table, error);
- else
- {
- error= 0;
- table->null_row= 0;
- if (!table->status && (!cond || cond->val_int()))
- {
- ((Item_in_subselect *) item)->value= 1;
- empty_result_set= FALSE;
- }
- else
- ((Item_in_subselect *) item)->value= 0;
- }
-
- DBUG_RETURN(error != 0);
-}
-
-
-/*
Index-lookup subselect 'engine' - run the subquery
SYNOPSIS
@@ -2825,6 +2687,8 @@ bool subselect_uniquesubquery_engine::ex
3. If check_null==TRUE, make another lookup via key=NULL, search for a
row that satisfies subq_where. If found, return NULL, otherwise
return FALSE.
+ 4. If unique==true, there can be only one row with key=oe and only one row
+ with key=NULL, we use that fact to shorten the search process.
TODO
The step #1 can be optimized further when the index has several key
@@ -2862,13 +2726,13 @@ bool subselect_indexsubquery_engine::exe
int error;
bool null_finding= 0;
TABLE *table= tab->table;
+ // 'tl' is NULL if this is a tmp table created by subselect_hash_sj_engine.
TABLE_LIST *tl= table->pos_in_table_list;
-
- ((Item_in_subselect *) item)->value= 0;
- empty_result_set= TRUE;
+ Item_in_subselect *const item_in= static_cast<Item_in_subselect*>(item);
+ item_in->value= false;
table->status= 0;
- if (tl->uses_materialization() && !tl->materialized)
+ if (tl && tl->uses_materialization() && !tl->materialized)
{
bool err= mysql_handle_single_derived(table->in_use->lex, tl,
mysql_derived_create) ||
@@ -2885,17 +2749,14 @@ bool subselect_indexsubquery_engine::exe
{
/* We need to check for NULL if there wasn't a matching value */
*tab->ref.null_ref_key= 0; // Search first for not null
- ((Item_in_subselect *) item)->was_null= 0;
+ item_in->was_null= false;
}
/* Copy the ref key and check for nulls... */
bool require_scan, convert_error;
copy_ref_key(&require_scan, &convert_error);
if (convert_error)
- {
- ((Item_in_subselect *) item)->value= 0;
DBUG_RETURN(0);
- }
if (require_scan)
{
@@ -2904,7 +2765,7 @@ bool subselect_indexsubquery_engine::exe
}
if (!table->file->inited)
- table->file->ha_index_init(tab->ref.key, 1);
+ table->file->ha_index_init(tab->ref.key, !unique /* sorted */);
error= table->file->ha_index_read_map(table->record[0],
tab->ref.key_buff,
make_prev_keypart_map(tab->ref.key_parts),
@@ -2922,13 +2783,21 @@ bool subselect_indexsubquery_engine::exe
{
if ((!cond || cond->val_int()) && (!having || having->val_int()))
{
- empty_result_set= FALSE;
+ item_in->value= true;
if (null_finding)
- ((Item_in_subselect *) item)->was_null= 1;
- else
- ((Item_in_subselect *) item)->value= 1;
+ {
+ /*
+ This is dead code; subqueries with check_null==true are always
+ transformed with IN-to-EXISTS and thus their artificial HAVING
+ rejects NULL values...
+ */
+ DBUG_ASSERT(false);
+ item_in->was_null= true;
+ }
break;
}
+ if (unique)
+ break;
error= table->file->ha_index_next_same(table->record[0],
tab->ref.key_buff,
tab->ref.key_length);
@@ -2942,9 +2811,14 @@ bool subselect_indexsubquery_engine::exe
{
if (!check_null || null_finding)
break; /* We don't need to check nulls */
+ /*
+ Check if there exists a row with a null value in the index. We come
+ here only if ref_or_null, and ref_or_null is always on a single
+ column (first keypart of the index). So we have only one NULL bit to
+ turn on:
+ */
*tab->ref.null_ref_key= 1;
null_finding= 1;
- /* Check if there exists a row with a null value in the index */
if ((error= (safe_index_read(tab) == 1)))
break;
}
@@ -2990,7 +2864,7 @@ void subselect_union_engine::exclude()
}
-void subselect_uniquesubquery_engine::exclude()
+void subselect_indexsubquery_engine::exclude()
{
//this never should be called
DBUG_ASSERT(0);
@@ -3085,41 +2959,12 @@ void subselect_union_engine::print(Strin
}
-void subselect_uniquesubquery_engine::print(String *str,
- enum_query_type query_type)
-{
- char *table_name= tab->table->s->table_name.str;
- str->append(STRING_WITH_LEN("<primary_index_lookup>("));
- tab->ref.items[0]->print(str, query_type);
- str->append(STRING_WITH_LEN(" in "));
- if (tab->table->s->table_category == TABLE_CATEGORY_TEMPORARY)
- {
- /*
- Temporary tables' names change across runs, so they can't be used for
- EXPLAIN EXTENDED.
- */
- str->append(STRING_WITH_LEN("<temporary table>"));
- }
- else
- str->append(table_name, tab->table->s->table_name.length);
- KEY *key_info= tab->table->key_info+ tab->ref.key;
- str->append(STRING_WITH_LEN(" on "));
- str->append(key_info->name);
- if (cond)
- {
- str->append(STRING_WITH_LEN(" where "));
- cond->print(str, query_type);
- }
- str->append(')');
-}
-
-
/*
TODO:
-The above ::print method should be changed as below. Do it after
+The ::print method below should be changed as follows. Do it after
all other tests pass.
-void subselect_uniquesubquery_engine::print(String *str)
+void subselect_indexsubquery_engine::print(String *str)
{
KEY *key_info= tab->table->key_info + tab->ref.key;
str->append(STRING_WITH_LEN("<primary_index_lookup>("));
@@ -3141,17 +2986,27 @@ void subselect_uniquesubquery_engine::pr
void subselect_indexsubquery_engine::print(String *str,
enum_query_type query_type)
{
- str->append(STRING_WITH_LEN("<index_lookup>("));
+ if (unique)
+ str->append(STRING_WITH_LEN("<primary_index_lookup>("));
+ else
+ str->append(STRING_WITH_LEN("<index_lookup>("));
tab->ref.items[0]->print(str, query_type);
str->append(STRING_WITH_LEN(" in "));
- /*
- For materialized derived tables/views use table/view alias instead of
- temporary table name, as it changes on each run and not acceptable for
- EXPLAIN EXTENDED.
- */
if (tab->table->pos_in_table_list &&
- tab->table->pos_in_table_list->uses_materialization())
+ tab->table->pos_in_table_list->uses_materialization())
+ {
+ /*
+ For materialized derived tables/views use table/view alias instead of
+ temporary table name, as it changes on each run and not acceptable for
+ EXPLAIN EXTENDED.
+ */
str->append(tab->table->alias, strlen(tab->table->alias));
+ }
+ else if (tab->table->s->table_category == TABLE_CATEGORY_TEMPORARY)
+ {
+ // Could be from subselect_hash_sj_engine.
+ str->append(STRING_WITH_LEN("<temporary table>"));
+ }
else
str->append(tab->table->s->table_name.str, tab->table->s->table_name.length);
KEY *key_info= tab->table->key_info+ tab->ref.key;
@@ -3227,8 +3082,8 @@ bool subselect_union_engine::change_resu
TRUE error
*/
-bool subselect_uniquesubquery_engine::change_result(Item_subselect *si,
- select_result_interceptor *res)
+bool subselect_indexsubquery_engine::change_result(Item_subselect *si,
+ select_result_interceptor *res)
{
DBUG_ASSERT(0);
return TRUE;
@@ -3293,7 +3148,7 @@ bool subselect_union_engine::no_tables()
FALSE there are some tables in subquery
*/
-bool subselect_uniquesubquery_engine::no_tables() const
+bool subselect_indexsubquery_engine::no_tables() const
{
/* returning value is correct, but this method should never be called */
return 0;
@@ -3310,7 +3165,8 @@ bool subselect_uniquesubquery_engine::no
@detail
- Create a temporary table to store the result of the IN subquery. The
- temporary table has one hash index on all its columns.
+ temporary table has one hash index on all its columns. If single-column,
+ the index allows at most one NULL row.
- Create a new result sink that sends the result stream of the subquery to
the temporary table,
- Create and initialize a new JOIN_TAB, and TABLE_REF objects to perform
@@ -3393,7 +3249,7 @@ bool subselect_hash_sj_engine::setup(Lis
plan operator into the materialized subquery result. Notice that:
- this JOIN_TAB has no corresponding JOIN (and doesn't need one), and
- here we initialize only those members that are used by
- subselect_uniquesubquery_engine, so these objects are incomplete.
+ subselect_indexsubquery_engine, so these objects are incomplete.
*/
JOIN_TAB * const tmp_tab= new (thd->mem_root) JOIN_TAB;
if (tmp_tab == NULL)
@@ -3414,11 +3270,14 @@ bool subselect_hash_sj_engine::setup(Lis
/*
Create an artificial condition to post-filter those rows matched by index
lookups that cannot be distinguished by the index lookup procedure, e.g.
- because of truncation. Prepared statements execution requires that
- fix_fields is called for every execution. In order to call fix_fields we
- need to create a Name_resolution_context and a corresponding TABLE_LIST
- for the temporary table for the subquery, so that all column references
- to the materialized subquery table can be resolved correctly.
+ because of truncation (if the outer column type's length is bigger than
+ the inner column type's, index lookup will use a truncated outer
+ value as search key, yielding false positives).
+ Prepared statements execution requires that fix_fields is called
+ for every execution. In order to call fix_fields we need to create a
+ Name_resolution_context and a corresponding TABLE_LIST for the temporary
+ table for the subquery, so that all column references to the materialized
+ subquery table can be resolved correctly.
*/
DBUG_ASSERT(cond == NULL);
if (!(cond= new Item_cond_and))
@@ -3448,7 +3307,7 @@ bool subselect_hash_sj_engine::setup(Lis
Item_func_eq *eq_cond;
/* Item for the corresponding field from the materialized temp table. */
Item_field *right_col_item;
- int null_count= test(key_parts[part_no].field->real_maybe_null());
+ const bool nullable= key_parts[part_no].field->real_maybe_null();
tmp_tab->ref.items[part_no]= item_in->left_expr->element_index(part_no);
if (!(right_col_item= new Item_field(thd, context,
@@ -3470,10 +3329,26 @@ bool subselect_hash_sj_engine::setup(Lis
cur_ref_buff + test(maybe_null), we could
use that information instead.
*/
- cur_ref_buff + null_count,
- null_count ? cur_ref_buff : 0,
+ cur_ref_buff + (nullable ? 1 : 0),
+ nullable ? cur_ref_buff : 0,
key_parts[part_no].length,
tmp_tab->ref.items[part_no]);
+ if (nullable && // nullable column in tmp table,
+ // and UNKNOWN should not be interpreted as FALSE
+ !item_in->is_top_level_item())
+ {
+ // It must be the single column, or we wouldn't be here
+ DBUG_ASSERT(tmp_key_parts == 1);
+ // Be ready to search for NULL into inner column:
+ tmp_tab->ref.null_ref_key= cur_ref_buff;
+ mat_table_has_nulls= NEX_UNKNOWN;
+ }
+ else
+ {
+ tmp_tab->ref.null_ref_key= NULL;
+ mat_table_has_nulls= NEX_IRRELEVANT_OR_FALSE;
+ }
+
cur_ref_buff+= key_parts[part_no].store_length;
}
tmp_tab->ref.key_err= 1;
@@ -3543,7 +3418,7 @@ void subselect_hash_sj_engine::cleanup()
bool subselect_hash_sj_engine::exec()
{
Item_in_subselect *item_in= (Item_in_subselect *) item;
-
+ TABLE *const table= tab->table;
DBUG_ENTER("subselect_hash_sj_engine::exec");
/*
@@ -3552,7 +3427,7 @@ bool subselect_hash_sj_engine::exec()
*/
if (!is_materialized)
{
- bool res= false;
+ bool res;
THD * const thd= item->unit->thd;
SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= materialize_engine->select_lex;
@@ -3576,21 +3451,10 @@ bool subselect_hash_sj_engine::exec()
unlocking).
*/
is_materialized= TRUE;
- /*
- If the subquery returned no rows, the temporary table is empty, so we know
- directly that the result of IN is FALSE. We first update the table
- statistics, then we test if the temporary table for the query result is
- empty.
- */
- tab->table->file->info(HA_STATUS_VARIABLE);
- if (!tab->table->file->stats.records)
- {
- empty_result_set= TRUE;
- item_in->value= FALSE;
- /* TODO: check we need this: item_in->null_value= FALSE; */
- thd->lex->current_select= save_select;
- DBUG_RETURN(FALSE);
- }
+
+ // Calculate row count:
+ table->file->info(HA_STATUS_VARIABLE);
+
/* Set tmp_param only if its usable, i.e. tmp_param->copy_field != NULL. */
tmp_param= &(item_in->unit->outer_select()->join->tmp_table_param);
if (tmp_param && !tmp_param->copy_field)
@@ -3600,12 +3464,71 @@ err:
thd->lex->current_select= save_select;
if (res)
DBUG_RETURN(res);
- }
+ } // if (!is_materialized)
+ if (table->file->stats.records == 0)
+ {
+ // The correct answer is FALSE.
+ item_in->value= false;
+ DBUG_RETURN(false);
+ }
/*
- Lookup the left IN operand in the hash index of the materialized subquery.
+ Here we could be brutal and set item_in->null_value. But we prefer to be
+ well-behaved and rather set the properties which
+ Item_in_subselect::val_bool() and Item_in_optimizer::val_int() expect,
+ and then those functions will set null_value based on those properties.
*/
- DBUG_RETURN(subselect_uniquesubquery_engine::exec());
+ if (item_in->left_expr->element_index(0)->null_value)
+ {
+ /*
+ The first outer expression oe1 is NULL. It is the single outer
+ expression because if there would be more ((oe1,oe2,...)IN(...)) then
+ either they would be non-nullable (so we wouldn't be here) or the
+ predicate would be top-level (so we wouldn't be here,
+ Item_in_optimizer::val_int() would have short-cut). The correct answer
+ is UNKNOWN. Do as if searching with all triggered conditions disabled:
+ this would surely find a row. The caller will translate this to UNKNOWN.
+ */
+ DBUG_ASSERT(item_in->left_expr->cols() == 1);
+ item_in->value= true;
+ DBUG_RETURN(false);
+ }
+
+ if (subselect_indexsubquery_engine::exec()) // Search with index
+ DBUG_RETURN(true);
+
+ if (!item_in->value && // no exact match
+ mat_table_has_nulls != NEX_IRRELEVANT_OR_FALSE)
+ {
+ /*
+ There is only one outer expression. It's not NULL. exec() above has set
+ the answer to FALSE, but if there exists an inner NULL in the temporary
+ table, then the correct answer is UNKNOWN, so let's find out.
+ */
+ if (mat_table_has_nulls == NEX_UNKNOWN) // We do not know yet
+ {
+ // Search for NULL inside tmp table, and remember the outcome.
+ DBUG_ASSERT(table->file->inited);
+ *tab->ref.null_ref_key= 1;
+ if (safe_index_read(tab) == 1)
+ DBUG_RETURN(true);
+ *tab->ref.null_ref_key= 0; // prepare for next searches of non-NULL
+ mat_table_has_nulls=
+ (table->status == 0) ? NEX_TRUE : NEX_IRRELEVANT_OR_FALSE;
+ }
+ if (mat_table_has_nulls == NEX_TRUE)
+ {
+ /*
+ There exists an inner NULL. The correct answer is UNKNOWN.
+ Do as if searching with all triggered conditions enabled; that
+ would not find any match, but Item_is_not_null_test would notice a
+ NULL:
+ */
+ item_in->value= false;
+ item_in->was_null= true;
+ }
+ }
+ DBUG_RETURN(false);
}
@@ -3619,7 +3542,7 @@ void subselect_hash_sj_engine::print(Str
materialize_engine->print(str, query_type);
str->append(STRING_WITH_LEN(" ), "));
if (tab)
- subselect_uniquesubquery_engine::print(str, query_type);
+ subselect_indexsubquery_engine::print(str, query_type);
else
str->append(STRING_WITH_LEN(
"<the access method for lookups is not yet created>"
=== modified file 'sql/item_subselect.h'
--- a/sql/item_subselect.h 2011-11-10 14:58:23 +0000
+++ b/sql/item_subselect.h 2012-02-08 15:25:17 +0000
@@ -320,7 +320,6 @@ public:
virtual void print(String *str, enum_query_type query_type);
friend class select_exists_subselect;
- friend class subselect_uniquesubquery_engine;
friend class subselect_indexsubquery_engine;
};
@@ -350,7 +349,7 @@ protected:
runtime memory root, for each execution, thus need not be freed.
*/
List<Cached_item> *left_expr_cache;
- bool first_execution;
+ bool left_expr_cache_filled; ///< Whether left_expr_cache holds a value
/** The need for expr cache may be optimized away, @sa init_left_expr_cache. */
bool need_expr_cache;
@@ -389,7 +388,7 @@ public:
Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
Item_in_subselect()
:Item_exists_subselect(), left_expr(NULL), left_expr_cache(NULL),
- first_execution(TRUE), need_expr_cache(TRUE), expr(NULL),
+ left_expr_cache_filled(false), need_expr_cache(TRUE), expr(NULL),
optimizer(NULL), was_null(FALSE), abort_on_null(FALSE),
pushed_cond_guards(NULL), upper_item(NULL)
{}
@@ -492,10 +491,6 @@ public:
either captured by previously set up select_result-based 'sink' or
stored somewhere by the exec() method itself.
- A required side effect: If at least one pushed-down predicate is
- disabled, subselect_engine->no_rows() must return correct result after
- the exec() call.
-
RETURN
0 - OK
1 - Either an execution error, or the engine was "changed", and the
@@ -515,8 +510,6 @@ public:
select_result_interceptor *result)= 0;
virtual bool no_tables() const = 0;
virtual bool is_executed() const { return FALSE; }
- /* Check if subquery produced any rows during last query execution */
- virtual bool no_rows() const = 0;
virtual enum_engine_type engine_type() const { return ABSTRACT_ENGINE; }
#ifndef DBUG_OFF
/**
@@ -557,7 +550,6 @@ public:
virtual bool no_tables() const;
virtual bool may_be_null() const;
virtual bool is_executed() const { return executed; }
- virtual bool no_rows() const;
virtual enum_engine_type engine_type() const { return SINGLE_SELECT_ENGINE; }
bool save_join_if_explain();
@@ -585,7 +577,6 @@ public:
select_result_interceptor *result);
virtual bool no_tables() const;
virtual bool is_executed() const;
- virtual bool no_rows() const;
virtual enum_engine_type engine_type() const { return UNION_ENGINE; }
private:
@@ -596,65 +587,32 @@ private:
struct st_join_table;
-/*
- A subquery execution engine that evaluates the subquery by doing one index
- lookup in a unique index.
+/**
+ A subquery execution engine that evaluates the subquery by doing index
+ lookups in a single table's index.
This engine is used to resolve subqueries in forms
-
- outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
-
- or, tuple-based:
-
- (oe1, .. oeN) IN (SELECT uniq_key_part1, ... uniq_key_partK
- FROM tbl WHERE subqwhere)
-
+
+ outer_expr IN (SELECT tbl.key FROM tbl WHERE subq_where)
+
+ or, row-based:
+
+ (oe1, .. oeN) IN (SELECT key_part1, ... key_partK
+ FROM tbl WHERE subqwhere)
+
i.e. the subquery is a single table SELECT without GROUP BY, aggregate
functions, etc.
*/
-
-class subselect_uniquesubquery_engine: public subselect_engine
+class subselect_indexsubquery_engine : public subselect_engine
{
protected:
st_join_table *tab;
Item *cond; /* The WHERE condition of subselect */
- /*
- TRUE<=> last execution produced empty set. Valid only when left
- expression is NULL.
- */
- bool empty_result_set;
-public:
-
- // constructor can assign THD because it will be called after JOIN::prepare
- subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg,
- Item_subselect *subs, Item *where)
- :subselect_engine(subs, 0), tab(tab_arg), cond(where) {}
- virtual void cleanup() {}
- virtual bool prepare();
- virtual void fix_length_and_dec(Item_cache** row);
- virtual bool exec();
- virtual uint cols() const { return 1; }
- virtual uint8 uncacheable() const { return UNCACHEABLE_DEPENDENT; }
- virtual void exclude();
- virtual table_map upper_select_const_tables() const { return 0; }
- virtual void print (String *str, enum_query_type query_type);
- virtual bool change_result(Item_subselect *si,
- select_result_interceptor *result);
- virtual bool no_tables() const;
- bool scan_table();
- void copy_ref_key(bool *require_scan, bool *convert_error);
- virtual bool no_rows() const { return empty_result_set; }
- virtual enum_engine_type engine_type() const { return UNIQUESUBQUERY_ENGINE; }
-};
-
-
-class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine
-{
private:
/* FALSE for 'ref', TRUE for 'ref-or-null'. */
bool check_null;
/*
- The "having" clause. This clause (further reffered to as "artificial
+ The "having" clause. This clause (further referred to as "artificial
having") was inserted by subquery transformation code. It contains
Item(s) that have a side-effect: they record whether the subquery has
produced a row with NULL certain components. We need to use it for cases
@@ -662,40 +620,39 @@ private:
(oe1, oe2) IN (SELECT t.key, t.no_key FROM t1)
where we do index lookup on t.key=oe1 but need also to check if there
was a row such that t.no_key IS NULL.
-
- NOTE: This is currently here and not in the uniquesubquery_engine. Ideally
- it should have been in uniquesubquery_engine in order to allow execution of
- subqueries like
-
- (oe1, oe2) IN (SELECT primary_key, non_key_maybe_null_field FROM tbl)
-
- We could use uniquesubquery_engine for the first component and let
- Item_is_not_null_test( non_key_maybe_null_field) to handle the second.
-
- However, subqueries like the above are currently not handled by index
- lookup-based subquery engines, the engine applicability check misses
- them: it doesn't switch the engine for case of artificial having and
- [eq_]ref access (only for artifical having + ref_or_null or no having).
- The above example subquery is handled as a full-blown SELECT with eq_ref
- access to one table.
-
- Due to this limitation, the "artificial having" currently needs to be
- checked by only in indexsubquery_engine.
*/
Item *having;
+ /**
+ Whether a lookup for key value (x0,y0) (x0 and/or y0 being NULL or not
+ NULL) will find at most one row.
+ */
+ bool unique;
public:
// constructor can assign THD because it will be called after JOIN::prepare
subselect_indexsubquery_engine(THD *thd_arg, st_join_table *tab_arg,
Item_subselect *subs, Item *where,
- Item *having_arg, bool chk_null)
- :subselect_uniquesubquery_engine(thd_arg, tab_arg, subs, where),
- check_null(chk_null),
- having(having_arg)
- {}
+ Item *having_arg, bool chk_null,
+ bool unique_arg)
+ :subselect_engine(subs, 0), tab(tab_arg), cond(where),
+ check_null(chk_null), having(having_arg), unique(unique_arg)
+ {};
virtual bool exec();
virtual void print (String *str, enum_query_type query_type);
- virtual enum_engine_type engine_type() const { return INDEXSUBQUERY_ENGINE; }
+ virtual enum_engine_type engine_type() const
+ { return unique ? UNIQUESUBQUERY_ENGINE : INDEXSUBQUERY_ENGINE; }
+ virtual void cleanup() {}
+ virtual bool prepare();
+ virtual void fix_length_and_dec(Item_cache** row);
+ virtual uint cols() const { return 1; }
+ virtual uint8 uncacheable() const { return UNCACHEABLE_DEPENDENT; }
+ virtual void exclude();
+ virtual table_map upper_select_const_tables() const { return 0; }
+ virtual bool change_result(Item_subselect *si,
+ select_result_interceptor *result);
+ virtual bool no_tables() const;
+ bool scan_table();
+ void copy_ref_key(bool *require_scan, bool *convert_error);
};
/*
@@ -723,14 +680,29 @@ inline bool Item_subselect::is_uncacheab
/**
Compute an IN predicate via a hash semi-join. The subquery is materialized
during the first evaluation of the IN predicate. The IN predicate is executed
- via the functionality inherited from subselect_uniquesubquery_engine.
+ via the functionality inherited from subselect_indexsubquery_engine.
*/
-class subselect_hash_sj_engine: public subselect_uniquesubquery_engine
+class subselect_hash_sj_engine: public subselect_indexsubquery_engine
{
private:
/* TRUE if the subquery was materialized into a temp table. */
bool is_materialized;
+ /**
+ Existence of inner NULLs in materialized table:
+ By design, other values than IRRELEVANT_OR_FALSE are possible only if the
+ subquery has only one inner expression.
+ */
+ enum nulls_exist
+ {
+ /// none, or they don't matter
+ NEX_IRRELEVANT_OR_FALSE= 0,
+ /// they matter, and we don't know yet if they exists
+ NEX_UNKNOWN= 1,
+ /// they matter, and we know there exists at least one.
+ NEX_TRUE= 2
+ };
+ enum nulls_exist mat_table_has_nulls;
/*
The old engine already chosen at parse time and stored in permanent memory.
Through this member we can re-create and re-prepare the join object
@@ -744,10 +716,10 @@ private:
public:
subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate,
- subselect_single_select_engine *old_engine)
- :subselect_uniquesubquery_engine(thd, NULL, in_predicate, NULL),
- is_materialized(FALSE), materialize_engine(old_engine),
- tmp_param(NULL)
+ subselect_single_select_engine *old_engine)
+ :subselect_indexsubquery_engine(thd, NULL, in_predicate, NULL,
+ NULL, false, true),
+ is_materialized(false), materialize_engine(old_engine), tmp_param(NULL)
{}
~subselect_hash_sj_engine();
=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc 2012-02-09 09:09:58 +0000
+++ b/sql/opt_range.cc 2012-02-09 11:22:17 +0000
@@ -483,8 +483,7 @@ public:
if (cmp_min_to_min(arg) > 0)
{
min_value=arg->min_value; min_flag=arg->min_flag;
- if ((max_flag & (NO_MAX_RANGE | NO_MIN_RANGE)) ==
- (NO_MAX_RANGE | NO_MIN_RANGE))
+ if ((max_flag & NO_MAX_RANGE) && (min_flag & NO_MIN_RANGE))
return 1; // Full range
}
maybe_flag|=arg->maybe_flag;
@@ -495,8 +494,7 @@ public:
if (cmp_max_to_max(arg) <= 0)
{
max_value=arg->max_value; max_flag=arg->max_flag;
- if ((max_flag & (NO_MAX_RANGE | NO_MIN_RANGE)) ==
- (NO_MAX_RANGE | NO_MIN_RANGE))
+ if ((max_flag & NO_MAX_RANGE) && (min_flag & NO_MIN_RANGE))
return 1; // Full range
}
maybe_flag|=arg->maybe_flag;
@@ -7475,7 +7473,16 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *
cur_key2->next= next_key2; // New copy of cur_key2
}
- cur_key2->copy_min(cur_key1);
+ if (cur_key2->copy_min(cur_key1))
+ {
+ // cur_key2 is full range: [-inf <= cur_key2 <= +inf]
+ key1->free_tree();
+ key2->free_tree();
+ if (key1->maybe_flag)
+ return new SEL_ARG(SEL_ARG::MAYBE_KEY);
+ return 0;
+ }
+
if (!(key1= key1->tree_delete(cur_key1)))
{
/*
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2012-01-31 15:16:16 +0000
+++ b/sql/sql_class.cc 2012-02-08 15:25:17 +0000
@@ -2978,6 +2978,12 @@ bool select_exists_subselect::send_data(
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
+ /*
+ A subquery may be evaluated 1) by executing the JOIN 2) by optimized
+ functions (index_subquery, subquery materialization).
+ It's only in (1) that we get here when we find a row. In (2) "value" is
+ set elsewhere.
+ */
it->value= 1;
it->assigned(1);
DBUG_RETURN(0);
=== modified file 'sql/sql_optimizer.cc'
--- a/sql/sql_optimizer.cc 2012-02-07 20:32:47 +0000
+++ b/sql/sql_optimizer.cc 2012-02-08 15:25:17 +0000
@@ -768,8 +768,10 @@ JOIN::optimize()
join_tab[0].type= JT_UNIQUE_SUBQUERY;
error= 0;
changed= TRUE;
- engine= new subselect_uniquesubquery_engine(thd, join_tab, unit->item,
- where);
+ engine= new subselect_indexsubquery_engine(thd, join_tab, unit->item,
+ where, NULL /* having */,
+ false /* check_null */,
+ true /* unique */);
}
else if (join_tab[0].type == JT_REF &&
join_tab[0].ref.items[0]->name == in_left_expr_name)
@@ -780,7 +782,7 @@ JOIN::optimize()
error= 0;
changed= TRUE;
engine= new subselect_indexsubquery_engine(thd, join_tab, unit->item,
- where, NULL, 0);
+ where, NULL, false, false);
}
} else if (join_tab[0].type == JT_REF_OR_NULL &&
join_tab[0].ref.items[0]->name == in_left_expr_name &&
@@ -792,7 +794,13 @@ JOIN::optimize()
conds= remove_additional_cond(conds);
save_index_subquery_explain_info(join_tab, conds);
engine= new subselect_indexsubquery_engine(thd, join_tab, unit->item,
- conds, having, 1);
+ conds, having, true, false);
+ /**
+ @todo Above we passed unique=false. But for this query:
+ (oe1, oe2) IN (SELECT primary_key, non_key_maybe_null_field FROM tbl)
+ we could use "unique=true" for the first index component and let
+ Item_is_not_null_test(non_key_maybe_null_field) handle the second.
+ */
}
if (changed)
DBUG_RETURN(unit->item->change_engine(engine));
@@ -8591,8 +8599,7 @@ static Item *remove_additional_cond(Item
where Subquery's WHERE clause
DESCRIPTION
- For index lookup-based subquery (i.e. one executed with
- subselect_uniquesubquery_engine or subselect_indexsubquery_engine),
+ For index lookup-based subquery (subselect_indexsubquery_engine),
check its EXPLAIN output row should contain
"Using index" (TAB_INFO_FULL_SCAN_ON_NULL)
"Using Where" (TAB_INFO_USING_WHERE)
=== modified file 'sql/sql_resolver.cc'
--- a/sql/sql_resolver.cc 2012-01-10 18:58:10 +0000
+++ b/sql/sql_resolver.cc 2012-02-08 15:25:17 +0000
@@ -377,42 +377,136 @@ err:
/**
- @brief Check if subquery predicate's compared types allow materialization.
+ Check if the subquery predicate can be executed via materialization.
- @param predicate subquery predicate
+ @param predicate IN subquery predicate
+ @param thd THD
+ @param select_lex SELECT_LEX of the subquery
+ @param outer Parent SELECT_LEX (outer to subquery)
- @return TRUE if subquery types allow materialization, FALSE otherwise.
-
- @details
- This is a temporary fix for BUG#36752.
- See bug report for description of restrictions we need to put on the
- compared expressions.
+ @return TRUE if subquery allows materialization, FALSE otherwise.
*/
-static
-bool subquery_types_allow_materialization(Item_in_subselect *predicate)
+static
+bool subquery_allows_materialization(Item_in_subselect *predicate,
+ THD *thd,
+ SELECT_LEX *select_lex,
+ const SELECT_LEX *outer)
{
- DBUG_ENTER("subquery_types_allow_materialization");
+ bool has_nullables= false;
+ const uint elements= predicate->unit->first_select()->item_list.elements;
+ DBUG_ENTER("subquery_allows_materialization");
+ DBUG_ASSERT(elements >= 1);
+ DBUG_ASSERT(predicate->left_expr->cols() == elements);
+
+ OPT_TRACE_TRANSFORM(&thd->opt_trace, trace_wrapper, trace_mat,
+ select_lex->select_number,
+ "IN (SELECT)", "materialization");
- DBUG_ASSERT(predicate->left_expr->fixed);
- DBUG_ASSERT(predicate->left_expr->cols() ==
- predicate->unit->first_select()->item_list.elements);
-
- List_iterator<Item> it(predicate->unit->first_select()->item_list);
- uint elements= predicate->unit->first_select()->item_list.elements;
-
- for (uint i= 0; i < elements; i++)
- {
- Item *inner= it++;
- if (!types_allow_materialization(predicate->left_expr->element_index(i),
- inner))
- DBUG_RETURN(FALSE);
- if (inner->is_blob_field())
- DBUG_RETURN(FALSE);
+ const char *cause= NULL;
+ if (select_lex->is_part_of_union())
+ {
+ // Subquery must be a single query specification clause (not a UNION)
+ cause= "in UNION";
+ }
+ else if (!select_lex->master_unit()->first_select()->leaf_tables)
+ {
+ // Subquery has no tables, hence no point in materializing.
+ cause= "no inner tables";
+ }
+ else if (!outer->join)
+ {
+ /*
+ Maybe this is a subquery of a single table UPDATE/DELETE (TODO:
+ handle this by switching to multi-table UPDATE/DELETE).
+ */
+ cause= "parent query has no JOIN";
}
+ else if (!outer->leaf_tables)
+ {
+ /*
+ The upper query is SELECT ... FROM DUAL. We can't do materialization for
+ SELECT .. FROM DUAL because it does not call
+ setup_subquery_materialization(). We could fix it but it's not worth it.
+ */
+ cause= "no tables in outer query";
+ }
+ else if (predicate->is_correlated)
+ {
+ /*
+ Subquery should not be correlated.
+ TODO:
+ This is an overly restrictive condition. It can be extended to:
+ (Subquery is non-correlated ||
+ Subquery is correlated to any query outer to IN predicate ||
+ (Subquery is correlated to the immediate outer query &&
+ Subquery !contains {GROUP BY, ORDER BY [LIMIT],
+ aggregate functions}) && subquery predicate is not under "NOT IN"))
+ */
+ cause= "correlated";
+ }
+ else if (predicate->exec_method !=
+ Item_exists_subselect::EXEC_UNSPECIFIED)
+ {
+ // An execution method was already chosen (by a prepared statement).
+ cause= "already have strategy";
+ }
+ else
+ {
+ /*
+ Check that involved expression types allow materialization.
+ This is a temporary fix for BUG#36752; see bug report for
+ description of restrictions we need to put on the compared expressions.
+ */
+ DBUG_ASSERT(predicate->left_expr->fixed);
+ List_iterator<Item> it(predicate->unit->first_select()->item_list);
- DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed"));
- DBUG_RETURN(TRUE);
+ for (uint i= 0; i < elements; i++)
+ {
+ Item * const inner= it++;
+ Item * const outer= predicate->left_expr->element_index(i);
+ if (!types_allow_materialization(outer, inner))
+ {
+ cause= "type mismatch";
+ break;
+ }
+ if (inner->is_blob_field()) // 6
+ {
+ cause= "inner blob";
+ break;
+ }
+ has_nullables|= outer->maybe_null | inner->maybe_null;
+ }
+
+ if (!cause)
+ {
+ trace_mat.add("has_nullable_expressions", has_nullables);
+ /*
+ Subquery materialization cannot handle NULLs partial matching
+ properly, yet. If the outer or inner values are NULL, the
+ subselect_hash_sj_engine may reply FALSE when it should reply UNKNOWN.
+ So, we must limit it to those three cases:
+ - when FALSE and UNKNOWN are equivalent answers. I.e. this is a a
+ top-level predicate (this implies it is not negated).
+ - when outer and inner values cannot be NULL.
+ - when there is a single inner column (because for this we have a
+ limited implementation of NULLs partial matching).
+ */
+ const bool is_top_level= predicate->is_top_level_item();
+ trace_mat.add("treat_UNKNOWN_as_FALSE", is_top_level);
+
+ if (!is_top_level && has_nullables && (elements > 1))
+ cause= "cannot_handle_partial_matches";
+ else
+ {
+ trace_mat.add("chosen", true);
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ DBUG_ASSERT(cause != NULL);
+ trace_mat.add("chosen", false).add_alnum("cause", cause);
+ DBUG_RETURN(false);
}
@@ -437,13 +531,11 @@ bool subquery_types_allow_materializatio
*/
-static
-bool resolve_subquery(THD *thd, JOIN *join)
+static bool resolve_subquery(THD *thd, JOIN *join)
{
DBUG_ENTER("resolve_subquery");
- enum {SQ_NONE, SQ_SEMIJOIN, SQ_MATERIALIZATION} sq_choice= SQ_NONE;
- bool types_problem= false; // if types prevented subq materialization
+ bool chose_semijoin= false;
SELECT_LEX *const select_lex= join->select_lex;
SELECT_LEX *const outer= select_lex->outer_select();
@@ -548,93 +640,37 @@ bool resolve_subquery(THD *thd, JOIN *jo
/* Register the subquery for further processing in flatten_subqueries() */
outer->join->sj_subselects.push_back(in_exists_predicate);
- sq_choice= SQ_SEMIJOIN;
+ chose_semijoin= true;
}
- else
+
+ if (subq_predicate_substype == Item_subselect::IN_SUBS)
+ {
+ Opt_trace_context * const trace= &join->thd->opt_trace;
+ OPT_TRACE_TRANSFORM(trace, oto0, oto1,
+ select_lex->select_number, "IN (SELECT)", "semijoin");
+ oto1.add("chosen", chose_semijoin);
+ }
+
+ if (!chose_semijoin &&
+ thd->optimizer_switch_flag(OPTIMIZER_SWITCH_MATERIALIZATION) &&
+ (subq_predicate_substype == Item_subselect::IN_SUBS))
{
- DBUG_PRINT("info", ("Subquery can't be converted to semi-join"));
/*
Check if the subquery predicate can be executed via materialization.
- The required conditions are:
- 1. Subquery predicate is an IN/=ANY subquery predicate
- 2. Subquery is a single SELECT (not a UNION)
- 3. Subquery is not a table-less query. In this case there is no
- point in materializing.
- 3A The upper query is not a confluent SELECT ... FROM DUAL. We
- can't do materialization for SELECT .. FROM DUAL because it
- does not call setup_subquery_materialization(). We could make
- SELECT ... FROM DUAL call that function but that doesn't seem
- to be the case that is worth handling.
- 4. Subquery predicate is a top-level predicate
- (this implies it is not negated)
- TODO: this is a limitation that should be lifted once we
- implement correct NULL semantics (WL#3830)
- 5. Subquery is non-correlated
- TODO:
- This is an overly restrictive condition. It can be extended to:
- (Subquery is non-correlated ||
- Subquery is correlated to any query outer to IN predicate ||
- (Subquery is correlated to the immediate outer query &&
- Subquery !contains {GROUP BY, ORDER BY [LIMIT],
- aggregate functions}) && subquery predicate is not under "NOT IN"))
- 6. No execution method was already chosen (by a prepared statement).
- 7. Involved expression types allow materialization (temporary only)
-
- (*) The subquery must be part of a SELECT or CREATE SELECT statement. We
- should relax this and allow it in multi/single-table UPDATE/DELETE,
- INSERT SELECT (after studying potential problems when the
- inserts/updates/deletes are done to a table which is itself part of
- the subquery).
We have to determine whether we will perform subquery materialization
before calling the IN=>EXISTS transformation, so that we know whether to
perform the whole transformation or only that part of it which wraps
Item_in_subselect in an Item_in_optimizer.
*/
- Item_in_subselect *in_predicate= (Item_in_subselect *)subq_predicate;
-
- if (thd->optimizer_switch_flag(OPTIMIZER_SWITCH_MATERIALIZATION) &&
- subq_predicate_substype == Item_subselect::IN_SUBS && // 1
- !select_lex->is_part_of_union() && // 2
- select_lex->master_unit()->first_select()->leaf_tables && // 3
- (thd->lex->sql_command == SQLCOM_SELECT ||
- thd->lex->sql_command == SQLCOM_CREATE_TABLE) && // *
- outer->leaf_tables && // 3A
- in_predicate->is_top_level_item() && // 4
- !in_predicate->is_correlated && // 5
- in_predicate->exec_method ==
- Item_exists_subselect::EXEC_UNSPECIFIED) // 6
- {
- if (subquery_types_allow_materialization(in_predicate)) // 7
- {
- in_predicate->exec_method=
- Item_exists_subselect::EXEC_MATERIALIZATION;
- sq_choice= SQ_MATERIALIZATION;
- }
- else
- types_problem= true;
- }
- }
-
- Opt_trace_context * const trace= &join->thd->opt_trace;
- if (subq_predicate_substype == Item_subselect::IN_SUBS)
- {
- {
- OPT_TRACE_TRANSFORM(trace, oto, oto1, select_lex->select_number,
- "IN (SELECT)", "semijoin");
- oto1.add("chosen", sq_choice == SQ_SEMIJOIN);
- }
- if (sq_choice != SQ_SEMIJOIN)
- {
- OPT_TRACE_TRANSFORM(trace, oto0, oto1, select_lex->select_number,
- "IN (SELECT)", "materialization");
- oto1.add("chosen", sq_choice == SQ_MATERIALIZATION);
- if (types_problem)
- oto1.add_alnum("cause", "field_types");
- }
+ Item_in_subselect *in_predicate= static_cast<Item_in_subselect *>
+ (subq_predicate);
+ if (subquery_allows_materialization(in_predicate, thd, select_lex, outer))
+ in_predicate->exec_method=
+ Item_exists_subselect::EXEC_MATERIALIZATION;
}
- if (sq_choice != SQ_SEMIJOIN &&
+ if (!chose_semijoin &&
subq_predicate->select_transformer(join) == Item_subselect::RES_ERROR)
DBUG_RETURN(TRUE);
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2012-02-01 09:59:13 +0000
+++ b/sql/sql_select.cc 2012-02-08 15:25:17 +0000
@@ -1510,7 +1510,10 @@ bool create_ref_for_key(JOIN *join, JOIN
instead of JT_REF_OR_NULL in case if field can't be null
*/
if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
- null_ref_key= key_buff;
+ {
+ DBUG_ASSERT(null_ref_key == NULL); // or we would overwrite it below
+ null_ref_key= key_buff;
+ }
key_buff+=keyinfo->key_part[part_no].store_length;
}
} /* not ftkey */
=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc 2012-02-02 16:56:36 +0000
+++ b/sql/sys_vars.cc 2012-02-09 12:57:42 +0000
@@ -2033,14 +2033,15 @@ static bool fix_read_only(sys_var *self,
}
/*
- Perform a 'FLUSH TABLES WITH READ LOCK'.
- This is a 3 step process:
- - [1] lock_global_read_lock()
- - [2] close_cached_tables()
- - [3] make_global_read_lock_block_commit()
- [1] prevents new connections from obtaining tables locked for write.
- [2] waits until all existing connections close their tables.
- [3] prevents transactions from being committed.
+ READ_ONLY=1 prevents write locks from being taken on tables and
+ blocks transactions from committing. We therefore should make sure
+ that no such events occur while setting the read_only variable.
+ This is a 2 step process:
+ [1] lock_global_read_lock()
+ Prevents connections from obtaining new write locks on
+ tables. Note that we can still have active rw transactions.
+ [2] make_global_read_lock_block_commit()
+ Prevents transactions from committing.
*/
read_only= opt_readonly;
@@ -2048,19 +2049,6 @@ static bool fix_read_only(sys_var *self,
if (thd->global_read_lock.lock_global_read_lock(thd))
goto end_with_mutex_unlock;
-
- /*
- This call will be blocked by any connection holding a READ or WRITE lock.
- Ideally, we want to wait only for pending WRITE locks, but since:
- con 1> LOCK TABLE T FOR READ;
- con 2> LOCK TABLE T FOR WRITE; (blocked by con 1)
- con 3> SET GLOBAL READ ONLY=1; (blocked by con 2)
- can cause to wait on a read lock, it's required for the client application
- to unlock everything, and acceptable for the server to wait on all locks.
- */
- if ((result= close_cached_tables(thd, NULL, TRUE,
- thd->variables.lock_wait_timeout)))
- goto end_with_read_lock;
if ((result= thd->global_read_lock.make_global_read_lock_block_commit(thd)))
goto end_with_read_lock;
=== modified file 'storage/heap/hp_hash.c'
--- a/storage/heap/hp_hash.c 2011-07-21 12:54:54 +0000
+++ b/storage/heap/hp_hash.c 2012-02-09 12:17:37 +0000
@@ -652,6 +652,10 @@ int hp_key_cmp(HP_KEYDEF *keydef, const
char_length2= my_charpos(cs, pos, pos + char_length_rec, char_length2);
set_if_smaller(char_length_rec, char_length2);
}
+ else
+ {
+ set_if_smaller(char_length_rec, seg->length);
+ }
if (cs->coll->strnncollsp(seg->charset,
(uchar*) pos, char_length_rec,
=== modified file 'unittest/gunit/opt_range-t.cc'
--- a/unittest/gunit/opt_range-t.cc 2011-12-20 09:51:05 +0000
+++ b/unittest/gunit/opt_range-t.cc 2012-02-09 11:22:17 +0000
@@ -48,6 +48,7 @@ protected:
initializer.SetUp();
m_opt_param.thd= thd();
m_opt_param.mem_root= &m_alloc;
+ m_opt_param.current_table= 1<<0;
init_sql_alloc(&m_alloc, thd()->variables.range_alloc_block_size, 0);
}
@@ -102,7 +103,7 @@ const SEL_TREE *null_tree= NULL;
class Mock_field_long : public Field_long
{
public:
- Mock_field_long()
+ Mock_field_long(THD *thd, Item *item)
: Field_long(0, // ptr_arg
8, // len_arg
NULL, // null_ptr_arg
@@ -118,30 +119,313 @@ public:
m_share.db.str= const_cast<char*>(foo);
m_share.db.length= strlen(m_share.db.str);
+ bitmap_init(&share_allset, 0, sizeof(my_bitmap_map), 0);
+ bitmap_set_above(&share_allset, 0, 1); //all bits 1
+ m_share.all_set= share_allset;
+
memset(&m_table, 0, sizeof(m_table));
m_table.s= &m_share;
+
+ bitmap_init(&tbl_readset, 0, sizeof(my_bitmap_map), 0);
+ m_table.read_set= &tbl_readset;
+
+ bitmap_init(&tbl_writeset, 0, sizeof(my_bitmap_map), 0);
+ m_table.write_set= &tbl_writeset;
+
+ m_table.map= 1<<0;
+ m_table.in_use= thd;
this->table_name= &m_table_name;
this->table= &m_table;
+ this->ptr= (uchar*) alloc_root((thd->mem_root), KEY_LENGTH);
+ if (item)
+ item->save_in_field_no_warnings(this, true);
}
+
+ // #bytes to store the value - see Field_long::key_lenght()
+ static const int KEY_LENGTH= 4;
const char *m_table_name;
TABLE_SHARE m_share;
TABLE m_table;
+ MY_BITMAP share_allset;
+ MY_BITMAP tbl_readset;
+ MY_BITMAP tbl_writeset;
};
+class Debug_sel_arg : public SEL_ARG
+{
+public:
+ Debug_sel_arg(Field *f, const uchar *min_val, const uchar *max_val,
+ const KEY_PART_INFO *kpi_)
+ : SEL_ARG(f, min_val, max_val), kpi(kpi_)
+ {}
+
+ void print(String *s)
+ {
+ append_range(s, kpi, min_value, max_value, min_flag | max_flag);
+ }
+private:
+ const KEY_PART_INFO * const kpi;
+};
+
TEST_F(SelArgTest, SimpleCond)
{
EXPECT_NE(null_tree, get_mm_tree(&m_opt_param, new Item_int(42)));
}
+/*
+ TODO: Here we try to build a range, but a lot of mocking remains
+ before it works as intended. Currently get_mm_tree() returns NULL
+ because m_opt_param.key_parts and m_opt_param.key_parts_end have not
+ been setup.
+*/
TEST_F(SelArgTest, EqualCond)
{
- Mock_field_long field_long;
- EXPECT_EQ(null_tree,
- get_mm_tree(&m_opt_param,
- new Item_equal(new Item_int(42),
- new Item_field(&field_long))));
+ Mock_field_long field_long(thd(), NULL);
+ m_opt_param.table= &field_long.m_table;
+ SEL_TREE *tree= get_mm_tree(&m_opt_param,
+ new Item_equal(new Item_int(42),
+ new Item_field(&field_long)));
+ EXPECT_EQ(null_tree, tree);
+}
+
+
+TEST_F(SelArgTest, SelArgOnevalue)
+{
+ Mock_field_long field_long7(thd(), new Item_int(7));
+
+ KEY_PART_INFO kpi;
+ kpi.init_from_field(&field_long7);
+
+ uchar range_val7[field_long7.KEY_LENGTH];
+ field_long7.get_key_image(range_val7, kpi.length, Field::itRAW);
+
+ Debug_sel_arg sel_arg7(&field_long7, range_val7, range_val7, &kpi);
+ String range_string;
+ sel_arg7.print(&range_string);
+ const char expected[]= "7 <= field_name <= 7";
+ EXPECT_STREQ(expected, range_string.c_ptr());
+
+ sel_arg7.min_flag|= NO_MIN_RANGE;
+ range_string.length(0);
+ sel_arg7.print(&range_string);
+ const char expected2[]= "field_name <= 7";
+ EXPECT_STREQ(expected2, range_string.c_ptr());
+
+ sel_arg7.max_flag= NEAR_MAX;
+ range_string.length(0);
+ sel_arg7.print(&range_string);
+ const char expected3[]= "field_name < 7";
+ EXPECT_STREQ(expected3, range_string.c_ptr());
+
+ sel_arg7.min_flag= NEAR_MIN;
+ sel_arg7.max_flag= NO_MAX_RANGE;
+ range_string.length(0);
+ sel_arg7.print(&range_string);
+ const char expected4[]= "7 < field_name";
+ EXPECT_STREQ(expected4, range_string.c_ptr());
+
+ sel_arg7.min_flag= 0;
+ range_string.length(0);
+ sel_arg7.print(&range_string);
+ const char expected5[]= "7 <= field_name";
+ EXPECT_STREQ(expected5, range_string.c_ptr());
+}
+
+
+TEST_F(SelArgTest, SelArgBetween)
+{
+ Mock_field_long field_long3(thd(), new Item_int(3));
+ Mock_field_long field_long5(thd(), new Item_int(5));
+
+ KEY_PART_INFO kpi;
+ kpi.init_from_field(&field_long3);
+
+ uchar range_val3[field_long3.KEY_LENGTH];
+ field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
+
+ uchar range_val5[field_long5.KEY_LENGTH];
+ field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
+
+ Debug_sel_arg sel_arg35(&field_long3, range_val3, range_val5, &kpi);
+
+ String range_string;
+ sel_arg35.print(&range_string);
+ const char expected[]= "3 <= field_name <= 5";
+ EXPECT_STREQ(expected, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg35.min_flag= NEAR_MIN;
+ sel_arg35.print(&range_string);
+ const char expected2[]= "3 < field_name <= 5";
+ EXPECT_STREQ(expected2, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg35.max_flag= NEAR_MAX;
+ sel_arg35.print(&range_string);
+ const char expected3[]= "3 < field_name < 5";
+ EXPECT_STREQ(expected3, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg35.min_flag= 0;
+ sel_arg35.print(&range_string);
+ const char expected4[]= "3 <= field_name < 5";
+ EXPECT_STREQ(expected4, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg35.min_flag= NO_MIN_RANGE;
+ sel_arg35.max_flag= 0;
+ sel_arg35.print(&range_string);
+ const char expected5[]= "field_name <= 5";
+ EXPECT_STREQ(expected5, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg35.min_flag= 0;
+ sel_arg35.max_flag= NO_MAX_RANGE;
+ sel_arg35.print(&range_string);
+ const char expected6[]= "3 <= field_name";
+ EXPECT_STREQ(expected6, range_string.c_ptr());
+}
+
+TEST_F(SelArgTest, CopyMax)
+{
+ Mock_field_long field_long3(thd(), new Item_int(3));
+ Mock_field_long field_long5(thd(), new Item_int(5));
+
+ KEY_PART_INFO kpi;
+ kpi.init_from_field(&field_long3);
+
+ uchar range_val3[field_long3.KEY_LENGTH];
+ field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
+
+ uchar range_val5[field_long5.KEY_LENGTH];
+ field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
+
+ Debug_sel_arg sel_arg3(&field_long3, range_val3, range_val3, &kpi);
+ sel_arg3.min_flag= NO_MIN_RANGE;
+ Debug_sel_arg sel_arg5(&field_long5, range_val5, range_val5, &kpi);
+ sel_arg5.min_flag= NO_MIN_RANGE;
+
+ String range_string;
+ sel_arg3.print(&range_string);
+ const char expected[]= "field_name <= 3";
+ EXPECT_STREQ(expected, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg5.print(&range_string);
+ const char expected2[]= "field_name <= 5";
+ EXPECT_STREQ(expected2, range_string.c_ptr());
+
+ /*
+ Ranges now:
+ -inf ----------------3-5----------- +inf
+ sel_arg3: [-------------------->
+ sel_arg5: [---------------------->
+ Below: merge these two ranges into sel_arg3 using copy_max()
+ */
+ bool full_range= sel_arg3.copy_max(&sel_arg5);
+ // The merged range does not cover all possible values
+ EXPECT_FALSE(full_range);
+
+ range_string.length(0);
+ sel_arg3.print(&range_string);
+ const char expected3[]= "field_name <= 5";
+ EXPECT_STREQ(expected3, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg5.min_flag= 0;
+ sel_arg5.max_flag= NO_MAX_RANGE;
+ sel_arg5.print(&range_string);
+ const char expected4[]= "5 <= field_name";
+ EXPECT_STREQ(expected4, range_string.c_ptr());
+
+ /*
+ Ranges now:
+ -inf ----------------3-5----------- +inf
+ sel_arg3: [---------------------->
+ sel_arg5: <---------------]
+ Below: merge these two ranges into sel_arg3 using copy_max()
+ */
+
+ full_range= sel_arg3.copy_max(&sel_arg5);
+ // The new range covers all possible values
+ EXPECT_TRUE(full_range);
+
+ range_string.length(0);
+ sel_arg3.print(&range_string);
+ const char expected5[]= "field_name";
+ EXPECT_STREQ(expected5, range_string.c_ptr());
+}
+
+TEST_F(SelArgTest, CopyMin)
+{
+ Mock_field_long field_long3(thd(), new Item_int(3));
+ Mock_field_long field_long5(thd(), new Item_int(5));
+
+ KEY_PART_INFO kpi;
+ kpi.init_from_field(&field_long3);
+
+ uchar range_val3[field_long3.KEY_LENGTH];
+ field_long3.get_key_image(range_val3, kpi.length, Field::itRAW);
+
+ uchar range_val5[field_long5.KEY_LENGTH];
+ field_long5.get_key_image(range_val5, kpi.length, Field::itRAW);
+
+ Debug_sel_arg sel_arg3(&field_long3, range_val3, range_val3, &kpi);
+ sel_arg3.max_flag= NO_MAX_RANGE;
+ Debug_sel_arg sel_arg5(&field_long5, range_val5, range_val5, &kpi);
+ sel_arg5.max_flag= NO_MAX_RANGE;
+
+ String range_string;
+ sel_arg3.print(&range_string);
+ const char expected[]= "3 <= field_name";
+ EXPECT_STREQ(expected, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg5.print(&range_string);
+ const char expected2[]= "5 <= field_name";
+ EXPECT_STREQ(expected2, range_string.c_ptr());
+
+ /*
+ Ranges now:
+ -inf ----------------3-5----------- +inf
+ sel_arg3: <-----------------]
+ sel_arg5: <---------------]
+ Below: merge these two ranges into sel_arg3 using copy_max()
+ */
+ bool full_range= sel_arg5.copy_min(&sel_arg3);
+ // The merged range does not cover all possible values
+ EXPECT_FALSE(full_range);
+
+ range_string.length(0);
+ sel_arg5.print(&range_string);
+ const char expected3[]= "3 <= field_name";
+ EXPECT_STREQ(expected3, range_string.c_ptr());
+
+ range_string.length(0);
+ sel_arg3.max_flag= 0;
+ sel_arg3.min_flag= NO_MIN_RANGE;
+ sel_arg3.print(&range_string);
+ const char expected4[]= "field_name <= 3";
+ EXPECT_STREQ(expected4, range_string.c_ptr());
+
+ /*
+ Ranges now:
+ -inf ----------------3-5----------- +inf
+ sel_arg3: [-------------------->
+ sel_arg5: <-----------------]
+ Below: merge these two ranges into sel_arg5 using copy_min()
+ */
+
+ full_range= sel_arg5.copy_min(&sel_arg3);
+ // The new range covers all possible values
+ EXPECT_TRUE(full_range);
+
+ range_string.length(0);
+ sel_arg5.print(&range_string);
+ const char expected5[]= "field_name";
+ EXPECT_STREQ(expected5, range_string.c_ptr());
}
}
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (roy.lyseng:3864 to 3870) | Roy Lyseng | 10 Feb |