List:Commits« Previous MessageNext Message »
From:Tor Didriksen Date:January 30 2012 10:36am
Subject:bzr push into mysql-trunk branch (tor.didriksen:3803 to 3804)
View as plain text  
 3804 Tor Didriksen	2012-01-30 [merge]
      merge opt-team => trunk

    added:
      mysql-test/suite/opt_trace/r/eq_range_statistics.result
      mysql-test/suite/opt_trace/t/eq_range_statistics.test
      mysql-test/suite/sys_vars/r/eq_range_index_dive_limit_basic.result
      mysql-test/suite/sys_vars/t/eq_range_index_dive_limit_basic.test
    modified:
      include/my_base.h
      mysql-test/include/join_cache.inc
      mysql-test/include/subquery_mat.inc
      mysql-test/include/subquery_sj.inc
      mysql-test/r/derived.result
      mysql-test/r/greedy_optimizer.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/join_nested.result
      mysql-test/r/join_nested_bka.result
      mysql-test/r/join_nested_bka_nixbnl.result
      mysql-test/r/mysqld--help-notwin.result
      mysql-test/r/mysqld--help-win.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_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_dupsweed.result
      mysql-test/r/subquery_sj_dupsweed_bka.result
      mysql-test/r/subquery_sj_dupsweed_bka_nixbnl.result
      mysql-test/r/subquery_sj_dupsweed_bkaunique.result
      mysql-test/r/subquery_sj_firstmatch.result
      mysql-test/r/subquery_sj_firstmatch_bka.result
      mysql-test/r/subquery_sj_firstmatch_bka_nixbnl.result
      mysql-test/r/subquery_sj_firstmatch_bkaunique.result
      mysql-test/r/subquery_sj_loosescan.result
      mysql-test/r/subquery_sj_loosescan_bka.result
      mysql-test/r/subquery_sj_loosescan_bka_nixbnl.result
      mysql-test/r/subquery_sj_loosescan_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/r/subquery_sj_none.result
      mysql-test/r/subquery_sj_none_bka.result
      mysql-test/r/subquery_sj_none_bka_nixbnl.result
      mysql-test/r/subquery_sj_none_bkaunique.result
      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/charset.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/range_no_prot.result
      mysql-test/suite/opt_trace/r/range_ps_prot.result
      mysql-test/suite/opt_trace/r/subquery_no_prot.result
      mysql-test/suite/opt_trace/r/subquery_ps_prot.result
      sql/filesort.cc
      sql/filesort_utils.h
      sql/handler.cc
      sql/opt_range.cc
      sql/sql_class.h
      sql/sql_join_buffer.cc
      sql/sql_join_buffer.h
      sql/sql_optimizer.cc
      sql/sql_optimizer.h
      sql/sql_select.cc
      sql/structs.h
      sql/sys_vars.cc
      sql/table.h
      unittest/gunit/filesort_buffer-t.cc
 3803 Tor Didriksen	2012-01-30 [merge]
      merge 5.5 => trunk

    modified:
      libmysql/CMakeLists.txt
=== modified file 'include/my_base.h'
--- a/include/my_base.h	2011-10-27 04:20:52 +0000
+++ b/include/my_base.h	2012-01-26 13:09:59 +0000
@@ -78,11 +78,11 @@ enum ha_rkey_function {
   HA_READ_PREFIX,                 /* Key which as same prefix */
   HA_READ_PREFIX_LAST,            /* Last key with the same prefix */
   HA_READ_PREFIX_LAST_OR_PREV,    /* Last or prev key with the same prefix */
-  HA_READ_MBR_CONTAIN,
-  HA_READ_MBR_INTERSECT,
-  HA_READ_MBR_WITHIN,
-  HA_READ_MBR_DISJOINT,
-  HA_READ_MBR_EQUAL
+  HA_READ_MBR_CONTAIN,            /* Minimum Bounding Rectangle contains */
+  HA_READ_MBR_INTERSECT,          /* Minimum Bounding Rectangle intersect */
+  HA_READ_MBR_WITHIN,             /* Minimum Bounding Rectangle within */
+  HA_READ_MBR_DISJOINT,           /* Minimum Bounding Rectangle disjoint */
+  HA_READ_MBR_EQUAL               /* Minimum Bounding Rectangle equal */
 };
 
 	/* Key algorithm types */
@@ -522,41 +522,40 @@ enum data_file_type {
 
 /* For key ranges */
 
-/* from -inf */
-#define NO_MIN_RANGE	1
-
-/* to +inf */
-#define NO_MAX_RANGE	2
-
-/*  X < key, i.e. not including the left endpoint */
-#define NEAR_MIN	4
-
-/* X > key, i.e. not including the right endpoint */
-#define NEAR_MAX	8
-
-/* 
-  This flag means that index is a unique index, and the interval is 
-  equivalent to "AND(keypart_i = const_i)", where all of const_i are not NULLs.
-*/
-#define UNIQUE_RANGE	16
-
-/* 
-  This flag means that the interval is equivalent to 
-  "AND(keypart_i = const_i)", where not all key parts may be used but all of 
-  const_i are not NULLs.
-*/
-#define EQ_RANGE	32
-
-/*
-  This flag has the same meaning as UNIQUE_RANGE, except that for at least
-  one keypart the condition is "keypart IS NULL". 
-*/
-#define NULL_RANGE	64
-
-#define GEOM_FLAG      128
+enum key_range_flag {
+  NO_MIN_RANGE=      1 << 0,                    ///< from -inf
+  NO_MAX_RANGE=      1 << 1,                    ///< to +inf
+  /*  X < key, i.e. not including the left endpoint */
+  NEAR_MIN=          1 << 2,
+  /* X > key, i.e. not including the right endpoint */
+  NEAR_MAX=          1 << 3,
+  /*
+    This flag means that index is a unique index, and the interval is
+    equivalent to "AND(keypart_i = const_i)", where all of const_i are
+    not NULLs.
+  */
+  UNIQUE_RANGE=      1 << 4,
+  /*
+    This flag means that the interval is equivalent to 
+    "AND(keypart_i = const_i)", where not all key parts may be used 
+    but all of const_i are not NULLs.
+  */
+  EQ_RANGE=          1 << 5,
+  /*
+    This flag has the same meaning as UNIQUE_RANGE, except that for at
+    least one keypart the condition is "keypart IS NULL".
+  */
+  NULL_RANGE=        1 << 6,
+  GEOM_FLAG=         1 << 7,                     ///< GIS
+  /* Deprecated, currently used only by NDB at row retrieval */
+  SKIP_RANGE=        1 << 8,
+  /* 
+    Used together with EQ_RANGE to indicate that index statistics
+    should be used instead of sampling the index.
+  */
+  USE_INDEX_STATISTICS= 1 << 9
+};
 
-/* Deprecated, currently used only by NDB at row retrieval */
-#define SKIP_RANGE     256
 
 typedef struct st_key_range
 {

=== modified file 'mysql-test/include/join_cache.inc'
--- a/mysql-test/include/join_cache.inc	2011-11-04 15:20:13 +0000
+++ b/mysql-test/include/join_cache.inc	2012-01-26 15:42:39 +0000
@@ -1984,3 +1984,35 @@ GROUP BY t1.col2;
 DROP TABLE t1,t2;
 
 --echo # End of Bug#12997905
+
+--echo #
+--echo # Bug 13596330 - EXTRA ROW ON SELECT WITH NESTED IN CLAUSE + IS
+--echo # NULL WHEN SEMIJOIN + BNL IS ON
+--echo #
+
+CREATE TABLE t1 (  
+  col_int_nokey int
+);
+INSERT INTO t1 VALUES(-1),(-1);
+
+CREATE TABLE t2 (
+  col_int_nokey int,
+  col_datetime_nokey datetime NOT NULL,
+  col_varchar_key varchar(1),
+  KEY col_varchar_key (col_varchar_key)
+);
+
+INSERT INTO t2 VALUES (9, '2002-08-25 20:35:06', 'e'),
+                      (9, '2002-08-25 20:35:06', 'e');
+
+let $query=SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+      ( SELECT col_varchar_key FROM t2 AS CHILD1
+        WHERE PARENT1.col_datetime_nokey IS NULL
+              AND t1.col_int_nokey IS NULL )
+;
+eval EXPLAIN $query;
+eval $query;
+
+DROP TABLE t1,t2;

=== modified file 'mysql-test/include/subquery_mat.inc'
--- a/mysql-test/include/subquery_mat.inc	2012-01-16 14:00:28 +0000
+++ b/mysql-test/include/subquery_mat.inc	2012-01-20 09:07:08 +0000
@@ -980,4 +980,46 @@ DROP TABLE t1, t2;
 
 --echo # End of test for bug#13591383.
 
+--echo #
+--echo # Bug#13607423: Assertion !(*tab->on_expr_ref->is_expensive())
+--echo # in join_read_const_table()
+--echo #
+
+CREATE TABLE t1 (
+  pk int NOT NULL,
+  col_int_nokey int DEFAULT NULL,
+  col_int_key int DEFAULT NULL,
+  PRIMARY KEY (pk),
+  KEY col_int_key (col_int_key)
+) ENGINE=MyISAM;
+
+INSERT INTO t1 VALUES (1,2,4), (2,150,62);
+
+CREATE TABLE t2 (
+  pk int NOT NULL,
+  col_int_key int DEFAULT NULL,
+  PRIMARY KEY (pk)
+) ENGINE=MyISAM;
+
+INSERT INTO t2 VALUES (1,7);
+
+let $query=
+SELECT table1.pk, table2.pk
+FROM t2 AS table1 LEFT JOIN t2 AS table2
+     ON table2.pk = table1.pk AND
+        table2.col_int_key IN
+         (SELECT col_int_key
+          FROM t1 AS innr
+          WHERE innr.col_int_nokey > innr.col_int_nokey
+          GROUP BY col_int_key
+          HAVING COUNT(*) > 0
+         );
+
+eval explain $query;
+eval $query;
+
+DROP TABLE t1, t2;
+
+--echo # End of test for bug#13607423.
+
 --echo # End of 5.6 tests

=== modified file 'mysql-test/include/subquery_sj.inc'
--- a/mysql-test/include/subquery_sj.inc	2012-01-16 12:51:06 +0000
+++ b/mysql-test/include/subquery_sj.inc	2012-01-27 12:28:14 +0000
@@ -4819,4 +4819,52 @@ eval $query;
 
 DROP TABLE t1,t2,t3;
 
+--echo #
+--echo # Bug #13596176: Missing row on select with nested in clause when
+--echo #                matr=on and bnl=off + MyISAM
+--echo #
+
+CREATE TABLE t1 (
+  int_key int DEFAULT NULL,
+  vc_key varchar(1) DEFAULT NULL,
+  vc_nokey varchar(1) DEFAULT NULL,
+  KEY int_key (int_key),
+  KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+
+INSERT INTO t1 VALUES
+ (8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+ (9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+ (2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+ (0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+ (NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+
+CREATE TABLE t2 (
+  int_key int DEFAULT NULL,
+  vc_key varchar(1) DEFAULT NULL,
+  KEY int_key (int_key),
+  KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+
+INSERT INTO t2 VALUES (8,'g');
+
+let $query=
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+ (SELECT vc_nokey, vc_nokey
+  FROM t1 middle
+  WHERE vc_nokey IN
+   (SELECT child1.vc_key
+    FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+   )
+ );
+
+eval explain $query;
+eval $query;
+
+DROP TABLE t1, t2;
+
+--echo # End of test for bug#13596176.
+
 --echo # End of 5.6 tests

=== modified file 'mysql-test/r/derived.result'
--- a/mysql-test/r/derived.result	2012-01-17 09:27:34 +0000
+++ b/mysql-test/r/derived.result	2012-01-27 14:22:35 +0000
@@ -845,8 +845,8 @@ EXPLAIN EXTENDED
 SELECT * FROM t1,v3 AS v31,v3 WHERE t1.f1=v31.f1 and t1.f1=v3.f1;
 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 where
-1	PRIMARY	<derived2>	ref	auto_key0	auto_key0	5	test.t1.f1	3	100.00	Using where
-1	PRIMARY	<derived3>	ref	auto_key0	auto_key0	5	v31.f1	3	100.00	Using where
+1	PRIMARY	<derived2>	ref	auto_key0	auto_key0	5	test.t1.f1	3	100.00	
+1	PRIMARY	<derived3>	ref	auto_key0	auto_key0	5	test.t1.f1	3	100.00	
 3	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	6	100.00	
 3	DERIVED	t11	ALL	NULL	NULL	NULL	NULL	6	100.00	Using join buffer (Block Nested Loop)
 2	DERIVED	t1	ALL	NULL	NULL	NULL	NULL	6	100.00	

=== modified file 'mysql-test/r/greedy_optimizer.result'
--- a/mysql-test/r/greedy_optimizer.result	2011-08-03 11:29:20 +0000
+++ b/mysql-test/r/greedy_optimizer.result	2012-01-20 15:30:14 +0000
@@ -1068,7 +1068,7 @@ AND t10000.K=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	ALL	NULL	NULL	NULL	NULL	10	Using where
 1	SIMPLE	t100	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	t10000	eq_ref	PRIMARY	PRIMARY	4	test.t100.K	1	Using where; Using index
+1	SIMPLE	t10000	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
 SELECT STRAIGHT_JOIN COUNT(*) FROM t10,t100,t10000
 WHERE t100.K=t10.I
 AND t10000.K=t10.I;
@@ -1094,7 +1094,7 @@ AND t10000.K=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	ALL	NULL	NULL	NULL	NULL	10	Using where
 1	SIMPLE	t100	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	t10000	eq_ref	PRIMARY	PRIMARY	4	test.t100.K	1	Using where; Using index
+1	SIMPLE	t10000	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
 SELECT COUNT(*) FROM t10,t100,t10000
 WHERE t100.K=t10.I
 AND t10000.K=t10.I;
@@ -1107,7 +1107,7 @@ AND t10000.K=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	ALL	NULL	NULL	NULL	NULL	10	Using where
 1	SIMPLE	t100	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	t10000	eq_ref	PRIMARY	PRIMARY	4	test.t100.K	1	Using where; Using index
+1	SIMPLE	t10000	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
 SELECT COUNT(*) FROM t10,t10000,t100
 WHERE t100.K=t10.I
 AND t10000.K=t10.I;
@@ -1429,7 +1429,7 @@ AND t10000.I=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	t100	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	t10000	ref	IX	IX	5	test.t100.K	1000	Using where; Using index
+1	SIMPLE	t10000	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT STRAIGHT_JOIN COUNT(*) FROM t10,t100,t10000
 WHERE t100.K=t10.I
 AND t10000.I=t10.I;
@@ -1442,7 +1442,7 @@ AND t10000.I=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	t100	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	t10000	ref	IX	IX	5	test.t100.K	1000	Using where; Using index
+1	SIMPLE	t10000	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT COUNT(*) FROM t10,t100,t10000
 WHERE t100.K=t10.I
 AND t10000.I=t10.I;
@@ -1455,7 +1455,7 @@ AND t10000.I=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	t100	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	t10000	ref	IX	IX	5	test.t100.K	1000	Using where; Using index
+1	SIMPLE	t10000	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT COUNT(*) FROM t10,t10000,t100
 WHERE t100.K=t10.I
 AND t10000.I=t10.I;
@@ -1501,7 +1501,7 @@ AND Y.I=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	X	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	Y	ref	IX	IX	5	test.X.K	1000	Using where; Using index
+1	SIMPLE	Y	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT STRAIGHT_JOIN COUNT(*) FROM t10,t10000 X,t10000 Y
 WHERE X.K=t10.I
 AND Y.I=t10.I;
@@ -1514,7 +1514,7 @@ AND Y.I=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	X	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	Y	ref	IX	IX	5	test.X.K	1000	Using where; Using index
+1	SIMPLE	Y	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT COUNT(*) FROM t10,t10000 X,t10000 Y
 WHERE X.K=t10.I
 AND Y.I=t10.I;
@@ -1527,7 +1527,7 @@ AND Y.I=t10.I;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	X	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	Y	ref	IX	IX	5	test.X.K	1000	Using where; Using index
+1	SIMPLE	Y	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT COUNT(*) FROM t10,t10000 Y,t10000 X
 WHERE X.K=t10.I
 AND Y.I=t10.I;
@@ -1540,7 +1540,7 @@ AND Y.I=X.K;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	X	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	Y	ref	IX	IX	5	test.X.K	1000	Using where; Using index
+1	SIMPLE	Y	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT STRAIGHT_JOIN COUNT(*) FROM t10,t10000 X,t10000 Y
 WHERE X.K=t10.I
 AND Y.I=X.K;
@@ -1553,7 +1553,7 @@ AND Y.I=X.K;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	X	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	Y	ref	IX	IX	5	test.X.K	1000	Using where; Using index
+1	SIMPLE	Y	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT COUNT(*) FROM t10,t10000 X,t10000 Y
 WHERE X.K=t10.I
 AND Y.I=X.K;
@@ -1566,7 +1566,7 @@ AND Y.I=X.K;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t10	index	IX	IX	5	NULL	10	Using where; Using index
 1	SIMPLE	X	eq_ref	PRIMARY	PRIMARY	4	test.t10.I	1	Using index
-1	SIMPLE	Y	ref	IX	IX	5	test.X.K	1000	Using where; Using index
+1	SIMPLE	Y	ref	IX	IX	5	test.t10.I	1000	Using index
 SELECT COUNT(*) FROM t10,t10000 Y,t10000 X
 WHERE X.K=t10.I
 AND Y.I=X.K;

=== modified file 'mysql-test/r/join_cache_bka.result'
--- a/mysql-test/r/join_cache_bka.result	2012-01-17 09:27:34 +0000
+++ b/mysql-test/r/join_cache_bka.result	2012-01-27 14:22:35 +0000
@@ -477,7 +477,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where; Using join buffer (Batched Key Access)
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where; Using join buffer (Batched Key Access)
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where; Using join buffer (Batched Key Access)
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -784,7 +784,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where; Using join buffer (Batched Key Access)
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where; Using join buffer (Batched Key Access)
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where; Using join buffer (Batched Key Access)
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -1308,7 +1308,7 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using join buffer (Batched Key Access)
 1	SIMPLE	t7	ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using index
 1	SIMPLE	t8	eq_ref	PRIMARY	PRIMARY	4	test.t7.artistid	1	Using join buffer (Batched Key Access)
-1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t7.metaid	2	Using index condition; Using join buffer (Batched Key Access)
+1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t1.metaid	2	Using join buffer (Batched Key Access)
 1	SIMPLE	t10	eq_ref	PRIMARY,t10_genreid	PRIMARY	4	test.t9.subgenreid	1	Using join buffer (Batched Key Access)
 1	SIMPLE	t11	eq_ref	PRIMARY	PRIMARY	4	test.t10.genreid	1	Using join buffer (Batched Key Access)
 1	SIMPLE	t3	ALL	t3_metaid,t3_formatid,t3_metaidformatid	NULL	NULL	NULL	2	Using where; Using join buffer (Block Nested Loop)
@@ -2699,4 +2699,40 @@ col1
 a
 DROP TABLE t1,t2;
 # End of Bug#12997905
+#
+# Bug 13596330 - EXTRA ROW ON SELECT WITH NESTED IN CLAUSE + IS
+# NULL WHEN SEMIJOIN + BNL IS ON
+#
+CREATE TABLE t1 (  
+col_int_nokey int
+);
+INSERT INTO t1 VALUES(-1),(-1);
+CREATE TABLE t2 (
+col_int_nokey int,
+col_datetime_nokey datetime NOT NULL,
+col_varchar_key varchar(1),
+KEY col_varchar_key (col_varchar_key)
+);
+INSERT INTO t2 VALUES (9, '2002-08-25 20:35:06', 'e'),
+(9, '2002-08-25 20:35:06', 'e');
+EXPLAIN SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	PARENT1	ALL	NULL	NULL	NULL	NULL	2	
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where; Using join buffer (Block Nested Loop)
+2	DEPENDENT SUBQUERY	CHILD1	index_subquery	col_varchar_key	col_varchar_key	4	func	2	Using index; Using where
+SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+col_varchar_key
+DROP TABLE t1,t2;
 set optimizer_switch = default;

=== modified file 'mysql-test/r/join_cache_bka_nixbnl.result'
--- a/mysql-test/r/join_cache_bka_nixbnl.result	2012-01-17 09:27:34 +0000
+++ b/mysql-test/r/join_cache_bka_nixbnl.result	2012-01-27 14:22:35 +0000
@@ -477,7 +477,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where; Using join buffer (Batched Key Access)
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where; Using join buffer (Batched Key Access)
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where; Using join buffer (Batched Key Access)
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -784,7 +784,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where; Using join buffer (Batched Key Access)
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where; Using join buffer (Batched Key Access)
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where; Using join buffer (Batched Key Access)
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -1308,7 +1308,7 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using join buffer (Batched Key Access)
 1	SIMPLE	t7	ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using index
 1	SIMPLE	t8	eq_ref	PRIMARY	PRIMARY	4	test.t7.artistid	1	Using join buffer (Batched Key Access)
-1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t7.metaid	2	Using index condition; Using join buffer (Batched Key Access)
+1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t1.metaid	2	Using join buffer (Batched Key Access)
 1	SIMPLE	t10	eq_ref	PRIMARY,t10_genreid	PRIMARY	4	test.t9.subgenreid	1	Using join buffer (Batched Key Access)
 1	SIMPLE	t11	eq_ref	PRIMARY	PRIMARY	4	test.t10.genreid	1	Using join buffer (Batched Key Access)
 1	SIMPLE	t3	ref	t3_metaid,t3_formatid,t3_metaidformatid	t3_metaid	4	test.t1.metaid	2	Using where; Using join buffer (Batched Key Access)
@@ -2699,4 +2699,40 @@ col1
 a
 DROP TABLE t1,t2;
 # End of Bug#12997905
+#
+# Bug 13596330 - EXTRA ROW ON SELECT WITH NESTED IN CLAUSE + IS
+# NULL WHEN SEMIJOIN + BNL IS ON
+#
+CREATE TABLE t1 (  
+col_int_nokey int
+);
+INSERT INTO t1 VALUES(-1),(-1);
+CREATE TABLE t2 (
+col_int_nokey int,
+col_datetime_nokey datetime NOT NULL,
+col_varchar_key varchar(1),
+KEY col_varchar_key (col_varchar_key)
+);
+INSERT INTO t2 VALUES (9, '2002-08-25 20:35:06', 'e'),
+(9, '2002-08-25 20:35:06', 'e');
+EXPLAIN SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	PARENT1	ALL	NULL	NULL	NULL	NULL	2	
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
+2	DEPENDENT SUBQUERY	CHILD1	index_subquery	col_varchar_key	col_varchar_key	4	func	2	Using index; Using where
+SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+col_varchar_key
+DROP TABLE t1,t2;
 set optimizer_switch = default;

=== modified file 'mysql-test/r/join_cache_bkaunique.result'
--- a/mysql-test/r/join_cache_bkaunique.result	2012-01-17 09:27:34 +0000
+++ b/mysql-test/r/join_cache_bkaunique.result	2012-01-27 14:22:35 +0000
@@ -478,7 +478,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where; Using join buffer (Batched Key Access (unique))
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where; Using join buffer (Batched Key Access (unique))
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where; Using join buffer (Batched Key Access (unique))
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -785,7 +785,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where; Using join buffer (Batched Key Access (unique))
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where; Using join buffer (Batched Key Access (unique))
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where; Using join buffer (Batched Key Access (unique))
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -1309,7 +1309,7 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using join buffer (Batched Key Access (unique))
 1	SIMPLE	t7	ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using index
 1	SIMPLE	t8	eq_ref	PRIMARY	PRIMARY	4	test.t7.artistid	1	Using join buffer (Batched Key Access (unique))
-1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t7.metaid	2	Using index condition; Using join buffer (Batched Key Access (unique))
+1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t1.metaid	2	Using join buffer (Batched Key Access (unique))
 1	SIMPLE	t10	eq_ref	PRIMARY,t10_genreid	PRIMARY	4	test.t9.subgenreid	1	Using join buffer (Batched Key Access (unique))
 1	SIMPLE	t11	eq_ref	PRIMARY	PRIMARY	4	test.t10.genreid	1	Using join buffer (Batched Key Access (unique))
 1	SIMPLE	t3	ALL	t3_metaid,t3_formatid,t3_metaidformatid	NULL	NULL	NULL	2	Using where; Using join buffer (Block Nested Loop)
@@ -2700,4 +2700,40 @@ col1
 a
 DROP TABLE t1,t2;
 # End of Bug#12997905
+#
+# Bug 13596330 - EXTRA ROW ON SELECT WITH NESTED IN CLAUSE + IS
+# NULL WHEN SEMIJOIN + BNL IS ON
+#
+CREATE TABLE t1 (  
+col_int_nokey int
+);
+INSERT INTO t1 VALUES(-1),(-1);
+CREATE TABLE t2 (
+col_int_nokey int,
+col_datetime_nokey datetime NOT NULL,
+col_varchar_key varchar(1),
+KEY col_varchar_key (col_varchar_key)
+);
+INSERT INTO t2 VALUES (9, '2002-08-25 20:35:06', 'e'),
+(9, '2002-08-25 20:35:06', 'e');
+EXPLAIN SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	PARENT1	ALL	NULL	NULL	NULL	NULL	2	
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where; Using join buffer (Block Nested Loop)
+2	DEPENDENT SUBQUERY	CHILD1	index_subquery	col_varchar_key	col_varchar_key	4	func	2	Using index; Using where
+SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+col_varchar_key
+DROP TABLE t1,t2;
 set optimizer_switch = default;

=== modified file 'mysql-test/r/join_cache_bnl.result'
--- a/mysql-test/r/join_cache_bnl.result	2012-01-17 09:27:34 +0000
+++ b/mysql-test/r/join_cache_bnl.result	2012-01-27 14:22:35 +0000
@@ -478,7 +478,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -785,7 +785,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -1309,7 +1309,7 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	
 1	SIMPLE	t7	ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using index
 1	SIMPLE	t8	eq_ref	PRIMARY	PRIMARY	4	test.t7.artistid	1	
-1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t7.metaid	2	Using index condition
+1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t1.metaid	2	
 1	SIMPLE	t10	eq_ref	PRIMARY,t10_genreid	PRIMARY	4	test.t9.subgenreid	1	
 1	SIMPLE	t11	eq_ref	PRIMARY	PRIMARY	4	test.t10.genreid	1	
 1	SIMPLE	t3	ALL	t3_metaid,t3_formatid,t3_metaidformatid	NULL	NULL	NULL	2	Using where; Using join buffer (Block Nested Loop)
@@ -2700,4 +2700,40 @@ col1
 a
 DROP TABLE t1,t2;
 # End of Bug#12997905
+#
+# Bug 13596330 - EXTRA ROW ON SELECT WITH NESTED IN CLAUSE + IS
+# NULL WHEN SEMIJOIN + BNL IS ON
+#
+CREATE TABLE t1 (  
+col_int_nokey int
+);
+INSERT INTO t1 VALUES(-1),(-1);
+CREATE TABLE t2 (
+col_int_nokey int,
+col_datetime_nokey datetime NOT NULL,
+col_varchar_key varchar(1),
+KEY col_varchar_key (col_varchar_key)
+);
+INSERT INTO t2 VALUES (9, '2002-08-25 20:35:06', 'e'),
+(9, '2002-08-25 20:35:06', 'e');
+EXPLAIN SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	PARENT1	ALL	NULL	NULL	NULL	NULL	2	
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where; Using join buffer (Block Nested Loop)
+2	DEPENDENT SUBQUERY	CHILD1	index_subquery	col_varchar_key	col_varchar_key	4	func	2	Using index; Using where
+SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+col_varchar_key
+DROP TABLE t1,t2;
 set optimizer_switch = default;

=== modified file 'mysql-test/r/join_cache_nojb.result'
--- a/mysql-test/r/join_cache_nojb.result	2012-01-17 09:27:34 +0000
+++ b/mysql-test/r/join_cache_nojb.result	2012-01-27 14:22:35 +0000
@@ -478,7 +478,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -785,7 +785,7 @@ CountryLanguage.Percentage > 50;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	CountryLanguage	ALL	PRIMARY,Percentage	NULL	NULL	NULL	984	Using where
 1	SIMPLE	Country	eq_ref	PRIMARY	PRIMARY	3	world.CountryLanguage.Country	1	Using where
-1	SIMPLE	City	ref	Country	Country	3	world.Country.Code	18	Using index condition; Using where
+1	SIMPLE	City	ref	Country	Country	3	world.CountryLanguage.Country	18	Using where
 SELECT City.Name, Country.Name, CountryLanguage.Language
 FROM City,Country,CountryLanguage
 WHERE City.Country=Country.Code AND
@@ -1309,7 +1309,7 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	
 1	SIMPLE	t7	ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using index
 1	SIMPLE	t8	eq_ref	PRIMARY	PRIMARY	4	test.t7.artistid	1	
-1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t7.metaid	2	Using index condition
+1	SIMPLE	t9	ref	PRIMARY,t9_subgenreid,t9_metaid	t9_metaid	4	test.t1.metaid	2	
 1	SIMPLE	t10	eq_ref	PRIMARY,t10_genreid	PRIMARY	4	test.t9.subgenreid	1	
 1	SIMPLE	t11	eq_ref	PRIMARY	PRIMARY	4	test.t10.genreid	1	
 1	SIMPLE	t3	ref	t3_metaid,t3_formatid,t3_metaidformatid	t3_metaid	4	test.t1.metaid	2	Using where
@@ -2700,4 +2700,40 @@ col1
 a
 DROP TABLE t1,t2;
 # End of Bug#12997905
+#
+# Bug 13596330 - EXTRA ROW ON SELECT WITH NESTED IN CLAUSE + IS
+# NULL WHEN SEMIJOIN + BNL IS ON
+#
+CREATE TABLE t1 (  
+col_int_nokey int
+);
+INSERT INTO t1 VALUES(-1),(-1);
+CREATE TABLE t2 (
+col_int_nokey int,
+col_datetime_nokey datetime NOT NULL,
+col_varchar_key varchar(1),
+KEY col_varchar_key (col_varchar_key)
+);
+INSERT INTO t2 VALUES (9, '2002-08-25 20:35:06', 'e'),
+(9, '2002-08-25 20:35:06', 'e');
+EXPLAIN SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	PARENT1	ALL	NULL	NULL	NULL	NULL	2	
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
+2	DEPENDENT SUBQUERY	CHILD1	index_subquery	col_varchar_key	col_varchar_key	4	func	2	Using index; Using where
+SELECT PARENT1.col_varchar_key
+FROM t2 AS PARENT1 LEFT JOIN t1 USING (col_int_nokey)
+WHERE PARENT1.col_varchar_key IN
+( SELECT col_varchar_key FROM t2 AS CHILD1
+WHERE PARENT1.col_datetime_nokey IS NULL
+AND t1.col_int_nokey IS NULL )
+;
+col_varchar_key
+DROP TABLE t1,t2;
 set optimizer_switch = default;

=== modified file 'mysql-test/r/join_nested.result'
--- a/mysql-test/r/join_nested.result	2011-08-03 11:29:20 +0000
+++ b/mysql-test/r/join_nested.result	2012-01-20 15:30:14 +0000
@@ -1729,9 +1729,9 @@ LEFT JOIN 
 (t5 JOIN t4 ON t5.carrier_id = t4.id)
 ON t4.carrier = t1.carrier;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	36	
-1	SIMPLE	t3	ref	package_id	package_id	5	test.t1.id	1	Using where; Using index
-1	SIMPLE	t2	ref	package_id	package_id	5	test.t3.package_id	5	Using where; Using index
+1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	36	Using where
+1	SIMPLE	t3	ref	package_id	package_id	5	test.t1.id	1	Using index
+1	SIMPLE	t2	ref	package_id	package_id	5	test.t1.id	5	Using index
 1	SIMPLE	t4	eq_ref	PRIMARY,id	PRIMARY	2	test.t1.carrier	1	
 1	SIMPLE	t5	ref	carrier_id	carrier_id	5	test.t4.id	22	Using index
 SELECT COUNT(*) 

=== modified file 'mysql-test/r/join_nested_bka.result'
--- a/mysql-test/r/join_nested_bka.result	2011-09-07 10:21:50 +0000
+++ b/mysql-test/r/join_nested_bka.result	2012-01-20 15:30:14 +0000
@@ -1730,9 +1730,9 @@ LEFT JOIN 
 (t5 JOIN t4 ON t5.carrier_id = t4.id)
 ON t4.carrier = t1.carrier;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	36	
-1	SIMPLE	t3	ref	package_id	package_id	5	test.t1.id	1	Using where; Using index
-1	SIMPLE	t2	ref	package_id	package_id	5	test.t3.package_id	5	Using where; Using index
+1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	36	Using where
+1	SIMPLE	t3	ref	package_id	package_id	5	test.t1.id	1	Using index
+1	SIMPLE	t2	ref	package_id	package_id	5	test.t1.id	5	Using index
 1	SIMPLE	t4	eq_ref	PRIMARY,id	PRIMARY	2	test.t1.carrier	1	
 1	SIMPLE	t5	ref	carrier_id	carrier_id	5	test.t4.id	22	Using index
 SELECT COUNT(*) 

=== modified file 'mysql-test/r/join_nested_bka_nixbnl.result'
--- a/mysql-test/r/join_nested_bka_nixbnl.result	2011-10-05 13:16:38 +0000
+++ b/mysql-test/r/join_nested_bka_nixbnl.result	2012-01-20 15:30:14 +0000
@@ -1734,7 +1734,7 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	4	test.t2.package_id	1	Using join buffer (Batched Key Access)
 1	SIMPLE	t4	eq_ref	PRIMARY,id	PRIMARY	2	test.t1.carrier	1	
 1	SIMPLE	t5	ref	carrier_id	carrier_id	5	test.t4.id	22	Using index
-1	SIMPLE	t3	ref	package_id	package_id	5	test.t1.id	1	Using where; Using index
+1	SIMPLE	t3	ref	package_id	package_id	5	test.t2.package_id	1	Using index
 SELECT COUNT(*) 
 FROM ((t2 JOIN t1 ON t2.package_id = t1.id) 
 JOIN t3 ON t3.package_id = t1.id)

=== modified file 'mysql-test/r/mysqld--help-notwin.result'
--- a/mysql-test/r/mysqld--help-notwin.result	2012-01-25 10:07:23 +0000
+++ b/mysql-test/r/mysqld--help-notwin.result	2012-01-30 10:34:28 +0000
@@ -151,6 +151,10 @@ The following options may be given as th
  --div-precision-increment=# 
  Precision of the result of '/' operator will be increased
  on that value
+ --eq-range-index-dive-limit=# 
+ The optimizer will use existing index statistics instead
+ of doing index dives for equality ranges if the number of
+ equality ranges is larger than or equal to this number.
  --event-scheduler[=name] 
  Enable the event scheduler. Possible values are ON, OFF,
  and DISABLED (keep the event scheduler completely
@@ -904,6 +908,7 @@ delayed-insert-timeout 300
 delayed-queue-size 1000
 disconnect-slave-event-count 0
 div-precision-increment 4
+eq-range-index-dive-limit 10
 event-scheduler OFF
 expire-logs-days 0
 external-locking FALSE

=== modified file 'mysql-test/r/mysqld--help-win.result'
--- a/mysql-test/r/mysqld--help-win.result	2012-01-26 07:01:30 +0000
+++ b/mysql-test/r/mysqld--help-win.result	2012-01-30 10:34:28 +0000
@@ -151,6 +151,10 @@ The following options may be given as th
  --div-precision-increment=# 
  Precision of the result of '/' operator will be increased
  on that value
+ --eq-range-index-dive-limit=# 
+ The optimizer will use existing index statistics instead
+ of doing index dives for equality ranges if the number of
+ equality ranges is larger than or equal to this number.
  --event-scheduler[=name] 
  Enable the event scheduler. Possible values are ON, OFF,
  and DISABLED (keep the event scheduler completely
@@ -912,6 +916,7 @@ delayed-insert-timeout 300
 delayed-queue-size 1000
 disconnect-slave-event-count 0
 div-precision-increment 4
+eq-range-index-dive-limit 10
 event-scheduler OFF
 expire-logs-days 0
 external-locking FALSE

=== modified file 'mysql-test/r/subquery_mat.result'
--- a/mysql-test/r/subquery_mat.result	2012-01-16 14:00:28 +0000
+++ b/mysql-test/r/subquery_mat.result	2012-01-20 15:30:14 +0000
@@ -1246,5 +1246,51 @@ v	v
 1	NULL
 DROP TABLE t1, t2;
 # End of test for bug#13591383.
+#
+# Bug#13607423: Assertion !(*tab->on_expr_ref->is_expensive())
+# in join_read_const_table()
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int DEFAULT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2,4), (2,150,62);
+CREATE TABLE t2 (
+pk int NOT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,7);
+explain SELECT table1.pk, table2.pk
+FROM t2 AS table1 LEFT JOIN t2 AS table2
+ON table2.pk = table1.pk AND
+table2.col_int_key IN
+(SELECT col_int_key
+FROM t1 AS innr
+WHERE innr.col_int_nokey > innr.col_int_nokey
+GROUP BY col_int_key
+HAVING COUNT(*) > 0
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	table1	system	NULL	NULL	NULL	NULL	1	
+1	PRIMARY	table2	const	PRIMARY	PRIMARY	4	const	1	Using where
+2	SUBQUERY	innr	ALL	NULL	NULL	NULL	NULL	2	Using where; Using temporary; Using filesort
+SELECT table1.pk, table2.pk
+FROM t2 AS table1 LEFT JOIN t2 AS table2
+ON table2.pk = table1.pk AND
+table2.col_int_key IN
+(SELECT col_int_key
+FROM t1 AS innr
+WHERE innr.col_int_nokey > innr.col_int_nokey
+GROUP BY col_int_key
+HAVING COUNT(*) > 0
+);
+pk	pk
+1	NULL
+DROP TABLE t1, t2;
+# End of test for bug#13607423.
 # 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-16 14:00:28 +0000
+++ b/mysql-test/r/subquery_mat_all.result	2012-01-20 15:30:14 +0000
@@ -1247,5 +1247,51 @@ v	v
 1	NULL
 DROP TABLE t1, t2;
 # End of test for bug#13591383.
+#
+# Bug#13607423: Assertion !(*tab->on_expr_ref->is_expensive())
+# in join_read_const_table()
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int DEFAULT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2,4), (2,150,62);
+CREATE TABLE t2 (
+pk int NOT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,7);
+explain SELECT table1.pk, table2.pk
+FROM t2 AS table1 LEFT JOIN t2 AS table2
+ON table2.pk = table1.pk AND
+table2.col_int_key IN
+(SELECT col_int_key
+FROM t1 AS innr
+WHERE innr.col_int_nokey > innr.col_int_nokey
+GROUP BY col_int_key
+HAVING COUNT(*) > 0
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	table1	system	NULL	NULL	NULL	NULL	1	
+1	PRIMARY	table2	const	PRIMARY	PRIMARY	4	const	1	Using where
+2	SUBQUERY	innr	ALL	NULL	NULL	NULL	NULL	2	Using where; Using temporary; Using filesort
+SELECT table1.pk, table2.pk
+FROM t2 AS table1 LEFT JOIN t2 AS table2
+ON table2.pk = table1.pk AND
+table2.col_int_key IN
+(SELECT col_int_key
+FROM t1 AS innr
+WHERE innr.col_int_nokey > innr.col_int_nokey
+GROUP BY col_int_key
+HAVING COUNT(*) > 0
+);
+pk	pk
+1	NULL
+DROP TABLE t1, t2;
+# End of test for bug#13607423.
 # 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-16 14:00:28 +0000
+++ b/mysql-test/r/subquery_mat_none.result	2012-01-20 09:07:08 +0000
@@ -1244,5 +1244,51 @@ v	v
 1	NULL
 DROP TABLE t1, t2;
 # End of test for bug#13591383.
+#
+# Bug#13607423: Assertion !(*tab->on_expr_ref->is_expensive())
+# in join_read_const_table()
+#
+CREATE TABLE t1 (
+pk int NOT NULL,
+col_int_nokey int DEFAULT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk),
+KEY col_int_key (col_int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1,2,4), (2,150,62);
+CREATE TABLE t2 (
+pk int NOT NULL,
+col_int_key int DEFAULT NULL,
+PRIMARY KEY (pk)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,7);
+explain SELECT table1.pk, table2.pk
+FROM t2 AS table1 LEFT JOIN t2 AS table2
+ON table2.pk = table1.pk AND
+table2.col_int_key IN
+(SELECT col_int_key
+FROM t1 AS innr
+WHERE innr.col_int_nokey > innr.col_int_nokey
+GROUP BY col_int_key
+HAVING COUNT(*) > 0
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	table1	system	NULL	NULL	NULL	NULL	1	
+1	PRIMARY	table2	system	PRIMARY	NULL	NULL	NULL	1	
+2	DEPENDENT SUBQUERY	innr	index	NULL	col_int_key	5	NULL	2	Using where; Using filesort
+SELECT table1.pk, table2.pk
+FROM t2 AS table1 LEFT JOIN t2 AS table2
+ON table2.pk = table1.pk AND
+table2.col_int_key IN
+(SELECT col_int_key
+FROM t1 AS innr
+WHERE innr.col_int_nokey > innr.col_int_nokey
+GROUP BY col_int_key
+HAVING COUNT(*) > 0
+);
+pk	pk
+1	NULL
+DROP TABLE t1, t2;
+# End of test for bug#13607423.
 # End of 5.6 tests
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_all.result'
--- a/mysql-test/r/subquery_sj_all.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_all.result	2012-01-27 12:28:14 +0000
@@ -5333,7 +5333,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using index condition; Using MRR; Materialize; Scan
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using index condition; Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using index condition; Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5876,7 +5876,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using index condition; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7626,5 +7626,58 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_all_bka.result'
--- a/mysql-test/r/subquery_sj_all_bka.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_all_bka.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using index condition; Using MRR; Materialize; Scan
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; Using join buffer (Batched Key Access)
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using index condition; Using where; Using join buffer (Batched Key Access)
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using index condition; Using where; Using join buffer (Batched Key Access)
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using index condition; End temporary; Using join buffer (Batched Key Access)
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary; Using join buffer (Batched Key Access)
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where; Using join buffer (Batched Key Access)
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_all_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_all_bka_nixbnl.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_all_bka_nixbnl.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using index condition; Using MRR; Materialize; Scan
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; Using join buffer (Batched Key Access)
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using index condition; Using where; Using join buffer (Batched Key Access)
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using index condition; Using where; Using join buffer (Batched Key Access)
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using index condition; End temporary; Using join buffer (Batched Key Access)
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary; Using join buffer (Batched Key Access)
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start materialize; Scan
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End materialize
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where; Using join buffer (Batched Key Access)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_all_bkaunique.result'
--- a/mysql-test/r/subquery_sj_all_bkaunique.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_all_bkaunique.result	2012-01-27 12:28:14 +0000
@@ -5335,7 +5335,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using index condition; Using MRR; Materialize; Scan
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; Using join buffer (Batched Key Access (unique))
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using index condition; Using where; Using join buffer (Batched Key Access (unique))
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using index condition; Using where; Using join buffer (Batched Key Access (unique))
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5878,7 +5878,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using index condition; End temporary; Using join buffer (Batched Key Access (unique))
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary; Using join buffer (Batched Key Access (unique))
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7628,6 +7628,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where; Using join buffer (Batched Key Access (unique))
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_dupsweed.result'
--- a/mysql-test/r/subquery_sj_dupsweed.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_dupsweed.result	2012-01-27 12:28:14 +0000
@@ -5332,7 +5332,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5875,7 +5875,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7625,5 +7625,58 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_dupsweed_bka.result'
--- a/mysql-test/r/subquery_sj_dupsweed_bka.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_dupsweed_bka.result	2012-01-27 12:28:14 +0000
@@ -5333,7 +5333,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5876,7 +5876,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7626,6 +7626,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_dupsweed_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_dupsweed_bka_nixbnl.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_dupsweed_bka_nixbnl.result	2012-01-27 12:28:14 +0000
@@ -5333,7 +5333,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5876,7 +5876,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7626,6 +7626,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_dupsweed_bkaunique.result'
--- a/mysql-test/r/subquery_sj_dupsweed_bkaunique.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_dupsweed_bkaunique.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_firstmatch.result'
--- a/mysql-test/r/subquery_sj_firstmatch.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_firstmatch.result	2012-01-27 12:28:14 +0000
@@ -5333,7 +5333,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5876,7 +5876,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7626,6 +7626,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 #
 # Bug#51457 Firstmatch semijoin strategy gives wrong results for

=== modified file 'mysql-test/r/subquery_sj_firstmatch_bka.result'
--- a/mysql-test/r/subquery_sj_firstmatch_bka.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_firstmatch_bka.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 #
 # Bug#51457 Firstmatch semijoin strategy gives wrong results for

=== modified file 'mysql-test/r/subquery_sj_firstmatch_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_firstmatch_bka_nixbnl.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_firstmatch_bka_nixbnl.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 #
 # Bug#51457 Firstmatch semijoin strategy gives wrong results for

=== modified file 'mysql-test/r/subquery_sj_firstmatch_bkaunique.result'
--- a/mysql-test/r/subquery_sj_firstmatch_bkaunique.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_firstmatch_bkaunique.result	2012-01-27 12:28:14 +0000
@@ -5335,7 +5335,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5878,7 +5878,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7628,6 +7628,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 #
 # Bug#51457 Firstmatch semijoin strategy gives wrong results for

=== modified file 'mysql-test/r/subquery_sj_loosescan.result'
--- a/mysql-test/r/subquery_sj_loosescan.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_loosescan.result	2012-01-27 12:28:14 +0000
@@ -5333,7 +5333,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5876,7 +5876,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7626,5 +7626,58 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_loosescan_bka.result'
--- a/mysql-test/r/subquery_sj_loosescan_bka.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_loosescan_bka.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_loosescan_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_loosescan_bka_nixbnl.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_loosescan_bka_nixbnl.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_loosescan_bkaunique.result'
--- a/mysql-test/r/subquery_sj_loosescan_bkaunique.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_loosescan_bkaunique.result	2012-01-27 12:28:14 +0000
@@ -5335,7 +5335,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Start temporary
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where; End temporary
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5878,7 +5878,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7628,6 +7628,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_mat.result'
--- a/mysql-test/r/subquery_sj_mat.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_mat.result	2012-01-27 12:28:14 +0000
@@ -5333,7 +5333,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Materialize; Scan
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5876,7 +5876,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7626,5 +7626,58 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_mat_bka.result'
--- a/mysql-test/r/subquery_sj_mat_bka.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_mat_bka.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Materialize; Scan
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_mat_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_mat_bka_nixbnl.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_mat_bka_nixbnl.result	2012-01-27 12:28:14 +0000
@@ -5334,7 +5334,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Materialize; Scan
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5877,7 +5877,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7627,6 +7627,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start materialize; Scan
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End materialize
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_mat_bkaunique.result'
--- a/mysql-test/r/subquery_sj_mat_bkaunique.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_mat_bkaunique.result	2012-01-27 12:28:14 +0000
@@ -5335,7 +5335,7 @@ t2.Population > 100000);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	range	Population,Country	Population	4	NULL	1	Using where; Materialize; Scan
 1	PRIMARY	t2	eq_ref	PRIMARY,Population	PRIMARY	3	test.t1.Country	1	Using where
-1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t2.Code,const	1	Using where
+1	PRIMARY	t3	eq_ref	PRIMARY,Percentage	PRIMARY	33	test.t1.Country,const	1	Using where
 DROP TABLE t1,t2,t3;
 CREATE TABLE t1 (
 Code char(3) NOT NULL DEFAULT '',
@@ -5878,7 +5878,7 @@ and t2.uid=t1.fid;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ref	uid	uid	5	const	4	Using where; Start temporary
 1	PRIMARY	t4	eq_ref	PRIMARY	PRIMARY	4	test.t3.fid	1	Using index
-1	PRIMARY	t1	ref	uid	uid	5	test.t4.uid	2	Using where; End temporary
+1	PRIMARY	t1	ref	uid	uid	5	test.t3.fid	2	End temporary
 1	PRIMARY	t2	ALL	PRIMARY	NULL	NULL	NULL	9	Using where; Using join buffer (Block Nested Loop)
 select name from t2, t1 
 where t1.uid in (select t4.uid from t4, t3 where t3.uid=1 and t4.uid=t3.fid)
@@ -7628,6 +7628,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	child1	index	int_key,vc_key	vc_key	9	NULL	1	Using where; Using index; Start temporary
+1	PRIMARY	outr	ref	vc_key	vc_key	4	test.child1.vc_key	3	Using where
+1	PRIMARY	child2	ref	int_key	int_key	5	test.child1.int_key	3	Using index
+1	PRIMARY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where; End temporary; Using join buffer (Block Nested Loop)
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_mat_nosj.result'
--- a/mysql-test/r/subquery_sj_mat_nosj.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_mat_nosj.result	2012-01-27 12:28:14 +0000
@@ -7702,5 +7702,58 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	outr	ALL	NULL	NULL	NULL	NULL	20	Using where
+2	SUBQUERY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where
+3	SUBQUERY	child1	system	int_key	NULL	NULL	NULL	1	
+3	SUBQUERY	child2	ref	int_key	int_key	5	const	3	Using index
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_none.result'
--- a/mysql-test/r/subquery_sj_none.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_none.result	2012-01-27 12:28:14 +0000
@@ -3402,7 +3402,7 @@ id	select_type	table	type	possible_keys	
 1	PRIMARY	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
 2	DEPENDENT SUBQUERY	t1	index	a	a	5	NULL	10	Using where; Using index
 2	DEPENDENT SUBQUERY	t2	ref	a	a	5	test.t1.a	1	Using index
-2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t2.a	1	Using where; Using index
+2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t1.a	1	Using index
 drop table t0, t1,t2,t3;
 
 Test that neither MaterializeLookup strategy for semijoin,
@@ -7637,5 +7637,58 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	outr	ALL	NULL	NULL	NULL	NULL	20	Using where
+2	DEPENDENT SUBQUERY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where
+3	DEPENDENT SUBQUERY	child1	system	int_key,vc_key	NULL	NULL	NULL	1	
+3	DEPENDENT SUBQUERY	child2	ref	int_key	int_key	5	const	3	Using where; Using index
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_none_bka.result'
--- a/mysql-test/r/subquery_sj_none_bka.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_none_bka.result	2012-01-27 12:28:14 +0000
@@ -3403,7 +3403,7 @@ id	select_type	table	type	possible_keys	
 1	PRIMARY	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
 2	DEPENDENT SUBQUERY	t1	index	a	a	5	NULL	10	Using where; Using index
 2	DEPENDENT SUBQUERY	t2	ref	a	a	5	test.t1.a	1	Using index
-2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t2.a	1	Using where; Using index
+2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t1.a	1	Using index
 drop table t0, t1,t2,t3;
 
 Test that neither MaterializeLookup strategy for semijoin,
@@ -7638,6 +7638,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	outr	ALL	NULL	NULL	NULL	NULL	20	Using where
+2	DEPENDENT SUBQUERY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where
+3	DEPENDENT SUBQUERY	child1	system	int_key,vc_key	NULL	NULL	NULL	1	
+3	DEPENDENT SUBQUERY	child2	ref	int_key	int_key	5	const	3	Using where; Using index
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_none_bka_nixbnl.result'
--- a/mysql-test/r/subquery_sj_none_bka_nixbnl.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_none_bka_nixbnl.result	2012-01-27 12:28:14 +0000
@@ -3403,7 +3403,7 @@ id	select_type	table	type	possible_keys	
 1	PRIMARY	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
 2	DEPENDENT SUBQUERY	t1	index	a	a	5	NULL	10	Using where; Using index
 2	DEPENDENT SUBQUERY	t2	ref	a	a	5	test.t1.a	1	Using index
-2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t2.a	1	Using where; Using index
+2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t1.a	1	Using index
 drop table t0, t1,t2,t3;
 
 Test that neither MaterializeLookup strategy for semijoin,
@@ -7638,6 +7638,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	outr	ALL	NULL	NULL	NULL	NULL	20	Using where
+2	DEPENDENT SUBQUERY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where
+3	DEPENDENT SUBQUERY	child1	system	int_key,vc_key	NULL	NULL	NULL	1	
+3	DEPENDENT SUBQUERY	child2	ref	int_key	int_key	5	const	3	Using where; Using index
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== modified file 'mysql-test/r/subquery_sj_none_bkaunique.result'
--- a/mysql-test/r/subquery_sj_none_bkaunique.result	2012-01-16 12:51:06 +0000
+++ b/mysql-test/r/subquery_sj_none_bkaunique.result	2012-01-27 12:28:14 +0000
@@ -3404,7 +3404,7 @@ id	select_type	table	type	possible_keys	
 1	PRIMARY	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
 2	DEPENDENT SUBQUERY	t1	index	a	a	5	NULL	10	Using where; Using index
 2	DEPENDENT SUBQUERY	t2	ref	a	a	5	test.t1.a	1	Using index
-2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t2.a	1	Using where; Using index
+2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t1.a	1	Using index
 drop table t0, t1,t2,t3;
 
 Test that neither MaterializeLookup strategy for semijoin,
@@ -7639,6 +7639,59 @@ FROM t2 LEFT JOIN t3 USING (col_varchar_
 id
 200
 DROP TABLE t1,t2,t3;
+#
+# Bug #13596176: Missing row on select with nested in clause when
+#                matr=on and bnl=off + MyISAM
+#
+CREATE TABLE t1 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+vc_nokey varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,'x','x'), (7,'d','d'), (1,'r','r'), (7,'f','f'),
+(9,'y','y'), (NULL,'u','u'), (1,'m','m'), (9,NULL,NULL),
+(2,'o','o'), (9,'w','w'), (2,'m','m'), (4,'q','q'),
+(0,NULL,NULL), (4,'d','d'), (8,'g','g'), (NULL,'x','x'),
+(NULL,'f','f'), (0,'p','p'), (NULL,'j','j'), (8,'c','c');
+CREATE TABLE t2 (
+int_key int DEFAULT NULL,
+vc_key varchar(1) DEFAULT NULL,
+KEY int_key (int_key),
+KEY vc_key (vc_key, int_key)
+) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (8,'g');
+explain SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	outr	ALL	NULL	NULL	NULL	NULL	20	Using where
+2	DEPENDENT SUBQUERY	middle	ALL	NULL	NULL	NULL	NULL	20	Using where
+3	DEPENDENT SUBQUERY	child1	system	int_key,vc_key	NULL	NULL	NULL	1	
+3	DEPENDENT SUBQUERY	child2	ref	int_key	int_key	5	const	3	Using where; Using index
+SELECT vc_key
+FROM t1 as outr
+WHERE (vc_nokey, vc_key ) IN
+(SELECT vc_nokey, vc_nokey
+FROM t1 middle
+WHERE vc_nokey IN
+(SELECT child1.vc_key
+FROM t2 AS child1 JOIN t1 AS child2 USING (int_key)
+)
+);
+vc_key
+g
+DROP TABLE t1, t2;
+# End of test for bug#13596176.
 # End of 5.6 tests
 set optimizer_switch=default;
 set optimizer_switch=default;

=== 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-17 09:27:34 +0000
+++ b/mysql-test/suite/opt_trace/r/bugs_no_prot_all.result	2012-01-27 14:22:35 +0000
@@ -2178,6 +2178,7 @@ SELECT 1 FROM t1 WHERE 1 LIKE
                                 "range_scan_alternatives": [
                                   {
                                     "index": "a",
+                                    "index_dives_for_eq_ranges": true,
                                     "ranges": [
                                       "1 <= a <= 1"
                                     ] /* ranges */,
@@ -2190,6 +2191,7 @@ SELECT 1 FROM t1 WHERE 1 LIKE
                                   },
                                   {
                                     "index": "a_2",
+                                    "index_dives_for_eq_ranges": true,
                                     "ranges": [
                                       "1 <= a <= 1"
                                     ] /* ranges */,

=== 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	2011-11-29 08:41:50 +0000
+++ b/mysql-test/suite/opt_trace/r/bugs_no_prot_none.result	2012-01-26 13:09:59 +0000
@@ -1679,6 +1679,7 @@ SELECT 1 FROM t1 WHERE 1 LIKE
                                 "range_scan_alternatives": [
                                   {
                                     "index": "a",
+                                    "index_dives_for_eq_ranges": true,
                                     "ranges": [
                                       "1 <= a <= 1"
                                     ] /* ranges */,
@@ -1691,6 +1692,7 @@ SELECT 1 FROM t1 WHERE 1 LIKE
                                   },
                                   {
                                     "index": "a_2",
+                                    "index_dives_for_eq_ranges": true,
                                     "ranges": [
                                       "1 <= a <= 1"
                                     ] /* ranges */,

=== 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-17 09:27:34 +0000
+++ b/mysql-test/suite/opt_trace/r/bugs_ps_prot_all.result	2012-01-30 09:05:57 +0000
@@ -2178,6 +2178,7 @@ SELECT 1 FROM t1 WHERE 1 LIKE
                                 "range_scan_alternatives": [
                                   {
                                     "index": "a",
+                                    "index_dives_for_eq_ranges": true,
                                     "ranges": [
                                       "1 <= a <= 1"
                                     ] /* ranges */,
@@ -2190,6 +2191,7 @@ SELECT 1 FROM t1 WHERE 1 LIKE
                                   },
                                   {
                                     "index": "a_2",
+                                    "index_dives_for_eq_ranges": true,
                                     "ranges": [
                                       "1 <= a <= 1"
                                     ] /* ranges */,

=== 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	2011-11-29 08:41:50 +0000
+++ b/mysql-test/suite/opt_trace/r/bugs_ps_prot_none.result	2012-01-30 08:57:24 +0000
@@ -1659,6 +1659,7 @@ SELECT 1 FROM t1 WHERE 1 LIKE
                                 "range_scan_alternatives": [
                                   {
                                     "index": "a",
+                                    "index_dives_for_eq_ranges": true,
                                     "ranges": [
                                       "1 <= a <= 1"
                                     ] /* ranges */,
@@ -1671,6 +1672,7 @@ SELECT 1 FROM t1 WHERE 1 LIKE
                                   },
                                   {
                                     "index": "a_2",
+                                    "index_dives_for_eq_ranges": true,
                                     "ranges": [
                                       "1 <= a <= 1"
                                     ] /* ranges */,

=== modified file 'mysql-test/suite/opt_trace/r/charset.result'
--- a/mysql-test/suite/opt_trace/r/charset.result	2011-11-18 14:51:40 +0000
+++ b/mysql-test/suite/opt_trace/r/charset.result	2012-01-26 13:09:59 +0000
@@ -425,6 +425,7 @@ select * from t1 where c < 'ÁÂÃÄÅ'	
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "c <= ÁÂÃÄ"
                         ] /* ranges */,
@@ -628,6 +629,7 @@ select `col
                     "range_scan_alternatives": [
                       {
                         "index": "index\n1\ta",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL < col\n1\ta < 6"
                         ] /* ranges */,

=== added file 'mysql-test/suite/opt_trace/r/eq_range_statistics.result'
--- a/mysql-test/suite/opt_trace/r/eq_range_statistics.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/opt_trace/r/eq_range_statistics.result	2012-01-26 13:09:59 +0000
@@ -0,0 +1,1244 @@
+SET optimizer_trace_max_mem_size=1048576;
+SET optimizer_trace="enabled=on,end_marker=on,one_line=off";
+SET eq_range_index_dive_limit=default;
+SELECT @@eq_range_index_dive_limit;
+@@eq_range_index_dive_limit
+10
+CREATE TABLE t1 (
+a INT, 
+b INT, 
+KEY (a,b)
+);
+INSERT INTO t1 VALUES (1,1), (2,2), (3,3);
+INSERT INTO t1 VALUES (4,1), (4,2), (4,3);
+INSERT INTO t1 VALUES (5,1), (5,2), (5,3);
+SHOW INDEX FROM t1;
+Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment	Index_comment
+t1	1	a	1	a	A	NULL	NULL	NULL	YES	BTREE		
+t1	1	a	2	b	A	NULL	NULL	NULL	YES	BTREE		
+ANALYZE TABLE t1;
+Table	Op	Msg_type	Msg_text
+test.t1	analyze	status	OK
+SHOW INDEX FROM t1;
+Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment	Index_comment
+t1	1	a	1	a	A	4	NULL	NULL	YES	BTREE		
+t1	1	a	2	b	A	9	NULL	NULL	YES	BTREE		
+#####
+# Apply knowledge about the statistics (each index value for 
+# the first key part has an estimate of 2 rows) to ensure that 
+# index statistics kicks in correctly.
+#####
+# Index dives are done, giving correct estimate of 3 records
+EXPLAIN SELECT * FROM t1 WHERE a IN (1,2,3);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	5	NULL	3	Using where; Using index
+SET eq_range_index_dive_limit=3;
+SELECT @@eq_range_index_dive_limit;
+@@eq_range_index_dive_limit
+3
+# Index statistics kicks in, giving incorrect estimate of 3x2=6 records
+EXPLAIN SELECT * FROM t1 WHERE a IN (1,2,3);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	5	NULL	6	Using where; Using index
+#####
+# Below: A number of tests to verify that the number of equality ranges
+# are counted correctly
+#####
+
+# 2 equality ranges: should not use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 OR a>10 OR a IN (1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	5	NULL	5	Using where; Using index
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT * FROM t1 WHERE a=5 OR a>10 OR a IN (1)	{
+  "steps": [
+    {
+      "join_preparation": {
+        "select#": 1,
+        "steps": [
+          {
+            "expanded_query": "/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` = 1))"
+          }
+        ] /* steps */
+      } /* join_preparation */
+    },
+    {
+      "join_optimization": {
+        "select#": 1,
+        "steps": [
+          {
+            "condition_processing": {
+              "condition": "WHERE",
+              "original_condition": "((`test`.`t1`.`a` = 5) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` = 1))",
+              "steps": [
+                {
+                  "transformation": "equality_propagation",
+                  "resulting_condition": "(multiple equal(5, `test`.`t1`.`a`) or (`test`.`t1`.`a` > 10) or multiple equal(1, `test`.`t1`.`a`))"
+                },
+                {
+                  "transformation": "constant_propagation",
+                  "resulting_condition": "(multiple equal(5, `test`.`t1`.`a`) or (`test`.`t1`.`a` > 10) or multiple equal(1, `test`.`t1`.`a`))"
+                },
+                {
+                  "transformation": "trivial_condition_removal",
+                  "resulting_condition": "(multiple equal(5, `test`.`t1`.`a`) or (`test`.`t1`.`a` > 10) or multiple equal(1, `test`.`t1`.`a`))"
+                }
+              ] /* steps */
+            } /* condition_processing */
+          },
+          {
+            "table_dependencies": [
+              {
+                "database": "test",
+                "table": "t1",
+                "row_may_be_null": false,
+                "map_bit": 0,
+                "depends_on_map_bits": [
+                ] /* depends_on_map_bits */
+              }
+            ] /* table_dependencies */
+          },
+          {
+            "ref_optimizer_key_uses": [
+            ] /* ref_optimizer_key_uses */
+          },
+          {
+            "rows_estimation": [
+              {
+                "database": "test",
+                "table": "t1",
+                "range_analysis": {
+                  "table_scan": {
+                    "rows": 9,
+                    "cost": 5.9198
+                  } /* table_scan */,
+                  "potential_range_indices": [
+                    {
+                      "index": "a",
+                      "usable": true,
+                      "key_parts": [
+                        "a",
+                        "b"
+                      ] /* key_parts */
+                    }
+                  ] /* potential_range_indices */,
+                  "best_covering_index_scan": {
+                    "index": "a",
+                    "cost": 3.0581,
+                    "chosen": true
+                  } /* best_covering_index_scan */,
+                  "setup_range_conditions": [
+                  ] /* setup_range_conditions */,
+                  "group_index_range": {
+                    "chosen": false,
+                    "cause": "not_group_by_or_distinct"
+                  } /* group_index_range */,
+                  "analyzing_range_alternatives": {
+                    "range_scan_alternatives": [
+                      {
+                        "index": "a",
+                        "index_dives_for_eq_ranges": true,
+                        "ranges": [
+                          "1 <= a <= 1",
+                          "5 <= a <= 5",
+                          "10 < a"
+                        ] /* ranges */,
+                        "index_only": true,
+                        "rows": 5,
+                        "cost": 2.139,
+                        "rowid_ordered": false,
+                        "chosen": true
+                      }
+                    ] /* range_scan_alternatives */,
+                    "analyzing_roworder_intersect": {
+                      "usable": false,
+                      "cause": "too_few_roworder_scans"
+                    } /* analyzing_roworder_intersect */
+                  } /* analyzing_range_alternatives */,
+                  "chosen_range_access_summary": {
+                    "range_access_plan": {
+                      "type": "range_scan",
+                      "index": "a",
+                      "rows": 5,
+                      "ranges": [
+                        "1 <= a <= 1",
+                        "5 <= a <= 5",
+                        "10 < a"
+                      ] /* ranges */
+                    } /* range_access_plan */,
+                    "rows_for_plan": 5,
+                    "cost_for_plan": 2.139,
+                    "chosen": true
+                  } /* chosen_range_access_summary */
+                } /* range_analysis */
+              }
+            ] /* rows_estimation */
+          },
+          {
+            "considered_execution_plans": [
+              {
+                "database": "test",
+                "table": "t1",
+                "best_access_path": {
+                  "considered_access_paths": [
+                    {
+                      "access_type": "range",
+                      "rows": 5,
+                      "cost": 2.139,
+                      "chosen": true
+                    }
+                  ] /* considered_access_paths */
+                } /* best_access_path */,
+                "cost_for_plan": 3.139,
+                "rows_for_plan": 5,
+                "chosen": true
+              }
+            ] /* considered_execution_plans */
+          },
+          {
+            "attaching_conditions_to_tables": {
+              "original_condition": "((`test`.`t1`.`a` = 5) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` = 1))",
+              "attached_conditions_computation": [
+              ] /* attached_conditions_computation */,
+              "attached_conditions_summary": [
+                {
+                  "database": "test",
+                  "table": "t1",
+                  "attached": "((`test`.`t1`.`a` = 5) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` = 1))"
+                }
+              ] /* attached_conditions_summary */
+            } /* attaching_conditions_to_tables */
+          },
+          {
+            "refine_plan": [
+              {
+                "database": "test",
+                "table": "t1",
+                "access_type": "range"
+              }
+            ] /* refine_plan */
+          }
+        ] /* steps */
+      } /* join_optimization */
+    },
+    {
+      "join_explain": {
+        "select#": 1,
+        "steps": [
+        ] /* steps */
+      } /* join_explain */
+    }
+  ] /* steps */
+}	0	0
+
+# 3 equality ranges: should use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 OR a>10 OR a IN (1,2);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	5	NULL	7	Using where; Using index
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT * FROM t1 WHERE a=5 OR a>10 OR a IN (1,2)	{
+  "steps": [
+    {
+      "join_preparation": {
+        "select#": 1,
+        "steps": [
+          {
+            "expanded_query": "/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` in (1,2)))"
+          }
+        ] /* steps */
+      } /* join_preparation */
+    },
+    {
+      "join_optimization": {
+        "select#": 1,
+        "steps": [
+          {
+            "condition_processing": {
+              "condition": "WHERE",
+              "original_condition": "((`test`.`t1`.`a` = 5) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` in (1,2)))",
+              "steps": [
+                {
+                  "transformation": "equality_propagation",
+                  "resulting_condition": "(multiple equal(5, `test`.`t1`.`a`) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` in (1,2)))"
+                },
+                {
+                  "transformation": "constant_propagation",
+                  "resulting_condition": "(multiple equal(5, `test`.`t1`.`a`) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` in (1,2)))"
+                },
+                {
+                  "transformation": "trivial_condition_removal",
+                  "resulting_condition": "(multiple equal(5, `test`.`t1`.`a`) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` in (1,2)))"
+                }
+              ] /* steps */
+            } /* condition_processing */
+          },
+          {
+            "table_dependencies": [
+              {
+                "database": "test",
+                "table": "t1",
+                "row_may_be_null": false,
+                "map_bit": 0,
+                "depends_on_map_bits": [
+                ] /* depends_on_map_bits */
+              }
+            ] /* table_dependencies */
+          },
+          {
+            "ref_optimizer_key_uses": [
+            ] /* ref_optimizer_key_uses */
+          },
+          {
+            "rows_estimation": [
+              {
+                "database": "test",
+                "table": "t1",
+                "range_analysis": {
+                  "table_scan": {
+                    "rows": 9,
+                    "cost": 5.9198
+                  } /* table_scan */,
+                  "potential_range_indices": [
+                    {
+                      "index": "a",
+                      "usable": true,
+                      "key_parts": [
+                        "a",
+                        "b"
+                      ] /* key_parts */
+                    }
+                  ] /* potential_range_indices */,
+                  "best_covering_index_scan": {
+                    "index": "a",
+                    "cost": 3.0581,
+                    "chosen": true
+                  } /* best_covering_index_scan */,
+                  "setup_range_conditions": [
+                  ] /* setup_range_conditions */,
+                  "group_index_range": {
+                    "chosen": false,
+                    "cause": "not_group_by_or_distinct"
+                  } /* group_index_range */,
+                  "analyzing_range_alternatives": {
+                    "range_scan_alternatives": [
+                      {
+                        "index": "a",
+                        "index_dives_for_eq_ranges": false,
+                        "ranges": [
+                          "1 <= a <= 1",
+                          "2 <= a <= 2",
+                          "5 <= a <= 5",
+                          "10 < a"
+                        ] /* ranges */,
+                        "index_only": true,
+                        "rows": 7,
+                        "cost": 2.6035,
+                        "rowid_ordered": false,
+                        "chosen": true
+                      }
+                    ] /* range_scan_alternatives */,
+                    "analyzing_roworder_intersect": {
+                      "usable": false,
+                      "cause": "too_few_roworder_scans"
+                    } /* analyzing_roworder_intersect */
+                  } /* analyzing_range_alternatives */,
+                  "chosen_range_access_summary": {
+                    "range_access_plan": {
+                      "type": "range_scan",
+                      "index": "a",
+                      "rows": 7,
+                      "ranges": [
+                        "1 <= a <= 1",
+                        "2 <= a <= 2",
+                        "5 <= a <= 5",
+                        "10 < a"
+                      ] /* ranges */
+                    } /* range_access_plan */,
+                    "rows_for_plan": 7,
+                    "cost_for_plan": 2.6035,
+                    "chosen": true
+                  } /* chosen_range_access_summary */
+                } /* range_analysis */
+              }
+            ] /* rows_estimation */
+          },
+          {
+            "considered_execution_plans": [
+              {
+                "database": "test",
+                "table": "t1",
+                "best_access_path": {
+                  "considered_access_paths": [
+                    {
+                      "access_type": "range",
+                      "rows": 7,
+                      "cost": 2.6035,
+                      "chosen": true
+                    }
+                  ] /* considered_access_paths */
+                } /* best_access_path */,
+                "cost_for_plan": 4.0035,
+                "rows_for_plan": 7,
+                "chosen": true
+              }
+            ] /* considered_execution_plans */
+          },
+          {
+            "attaching_conditions_to_tables": {
+              "original_condition": "((`test`.`t1`.`a` = 5) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` in (1,2)))",
+              "attached_conditions_computation": [
+              ] /* attached_conditions_computation */,
+              "attached_conditions_summary": [
+                {
+                  "database": "test",
+                  "table": "t1",
+                  "attached": "((`test`.`t1`.`a` = 5) or (`test`.`t1`.`a` > 10) or (`test`.`t1`.`a` in (1,2)))"
+                }
+              ] /* attached_conditions_summary */
+            } /* attaching_conditions_to_tables */
+          },
+          {
+            "refine_plan": [
+              {
+                "database": "test",
+                "table": "t1",
+                "access_type": "range"
+              }
+            ] /* refine_plan */
+          }
+        ] /* steps */
+      } /* join_optimization */
+    },
+    {
+      "join_explain": {
+        "select#": 1,
+        "steps": [
+        ] /* steps */
+      } /* join_explain */
+    }
+  ] /* steps */
+}	0	0
+
+# 3 equality ranges: should use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b=4);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	10	NULL	3	Using where; Using index
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b=4)	{
+  "steps": [
+    {
+      "join_preparation": {
+        "select#": 1,
+        "steps": [
+          {
+            "expanded_query": "/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` = 4)))"
+          }
+        ] /* steps */
+      } /* join_preparation */
+    },
+    {
+      "join_optimization": {
+        "select#": 1,
+        "steps": [
+          {
+            "condition_processing": {
+              "condition": "WHERE",
+              "original_condition": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` = 4)))",
+              "steps": [
+                {
+                  "transformation": "equality_propagation",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or multiple equal(4, `test`.`t1`.`b`)) and multiple equal(5, `test`.`t1`.`a`))"
+                },
+                {
+                  "transformation": "constant_propagation",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or multiple equal(4, `test`.`t1`.`b`)) and multiple equal(5, `test`.`t1`.`a`))"
+                },
+                {
+                  "transformation": "trivial_condition_removal",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or multiple equal(4, `test`.`t1`.`b`)) and multiple equal(5, `test`.`t1`.`a`))"
+                }
+              ] /* steps */
+            } /* condition_processing */
+          },
+          {
+            "table_dependencies": [
+              {
+                "database": "test",
+                "table": "t1",
+                "row_may_be_null": false,
+                "map_bit": 0,
+                "depends_on_map_bits": [
+                ] /* depends_on_map_bits */
+              }
+            ] /* table_dependencies */
+          },
+          {
+            "ref_optimizer_key_uses": [
+              {
+                "database": "test",
+                "table": "t1",
+                "field": "a",
+                "equals": "5",
+                "null_rejecting": false
+              }
+            ] /* ref_optimizer_key_uses */
+          },
+          {
+            "rows_estimation": [
+              {
+                "database": "test",
+                "table": "t1",
+                "range_analysis": {
+                  "table_scan": {
+                    "rows": 9,
+                    "cost": 5.9198
+                  } /* table_scan */,
+                  "potential_range_indices": [
+                    {
+                      "index": "a",
+                      "usable": true,
+                      "key_parts": [
+                        "a",
+                        "b"
+                      ] /* key_parts */
+                    }
+                  ] /* potential_range_indices */,
+                  "best_covering_index_scan": {
+                    "index": "a",
+                    "cost": 3.0581,
+                    "chosen": true
+                  } /* best_covering_index_scan */,
+                  "setup_range_conditions": [
+                  ] /* setup_range_conditions */,
+                  "group_index_range": {
+                    "chosen": false,
+                    "cause": "not_group_by_or_distinct"
+                  } /* group_index_range */,
+                  "analyzing_range_alternatives": {
+                    "range_scan_alternatives": [
+                      {
+                        "index": "a",
+                        "index_dives_for_eq_ranges": false,
+                        "ranges": [
+                          "5 <= a <= 5 AND 2 <= b <= 2",
+                          "5 <= a <= 5 AND 3 <= b <= 3",
+                          "5 <= a <= 5 AND 4 <= b <= 4"
+                        ] /* ranges */,
+                        "index_only": true,
+                        "rows": 3,
+                        "cost": 1.6745,
+                        "rowid_ordered": false,
+                        "chosen": true
+                      }
+                    ] /* range_scan_alternatives */,
+                    "analyzing_roworder_intersect": {
+                      "usable": false,
+                      "cause": "too_few_roworder_scans"
+                    } /* analyzing_roworder_intersect */
+                  } /* analyzing_range_alternatives */,
+                  "chosen_range_access_summary": {
+                    "range_access_plan": {
+                      "type": "range_scan",
+                      "index": "a",
+                      "rows": 3,
+                      "ranges": [
+                        "5 <= a <= 5 AND 2 <= b <= 2",
+                        "5 <= a <= 5 AND 3 <= b <= 3",
+                        "5 <= a <= 5 AND 4 <= b <= 4"
+                      ] /* ranges */
+                    } /* range_access_plan */,
+                    "rows_for_plan": 3,
+                    "cost_for_plan": 1.6745,
+                    "chosen": true
+                  } /* chosen_range_access_summary */
+                } /* range_analysis */
+              }
+            ] /* rows_estimation */
+          },
+          {
+            "considered_execution_plans": [
+              {
+                "database": "test",
+                "table": "t1",
+                "best_access_path": {
+                  "considered_access_paths": [
+                    {
+                      "access_type": "ref",
+                      "index": "a",
+                      "rows": 3,
+                      "cost": 1.6645,
+                      "chosen": true
+                    },
+                    {
+                      "access_type": "range",
+                      "rows": 3,
+                      "cost": 1.6745,
+                      "chosen": false
+                    }
+                  ] /* considered_access_paths */
+                } /* best_access_path */,
+                "cost_for_plan": 1.6645,
+                "rows_for_plan": 3,
+                "chosen": true
+              }
+            ] /* considered_execution_plans */
+          },
+          {
+            "attaching_conditions_to_tables": {
+              "original_condition": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` = 4)))",
+              "attached_conditions_computation": [
+                {
+                  "access_type_changed": {
+                    "database": "test",
+                    "table": "t1",
+                    "index": "a",
+                    "old_type": "ref",
+                    "new_type": "range",
+                    "cause": "uses_more_keyparts"
+                  } /* access_type_changed */
+                }
+              ] /* attached_conditions_computation */,
+              "attached_conditions_summary": [
+                {
+                  "database": "test",
+                  "table": "t1",
+                  "attached": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` = 4)))"
+                }
+              ] /* attached_conditions_summary */
+            } /* attaching_conditions_to_tables */
+          },
+          {
+            "refine_plan": [
+              {
+                "database": "test",
+                "table": "t1",
+                "access_type": "range"
+              }
+            ] /* refine_plan */
+          }
+        ] /* steps */
+      } /* join_optimization */
+    },
+    {
+      "join_explain": {
+        "select#": 1,
+        "steps": [
+        ] /* steps */
+      } /* join_explain */
+    }
+  ] /* steps */
+}	0	0
+
+# 2 equality ranges: should not use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b>4);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	10	NULL	3	Using where; Using index
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b>4)	{
+  "steps": [
+    {
+      "join_preparation": {
+        "select#": 1,
+        "steps": [
+          {
+            "expanded_query": "/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` > 4)))"
+          }
+        ] /* steps */
+      } /* join_preparation */
+    },
+    {
+      "join_optimization": {
+        "select#": 1,
+        "steps": [
+          {
+            "condition_processing": {
+              "condition": "WHERE",
+              "original_condition": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` > 4)))",
+              "steps": [
+                {
+                  "transformation": "equality_propagation",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or (`test`.`t1`.`b` > 4)) and multiple equal(5, `test`.`t1`.`a`))"
+                },
+                {
+                  "transformation": "constant_propagation",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or (`test`.`t1`.`b` > 4)) and multiple equal(5, `test`.`t1`.`a`))"
+                },
+                {
+                  "transformation": "trivial_condition_removal",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or (`test`.`t1`.`b` > 4)) and multiple equal(5, `test`.`t1`.`a`))"
+                }
+              ] /* steps */
+            } /* condition_processing */
+          },
+          {
+            "table_dependencies": [
+              {
+                "database": "test",
+                "table": "t1",
+                "row_may_be_null": false,
+                "map_bit": 0,
+                "depends_on_map_bits": [
+                ] /* depends_on_map_bits */
+              }
+            ] /* table_dependencies */
+          },
+          {
+            "ref_optimizer_key_uses": [
+              {
+                "database": "test",
+                "table": "t1",
+                "field": "a",
+                "equals": "5",
+                "null_rejecting": false
+              }
+            ] /* ref_optimizer_key_uses */
+          },
+          {
+            "rows_estimation": [
+              {
+                "database": "test",
+                "table": "t1",
+                "range_analysis": {
+                  "table_scan": {
+                    "rows": 9,
+                    "cost": 5.9198
+                  } /* table_scan */,
+                  "potential_range_indices": [
+                    {
+                      "index": "a",
+                      "usable": true,
+                      "key_parts": [
+                        "a",
+                        "b"
+                      ] /* key_parts */
+                    }
+                  ] /* potential_range_indices */,
+                  "best_covering_index_scan": {
+                    "index": "a",
+                    "cost": 3.0581,
+                    "chosen": true
+                  } /* best_covering_index_scan */,
+                  "setup_range_conditions": [
+                  ] /* setup_range_conditions */,
+                  "group_index_range": {
+                    "chosen": false,
+                    "cause": "not_group_by_or_distinct"
+                  } /* group_index_range */,
+                  "analyzing_range_alternatives": {
+                    "range_scan_alternatives": [
+                      {
+                        "index": "a",
+                        "index_dives_for_eq_ranges": true,
+                        "ranges": [
+                          "5 <= a <= 5 AND 2 <= b <= 2",
+                          "5 <= a <= 5 AND 3 <= b <= 3",
+                          "5 <= a <= 5 AND 4 < b"
+                        ] /* ranges */,
+                        "index_only": true,
+                        "rows": 3,
+                        "cost": 1.6745,
+                        "rowid_ordered": false,
+                        "chosen": true
+                      }
+                    ] /* range_scan_alternatives */,
+                    "analyzing_roworder_intersect": {
+                      "usable": false,
+                      "cause": "too_few_roworder_scans"
+                    } /* analyzing_roworder_intersect */
+                  } /* analyzing_range_alternatives */,
+                  "chosen_range_access_summary": {
+                    "range_access_plan": {
+                      "type": "range_scan",
+                      "index": "a",
+                      "rows": 3,
+                      "ranges": [
+                        "5 <= a <= 5 AND 2 <= b <= 2",
+                        "5 <= a <= 5 AND 3 <= b <= 3",
+                        "5 <= a <= 5 AND 4 < b"
+                      ] /* ranges */
+                    } /* range_access_plan */,
+                    "rows_for_plan": 3,
+                    "cost_for_plan": 1.6745,
+                    "chosen": true
+                  } /* chosen_range_access_summary */
+                } /* range_analysis */
+              }
+            ] /* rows_estimation */
+          },
+          {
+            "considered_execution_plans": [
+              {
+                "database": "test",
+                "table": "t1",
+                "best_access_path": {
+                  "considered_access_paths": [
+                    {
+                      "access_type": "ref",
+                      "index": "a",
+                      "rows": 3,
+                      "cost": 1.6645,
+                      "chosen": true
+                    },
+                    {
+                      "access_type": "range",
+                      "rows": 3,
+                      "cost": 1.6745,
+                      "chosen": false
+                    }
+                  ] /* considered_access_paths */
+                } /* best_access_path */,
+                "cost_for_plan": 1.6645,
+                "rows_for_plan": 3,
+                "chosen": true
+              }
+            ] /* considered_execution_plans */
+          },
+          {
+            "attaching_conditions_to_tables": {
+              "original_condition": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` > 4)))",
+              "attached_conditions_computation": [
+                {
+                  "access_type_changed": {
+                    "database": "test",
+                    "table": "t1",
+                    "index": "a",
+                    "old_type": "ref",
+                    "new_type": "range",
+                    "cause": "uses_more_keyparts"
+                  } /* access_type_changed */
+                }
+              ] /* attached_conditions_computation */,
+              "attached_conditions_summary": [
+                {
+                  "database": "test",
+                  "table": "t1",
+                  "attached": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` > 4)))"
+                }
+              ] /* attached_conditions_summary */
+            } /* attaching_conditions_to_tables */
+          },
+          {
+            "refine_plan": [
+              {
+                "database": "test",
+                "table": "t1",
+                "access_type": "range"
+              }
+            ] /* refine_plan */
+          }
+        ] /* steps */
+      } /* join_optimization */
+    },
+    {
+      "join_explain": {
+        "select#": 1,
+        "steps": [
+        ] /* steps */
+      } /* join_explain */
+    }
+  ] /* steps */
+}	0	0
+
+# 2 equality ranges: should not use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b IS NULL);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	10	NULL	3	Using where; Using index
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b IS NULL)	{
+  "steps": [
+    {
+      "join_preparation": {
+        "select#": 1,
+        "steps": [
+          {
+            "expanded_query": "/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or isnull(`test`.`t1`.`b`)))"
+          }
+        ] /* steps */
+      } /* join_preparation */
+    },
+    {
+      "join_optimization": {
+        "select#": 1,
+        "steps": [
+          {
+            "condition_processing": {
+              "condition": "WHERE",
+              "original_condition": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or isnull(`test`.`t1`.`b`)))",
+              "steps": [
+                {
+                  "transformation": "equality_propagation",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or isnull(`test`.`t1`.`b`)) and multiple equal(5, `test`.`t1`.`a`))"
+                },
+                {
+                  "transformation": "constant_propagation",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or isnull(`test`.`t1`.`b`)) and multiple equal(5, `test`.`t1`.`a`))"
+                },
+                {
+                  "transformation": "trivial_condition_removal",
+                  "resulting_condition": "((multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or isnull(`test`.`t1`.`b`)) and multiple equal(5, `test`.`t1`.`a`))"
+                }
+              ] /* steps */
+            } /* condition_processing */
+          },
+          {
+            "table_dependencies": [
+              {
+                "database": "test",
+                "table": "t1",
+                "row_may_be_null": false,
+                "map_bit": 0,
+                "depends_on_map_bits": [
+                ] /* depends_on_map_bits */
+              }
+            ] /* table_dependencies */
+          },
+          {
+            "ref_optimizer_key_uses": [
+              {
+                "database": "test",
+                "table": "t1",
+                "field": "a",
+                "equals": "5",
+                "null_rejecting": false
+              }
+            ] /* ref_optimizer_key_uses */
+          },
+          {
+            "rows_estimation": [
+              {
+                "database": "test",
+                "table": "t1",
+                "range_analysis": {
+                  "table_scan": {
+                    "rows": 9,
+                    "cost": 5.9198
+                  } /* table_scan */,
+                  "potential_range_indices": [
+                    {
+                      "index": "a",
+                      "usable": true,
+                      "key_parts": [
+                        "a",
+                        "b"
+                      ] /* key_parts */
+                    }
+                  ] /* potential_range_indices */,
+                  "best_covering_index_scan": {
+                    "index": "a",
+                    "cost": 3.0581,
+                    "chosen": true
+                  } /* best_covering_index_scan */,
+                  "setup_range_conditions": [
+                  ] /* setup_range_conditions */,
+                  "group_index_range": {
+                    "chosen": false,
+                    "cause": "not_group_by_or_distinct"
+                  } /* group_index_range */,
+                  "analyzing_range_alternatives": {
+                    "range_scan_alternatives": [
+                      {
+                        "index": "a",
+                        "index_dives_for_eq_ranges": true,
+                        "ranges": [
+                          "5 <= a <= 5 AND NULL <= b <= NULL",
+                          "5 <= a <= 5 AND 2 <= b <= 2",
+                          "5 <= a <= 5 AND 3 <= b <= 3"
+                        ] /* ranges */,
+                        "index_only": true,
+                        "rows": 3,
+                        "cost": 1.6745,
+                        "rowid_ordered": false,
+                        "chosen": true
+                      }
+                    ] /* range_scan_alternatives */,
+                    "analyzing_roworder_intersect": {
+                      "usable": false,
+                      "cause": "too_few_roworder_scans"
+                    } /* analyzing_roworder_intersect */
+                  } /* analyzing_range_alternatives */,
+                  "chosen_range_access_summary": {
+                    "range_access_plan": {
+                      "type": "range_scan",
+                      "index": "a",
+                      "rows": 3,
+                      "ranges": [
+                        "5 <= a <= 5 AND NULL <= b <= NULL",
+                        "5 <= a <= 5 AND 2 <= b <= 2",
+                        "5 <= a <= 5 AND 3 <= b <= 3"
+                      ] /* ranges */
+                    } /* range_access_plan */,
+                    "rows_for_plan": 3,
+                    "cost_for_plan": 1.6745,
+                    "chosen": true
+                  } /* chosen_range_access_summary */
+                } /* range_analysis */
+              }
+            ] /* rows_estimation */
+          },
+          {
+            "considered_execution_plans": [
+              {
+                "database": "test",
+                "table": "t1",
+                "best_access_path": {
+                  "considered_access_paths": [
+                    {
+                      "access_type": "ref",
+                      "index": "a",
+                      "rows": 3,
+                      "cost": 1.6645,
+                      "chosen": true
+                    },
+                    {
+                      "access_type": "range",
+                      "rows": 3,
+                      "cost": 1.6745,
+                      "chosen": false
+                    }
+                  ] /* considered_access_paths */
+                } /* best_access_path */,
+                "cost_for_plan": 1.6645,
+                "rows_for_plan": 3,
+                "chosen": true
+              }
+            ] /* considered_execution_plans */
+          },
+          {
+            "attaching_conditions_to_tables": {
+              "original_condition": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or isnull(`test`.`t1`.`b`)))",
+              "attached_conditions_computation": [
+                {
+                  "access_type_changed": {
+                    "database": "test",
+                    "table": "t1",
+                    "index": "a",
+                    "old_type": "ref",
+                    "new_type": "range",
+                    "cause": "uses_more_keyparts"
+                  } /* access_type_changed */
+                }
+              ] /* attached_conditions_computation */,
+              "attached_conditions_summary": [
+                {
+                  "database": "test",
+                  "table": "t1",
+                  "attached": "((`test`.`t1`.`a` = 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or isnull(`test`.`t1`.`b`)))"
+                }
+              ] /* attached_conditions_summary */
+            } /* attaching_conditions_to_tables */
+          },
+          {
+            "refine_plan": [
+              {
+                "database": "test",
+                "table": "t1",
+                "access_type": "range"
+              }
+            ] /* refine_plan */
+          }
+        ] /* steps */
+      } /* join_optimization */
+    },
+    {
+      "join_explain": {
+        "select#": 1,
+        "steps": [
+        ] /* steps */
+      } /* join_explain */
+    }
+  ] /* steps */
+}	0	0
+
+# 0 equality ranges: should not use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a>5 AND (b=2 OR b=3 OR b=4);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	5	NULL	1	Using where; Using index
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT * FROM t1 WHERE a>5 AND (b=2 OR b=3 OR b=4)	{
+  "steps": [
+    {
+      "join_preparation": {
+        "select#": 1,
+        "steps": [
+          {
+            "expanded_query": "/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where ((`test`.`t1`.`a` > 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` = 4)))"
+          }
+        ] /* steps */
+      } /* join_preparation */
+    },
+    {
+      "join_optimization": {
+        "select#": 1,
+        "steps": [
+          {
+            "condition_processing": {
+              "condition": "WHERE",
+              "original_condition": "((`test`.`t1`.`a` > 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` = 4)))",
+              "steps": [
+                {
+                  "transformation": "equality_propagation",
+                  "resulting_condition": "((`test`.`t1`.`a` > 5) and (multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or multiple equal(4, `test`.`t1`.`b`)))"
+                },
+                {
+                  "transformation": "constant_propagation",
+                  "resulting_condition": "((`test`.`t1`.`a` > 5) and (multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or multiple equal(4, `test`.`t1`.`b`)))"
+                },
+                {
+                  "transformation": "trivial_condition_removal",
+                  "resulting_condition": "((`test`.`t1`.`a` > 5) and (multiple equal(2, `test`.`t1`.`b`) or multiple equal(3, `test`.`t1`.`b`) or multiple equal(4, `test`.`t1`.`b`)))"
+                }
+              ] /* steps */
+            } /* condition_processing */
+          },
+          {
+            "table_dependencies": [
+              {
+                "database": "test",
+                "table": "t1",
+                "row_may_be_null": false,
+                "map_bit": 0,
+                "depends_on_map_bits": [
+                ] /* depends_on_map_bits */
+              }
+            ] /* table_dependencies */
+          },
+          {
+            "ref_optimizer_key_uses": [
+            ] /* ref_optimizer_key_uses */
+          },
+          {
+            "rows_estimation": [
+              {
+                "database": "test",
+                "table": "t1",
+                "range_analysis": {
+                  "table_scan": {
+                    "rows": 9,
+                    "cost": 5.9198
+                  } /* table_scan */,
+                  "potential_range_indices": [
+                    {
+                      "index": "a",
+                      "usable": true,
+                      "key_parts": [
+                        "a",
+                        "b"
+                      ] /* key_parts */
+                    }
+                  ] /* potential_range_indices */,
+                  "best_covering_index_scan": {
+                    "index": "a",
+                    "cost": 3.0581,
+                    "chosen": true
+                  } /* best_covering_index_scan */,
+                  "setup_range_conditions": [
+                  ] /* setup_range_conditions */,
+                  "group_index_range": {
+                    "chosen": false,
+                    "cause": "not_group_by_or_distinct"
+                  } /* group_index_range */,
+                  "analyzing_range_alternatives": {
+                    "range_scan_alternatives": [
+                      {
+                        "index": "a",
+                        "index_dives_for_eq_ranges": true,
+                        "ranges": [
+                          "5 < a AND 2 <= b <= 2",
+                          "5 < a AND 3 <= b <= 3",
+                          "5 < a AND 4 <= b <= 4"
+                        ] /* ranges */,
+                        "index_only": true,
+                        "rows": 1,
+                        "cost": 2.21,
+                        "rowid_ordered": false,
+                        "chosen": true
+                      }
+                    ] /* range_scan_alternatives */,
+                    "analyzing_roworder_intersect": {
+                      "usable": false,
+                      "cause": "too_few_roworder_scans"
+                    } /* analyzing_roworder_intersect */
+                  } /* analyzing_range_alternatives */,
+                  "chosen_range_access_summary": {
+                    "range_access_plan": {
+                      "type": "range_scan",
+                      "index": "a",
+                      "rows": 1,
+                      "ranges": [
+                        "5 < a AND 2 <= b <= 2",
+                        "5 < a AND 3 <= b <= 3",
+                        "5 < a AND 4 <= b <= 4"
+                      ] /* ranges */
+                    } /* range_access_plan */,
+                    "rows_for_plan": 1,
+                    "cost_for_plan": 2.21,
+                    "chosen": true
+                  } /* chosen_range_access_summary */
+                } /* range_analysis */
+              }
+            ] /* rows_estimation */
+          },
+          {
+            "considered_execution_plans": [
+              {
+                "database": "test",
+                "table": "t1",
+                "best_access_path": {
+                  "considered_access_paths": [
+                    {
+                      "access_type": "range",
+                      "rows": 1,
+                      "cost": 2.21,
+                      "chosen": true
+                    }
+                  ] /* considered_access_paths */
+                } /* best_access_path */,
+                "cost_for_plan": 2.41,
+                "rows_for_plan": 1,
+                "chosen": true
+              }
+            ] /* considered_execution_plans */
+          },
+          {
+            "attaching_conditions_to_tables": {
+              "original_condition": "((`test`.`t1`.`a` > 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` = 4)))",
+              "attached_conditions_computation": [
+              ] /* attached_conditions_computation */,
+              "attached_conditions_summary": [
+                {
+                  "database": "test",
+                  "table": "t1",
+                  "attached": "((`test`.`t1`.`a` > 5) and ((`test`.`t1`.`b` = 2) or (`test`.`t1`.`b` = 3) or (`test`.`t1`.`b` = 4)))"
+                }
+              ] /* attached_conditions_summary */
+            } /* attaching_conditions_to_tables */
+          },
+          {
+            "refine_plan": [
+              {
+                "database": "test",
+                "table": "t1",
+                "access_type": "range"
+              }
+            ] /* refine_plan */
+          }
+        ] /* steps */
+      } /* join_optimization */
+    },
+    {
+      "join_explain": {
+        "select#": 1,
+        "steps": [
+        ] /* steps */
+      } /* join_explain */
+    }
+  ] /* steps */
+}	0	0
+DROP TABLE t1;
+SET eq_range_index_dive_limit=default;

=== 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-10 18:58:10 +0000
+++ b/mysql-test/suite/opt_trace/r/general2_no_prot.result	2012-01-26 13:09:59 +0000
@@ -331,6 +331,7 @@ TRACE
                     "range_scan_alternatives": [
                       {
                         "index": "a",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "12 < a"
                         ] /* ranges */,
@@ -2622,7 +2623,7 @@ id	select_type	table	type	possible_keys	
 1	PRIMARY	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
 2	DEPENDENT SUBQUERY	t1	index	a	a	5	NULL	10	Using where; Using index
 2	DEPENDENT SUBQUERY	t2	ref	a	a	5	test.t1.a	1	Using index
-2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t2.a	1	Using where; Using index
+2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t1.a	1	Using index
 select * from information_schema.optimizer_trace;
 QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
 explain select * 
@@ -3271,7 +3272,7 @@ from t0 where a in
                       {
                         "database": "test",
                         "table": "t3",
-                        "attached": "(`test`.`t3`.`a` = `test`.`t1`.`a`)"
+                        "attached": null
                       }
                     ] /* attached_conditions_summary */
                   } /* attaching_conditions_to_tables */
@@ -4057,6 +4058,7 @@ select replace(t3._field_140, "\r","^M")
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= seq_0_id <= 1"
                         ] /* ranges */,
@@ -4144,6 +4146,7 @@ select replace(t3._field_140, "\r","^M")
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= seq_0_id <= 1"
                         ] /* ranges */,
@@ -4241,6 +4244,7 @@ select replace(t3._field_140, "\r","^M")
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= seq_0_id <= 1"
                         ] /* ranges */,

=== 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-10 18:58:10 +0000
+++ b/mysql-test/suite/opt_trace/r/general2_ps_prot.result	2012-01-30 08:57:24 +0000
@@ -359,6 +359,7 @@ TRACE
                     "range_scan_alternatives": [
                       {
                         "index": "a",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "12 < a"
                         ] /* ranges */,
@@ -2675,7 +2676,7 @@ id	select_type	table	type	possible_keys	
 1	PRIMARY	t0	ALL	NULL	NULL	NULL	NULL	10	Using where
 2	DEPENDENT SUBQUERY	t1	index	a	a	5	NULL	10	Using where; Using index
 2	DEPENDENT SUBQUERY	t2	ref	a	a	5	test.t1.a	1	Using index
-2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t2.a	1	Using where; Using index
+2	DEPENDENT SUBQUERY	t3	ref	a	a	5	test.t1.a	1	Using index
 select * from information_schema.optimizer_trace;
 QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
 explain select * 
@@ -3324,7 +3325,7 @@ from t0 where a in
                       {
                         "database": "test",
                         "table": "t3",
-                        "attached": "(`test`.`t3`.`a` = `test`.`t1`.`a`)"
+                        "attached": null
                       }
                     ] /* attached_conditions_summary */
                   } /* attaching_conditions_to_tables */
@@ -4110,6 +4111,7 @@ select replace(t3._field_140, "\r","^M")
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= seq_0_id <= 1"
                         ] /* ranges */,
@@ -4197,6 +4199,7 @@ select replace(t3._field_140, "\r","^M")
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= seq_0_id <= 1"
                         ] /* ranges */,
@@ -4294,6 +4297,7 @@ select replace(t3._field_140, "\r","^M")
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= seq_0_id <= 1"
                         ] /* ranges */,

=== 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	2011-11-22 13:47:46 +0000
+++ b/mysql-test/suite/opt_trace/r/general_no_prot_all.result	2012-01-26 13:09:59 +0000
@@ -1536,6 +1536,7 @@ explain SELECT c FROM t5 where c+1 in (s
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL <= d <= NULL"
                         ] /* ranges */,
@@ -1911,6 +1912,7 @@ explain SELECT c FROM t5 where c+1 in (s
                           "range_scan_alternatives": [
                             {
                               "index": "d",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "NULL <= d <= NULL"
                               ] /* ranges */,
@@ -6740,6 +6742,7 @@ update t6 set d=5 where d is NULL	{
           "range_scan_alternatives": [
             {
               "index": "d",
+              "index_dives_for_eq_ranges": true,
               "ranges": [
                 "NULL <= d <= NULL"
               ] /* ranges */,
@@ -6804,6 +6807,7 @@ delete from t6 where d=5	{
           "range_scan_alternatives": [
             {
               "index": "d",
+              "index_dives_for_eq_ranges": true,
               "ranges": [
                 "5 <= d <= 5"
               ] /* ranges */,
@@ -6928,6 +6932,7 @@ insert into t6 select * from t6 where d>
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7 < d"
                         ] /* ranges */,
@@ -7115,6 +7120,7 @@ update t5, t6 set t6.d=t6.d+t5.c+4-t5.c-
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7000 < d"
                         ] /* ranges */,
@@ -7319,6 +7325,7 @@ delete t6 from t5, t6 where d>7000	{
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7000 < d"
                         ] /* ranges */,
@@ -7743,6 +7750,7 @@ select * from t6 where d in (select f1()
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "3 <= d <= 3"
                         ] /* ranges */,
@@ -8436,6 +8444,7 @@ select d into res from t6 where d in (se
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "3 <= d <= 3"
                         ] /* ranges */,
@@ -9152,6 +9161,7 @@ insert into t2 select d,100,200 from t6 
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL < d"
                         ] /* ranges */,
@@ -10045,6 +10055,7 @@ select d into res from t6 where d in (se
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "3 <= d <= 3"
                         ] /* ranges */,

=== 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	2011-11-30 11:36:14 +0000
+++ b/mysql-test/suite/opt_trace/r/general_no_prot_none.result	2012-01-26 13:09:59 +0000
@@ -1583,6 +1583,7 @@ explain SELECT c FROM t5 where c+1 in (s
                           "range_scan_alternatives": [
                             {
                               "index": "d",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "NULL <= d <= NULL"
                               ] /* ranges */,
@@ -1872,6 +1873,7 @@ explain SELECT c FROM t5 where c+1 in (s
                           "range_scan_alternatives": [
                             {
                               "index": "d",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "NULL <= d <= NULL"
                               ] /* ranges */,
@@ -5996,6 +5998,7 @@ update t6 set d=5 where d is NULL	{
           "range_scan_alternatives": [
             {
               "index": "d",
+              "index_dives_for_eq_ranges": true,
               "ranges": [
                 "NULL <= d <= NULL"
               ] /* ranges */,
@@ -6060,6 +6063,7 @@ delete from t6 where d=5	{
           "range_scan_alternatives": [
             {
               "index": "d",
+              "index_dives_for_eq_ranges": true,
               "ranges": [
                 "5 <= d <= 5"
               ] /* ranges */,
@@ -6184,6 +6188,7 @@ insert into t6 select * from t6 where d>
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7 < d"
                         ] /* ranges */,
@@ -6371,6 +6376,7 @@ update t5, t6 set t6.d=t6.d+t5.c+4-t5.c-
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7000 < d"
                         ] /* ranges */,
@@ -6575,6 +6581,7 @@ delete t6 from t5, t6 where d>7000	{
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7000 < d"
                         ] /* ranges */,
@@ -8399,6 +8406,7 @@ insert into t2 select d,100,200 from t6 
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL < d"
                         ] /* ranges */,

=== 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	2011-11-22 13:47:46 +0000
+++ b/mysql-test/suite/opt_trace/r/general_ps_prot_all.result	2012-01-30 08:57:24 +0000
@@ -1516,6 +1516,7 @@ explain SELECT c FROM t5 where c+1 in (s
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL <= d <= NULL"
                         ] /* ranges */,
@@ -1891,6 +1892,7 @@ explain SELECT c FROM t5 where c+1 in (s
                           "range_scan_alternatives": [
                             {
                               "index": "d",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "NULL <= d <= NULL"
                               ] /* ranges */,
@@ -6708,6 +6710,7 @@ update t6 set d=5 where d is NULL	{
           "range_scan_alternatives": [
             {
               "index": "d",
+              "index_dives_for_eq_ranges": true,
               "ranges": [
                 "NULL <= d <= NULL"
               ] /* ranges */,
@@ -6772,6 +6775,7 @@ delete from t6 where d=5	{
           "range_scan_alternatives": [
             {
               "index": "d",
+              "index_dives_for_eq_ranges": true,
               "ranges": [
                 "5 <= d <= 5"
               ] /* ranges */,
@@ -6896,6 +6900,7 @@ insert into t6 select * from t6 where d>
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7 < d"
                         ] /* ranges */,
@@ -7083,6 +7088,7 @@ update t5, t6 set t6.d=t6.d+t5.c+4-t5.c-
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7000 < d"
                         ] /* ranges */,
@@ -7287,6 +7293,7 @@ delete t6 from t5, t6 where d>7000	{
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7000 < d"
                         ] /* ranges */,
@@ -7715,6 +7722,7 @@ select * from t6 where d in (select f1()
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "3 <= d <= 3"
                         ] /* ranges */,
@@ -8398,6 +8406,7 @@ select d into res from t6 where d in (se
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "3 <= d <= 3"
                         ] /* ranges */,
@@ -9128,6 +9137,7 @@ insert into t2 select d,100,200 from t6 
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL < d"
                         ] /* ranges */,
@@ -10021,6 +10031,7 @@ select d into res from t6 where d in (se
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "3 <= d <= 3"
                         ] /* ranges */,

=== 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	2011-11-30 11:36:14 +0000
+++ b/mysql-test/suite/opt_trace/r/general_ps_prot_none.result	2012-01-30 08:57:24 +0000
@@ -1563,6 +1563,7 @@ explain SELECT c FROM t5 where c+1 in (s
                           "range_scan_alternatives": [
                             {
                               "index": "d",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "NULL <= d <= NULL"
                               ] /* ranges */,
@@ -1852,6 +1853,7 @@ explain SELECT c FROM t5 where c+1 in (s
                           "range_scan_alternatives": [
                             {
                               "index": "d",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "NULL <= d <= NULL"
                               ] /* ranges */,
@@ -5954,6 +5956,7 @@ update t6 set d=5 where d is NULL	{
           "range_scan_alternatives": [
             {
               "index": "d",
+              "index_dives_for_eq_ranges": true,
               "ranges": [
                 "NULL <= d <= NULL"
               ] /* ranges */,
@@ -6018,6 +6021,7 @@ delete from t6 where d=5	{
           "range_scan_alternatives": [
             {
               "index": "d",
+              "index_dives_for_eq_ranges": true,
               "ranges": [
                 "5 <= d <= 5"
               ] /* ranges */,
@@ -6142,6 +6146,7 @@ insert into t6 select * from t6 where d>
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7 < d"
                         ] /* ranges */,
@@ -6329,6 +6334,7 @@ update t5, t6 set t6.d=t6.d+t5.c+4-t5.c-
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7000 < d"
                         ] /* ranges */,
@@ -6533,6 +6539,7 @@ delete t6 from t5, t6 where d>7000	{
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7000 < d"
                         ] /* ranges */,
@@ -8333,6 +8340,7 @@ insert into t2 select d,100,200 from t6 
                     "range_scan_alternatives": [
                       {
                         "index": "d",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL < d"
                         ] /* ranges */,

=== modified file 'mysql-test/suite/opt_trace/r/range_no_prot.result'
--- a/mysql-test/suite/opt_trace/r/range_no_prot.result	2011-12-01 14:12:10 +0000
+++ b/mysql-test/suite/opt_trace/r/range_no_prot.result	2012-01-26 13:09:59 +0000
@@ -157,6 +157,7 @@ EXPLAIN SELECT * FROM t1 WHERE key2 < 5 
                     "range_scan_alternatives": [
                       {
                         "index": "i2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "key2 < 5",
                           "1020 < key2"
@@ -529,6 +530,7 @@ EXPLAIN SELECT * FROM t1 WHERE key1 < 3 
                           "range_scan_alternatives": [
                             {
                               "index": "i1",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "key1 < 3"
                               ] /* ranges */,
@@ -546,6 +548,7 @@ EXPLAIN SELECT * FROM t1 WHERE key1 < 3 
                           "range_scan_alternatives": [
                             {
                               "index": "i2",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "1020 < key2"
                               ] /* ranges */,
@@ -1233,6 +1236,7 @@ GROUP BY key2	{
                       {
                         "index": "i2_1",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1",
                           "2 <= key2 <= 2",
@@ -1246,6 +1250,7 @@ GROUP BY key2	{
                       {
                         "index": "i2_2",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1",
                           "2 <= key2 <= 2",
@@ -1283,6 +1288,7 @@ GROUP BY key2	{
                     "range_scan_alternatives": [
                       {
                         "index": "i2_1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1",
                           "2 <= key2 <= 2",
@@ -1298,6 +1304,7 @@ GROUP BY key2	{
                       },
                       {
                         "index": "i2_2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1",
                           "2 <= key2 <= 2",
@@ -1540,6 +1547,7 @@ EXPLAIN SELECT * FROM t2 WHERE key2 = 1 
                     "range_scan_alternatives": [
                       {
                         "index": "i2_1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1"
                         ] /* ranges */,
@@ -1551,6 +1559,7 @@ EXPLAIN SELECT * FROM t2 WHERE key2 = 1 
                       },
                       {
                         "index": "i2_2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1"
                         ] /* ranges */,
@@ -1787,6 +1796,7 @@ EXPLAIN SELECT * FROM t1 WHERE key2=10 O
                           "range_scan_alternatives": [
                             {
                               "index": "i2",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "10 <= key2 <= 10"
                               ] /* ranges */,
@@ -1804,6 +1814,7 @@ EXPLAIN SELECT * FROM t1 WHERE key2=10 O
                           "range_scan_alternatives": [
                             {
                               "index": "i3",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "3 <= key3 <= 3"
                               ] /* ranges */,
@@ -2217,6 +2228,7 @@ EXPLAIN SELECT * FROM t2 WHERE key1a = 5
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "5 <= key1a <= 5 AND key1b < 10"
                         ] /* ranges */,
@@ -2228,6 +2240,7 @@ EXPLAIN SELECT * FROM t2 WHERE key1a = 5
                       },
                       {
                         "index": "i1b",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "key1b < 10 AND 5 <= key1a <= 5"
                         ] /* ranges */,
@@ -2435,6 +2448,7 @@ EXPLAIN SELECT * FROM t2 WHERE (key1a = 
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "4 <= key1a <= 4 AND 3 < key1b < 7",
                           "5 <= key1a <= 5 AND 2 < key1b < 10"
@@ -2447,6 +2461,7 @@ EXPLAIN SELECT * FROM t2 WHERE (key1a = 
                       },
                       {
                         "index": "i1b",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "2 < key1b <= 3 AND 5 <= key1a <= 5",
                           "3 < key1b < 7",
@@ -2650,6 +2665,7 @@ EXPLAIN SELECT * FROM t2 WHERE (key1b < 
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "4 <= key1a <= 4 AND 7 < key1b < 10",
                           "5 <= key1a <= 5 AND 7 < key1b < 10"
@@ -2662,6 +2678,7 @@ EXPLAIN SELECT * FROM t2 WHERE (key1b < 
                       },
                       {
                         "index": "i1b",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7 < key1b < 10 AND 4 <= key1a <= 4",
                           "7 < key1b < 10 AND 5 <= key1a <= 5"
@@ -2882,6 +2899,7 @@ EXPLAIN SELECT * FROM t1 WHERE (key1 > 1
                           "range_scan_alternatives": [
                             {
                               "index": "i1",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "1 < key1"
                               ] /* ranges */,
@@ -2900,6 +2918,7 @@ EXPLAIN SELECT * FROM t1 WHERE (key1 > 1
                           "range_scan_alternatives": [
                             {
                               "index": "i2",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "2 < key2"
                               ] /* ranges */,
@@ -3129,6 +3148,7 @@ WHERE t1.key1=t2.key1a AND t1.key2 > 102
                     "range_scan_alternatives": [
                       {
                         "index": "i2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1020 < key2"
                         ] /* ranges */,
@@ -3384,6 +3404,7 @@ EXPLAIN SELECT * FROM t1 WHERE cola = 'f
                     "range_scan_alternatives": [
                       {
                         "index": "cola",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "foo <= cola <= foo"
                         ] /* ranges */,
@@ -3395,6 +3416,7 @@ EXPLAIN SELECT * FROM t1 WHERE cola = 'f
                       },
                       {
                         "index": "colb",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "bar <= colb <= bar"
                         ] /* ranges */,
@@ -3637,6 +3659,7 @@ EXPLAIN SELECT * FROM t1 WHERE cola = 'f
                     "range_scan_alternatives": [
                       {
                         "index": "cola",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "f\no <= cola <= f\no"
                         ] /* ranges */,
@@ -4510,6 +4533,7 @@ EXPLAIN SELECT * FROM t1 WHERE i1 > '2' 
                     "range_scan_alternatives": [
                       {
                         "index": "k1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "2 < i1"
                         ] /* ranges */,
@@ -4521,6 +4545,7 @@ EXPLAIN SELECT * FROM t1 WHERE i1 > '2' 
                       },
                       {
                         "index": "k2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "2 < i1"
                         ] /* ranges */,
@@ -4662,6 +4687,7 @@ EXPLAIN SELECT * FROM t1 WHERE i1 > '2' 
                     "range_scan_alternatives": [
                       {
                         "index": "k2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "2 < i1"
                         ] /* ranges */,
@@ -4807,6 +4833,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                       {
                         "index": "k1",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -4816,6 +4843,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                       {
                         "index": "k2",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -4846,6 +4874,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                     "range_scan_alternatives": [
                       {
                         "index": "k1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -4858,6 +4887,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                       },
                       {
                         "index": "k2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -4969,6 +4999,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                     "range_scan_alternatives": [
                       {
                         "index": "k1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -5203,6 +5234,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "pk < 3"
                         ] /* ranges */,
@@ -5215,6 +5247,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                       },
                       {
                         "index": "i1_idx",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1 <= 1"
                         ] /* ranges */,
@@ -5227,6 +5260,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                       },
                       {
                         "index": "v_idx",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "a <= v <= a AND 1 <= i1 <= 1"
                         ] /* ranges */,
@@ -5507,6 +5541,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "pk < 3"
                         ] /* ranges */,
@@ -5518,6 +5553,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                       },
                       {
                         "index": "v_idx",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "a <= v <= a AND 1 <= i1 <= 1"
                         ] /* ranges */,
@@ -5529,6 +5565,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                       },
                       {
                         "index": "i1_i2_idx",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i2 <= 1 AND 1 <= i1 <= 1"
                         ] /* ranges */,
@@ -5782,6 +5819,7 @@ EXPLAIN SELECT MAX(b), a FROM t1 WHERE b
                       {
                         "index": "PRIMARY",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= a <= 1 AND b < 2"
                         ] /* ranges */,
@@ -5816,6 +5854,7 @@ EXPLAIN SELECT MAX(b), a FROM t1 WHERE b
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= a <= 1 AND b < 2"
                         ] /* ranges */,
@@ -5828,6 +5867,7 @@ EXPLAIN SELECT MAX(b), a FROM t1 WHERE b
                       },
                       {
                         "index": "b",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "b < 2"
                         ] /* ranges */,
@@ -6079,6 +6119,7 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = '1' 
                     "range_scan_alternatives": [
                       {
                         "index": "k1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= c1 <= 1"
                         ] /* ranges */,
@@ -6090,6 +6131,7 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = '1' 
                       },
                       {
                         "index": "k2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= c1 <= 1"
                         ] /* ranges */,

=== modified file 'mysql-test/suite/opt_trace/r/range_ps_prot.result'
--- a/mysql-test/suite/opt_trace/r/range_ps_prot.result	2011-12-01 14:12:10 +0000
+++ b/mysql-test/suite/opt_trace/r/range_ps_prot.result	2012-01-30 08:57:24 +0000
@@ -157,6 +157,7 @@ EXPLAIN SELECT * FROM t1 WHERE key2 < 5 
                     "range_scan_alternatives": [
                       {
                         "index": "i2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "key2 < 5",
                           "1020 < key2"
@@ -529,6 +530,7 @@ EXPLAIN SELECT * FROM t1 WHERE key1 < 3 
                           "range_scan_alternatives": [
                             {
                               "index": "i1",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "key1 < 3"
                               ] /* ranges */,
@@ -546,6 +548,7 @@ EXPLAIN SELECT * FROM t1 WHERE key1 < 3 
                           "range_scan_alternatives": [
                             {
                               "index": "i2",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "1020 < key2"
                               ] /* ranges */,
@@ -1233,6 +1236,7 @@ GROUP BY key2	{
                       {
                         "index": "i2_1",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1",
                           "2 <= key2 <= 2",
@@ -1246,6 +1250,7 @@ GROUP BY key2	{
                       {
                         "index": "i2_2",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1",
                           "2 <= key2 <= 2",
@@ -1283,6 +1288,7 @@ GROUP BY key2	{
                     "range_scan_alternatives": [
                       {
                         "index": "i2_1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1",
                           "2 <= key2 <= 2",
@@ -1298,6 +1304,7 @@ GROUP BY key2	{
                       },
                       {
                         "index": "i2_2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1",
                           "2 <= key2 <= 2",
@@ -1540,6 +1547,7 @@ EXPLAIN SELECT * FROM t2 WHERE key2 = 1 
                     "range_scan_alternatives": [
                       {
                         "index": "i2_1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1"
                         ] /* ranges */,
@@ -1551,6 +1559,7 @@ EXPLAIN SELECT * FROM t2 WHERE key2 = 1 
                       },
                       {
                         "index": "i2_2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= key2 <= 1"
                         ] /* ranges */,
@@ -1787,6 +1796,7 @@ EXPLAIN SELECT * FROM t1 WHERE key2=10 O
                           "range_scan_alternatives": [
                             {
                               "index": "i2",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "10 <= key2 <= 10"
                               ] /* ranges */,
@@ -1804,6 +1814,7 @@ EXPLAIN SELECT * FROM t1 WHERE key2=10 O
                           "range_scan_alternatives": [
                             {
                               "index": "i3",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "3 <= key3 <= 3"
                               ] /* ranges */,
@@ -2217,6 +2228,7 @@ EXPLAIN SELECT * FROM t2 WHERE key1a = 5
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "5 <= key1a <= 5 AND key1b < 10"
                         ] /* ranges */,
@@ -2228,6 +2240,7 @@ EXPLAIN SELECT * FROM t2 WHERE key1a = 5
                       },
                       {
                         "index": "i1b",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "key1b < 10 AND 5 <= key1a <= 5"
                         ] /* ranges */,
@@ -2435,6 +2448,7 @@ EXPLAIN SELECT * FROM t2 WHERE (key1a = 
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "4 <= key1a <= 4 AND 3 < key1b < 7",
                           "5 <= key1a <= 5 AND 2 < key1b < 10"
@@ -2447,6 +2461,7 @@ EXPLAIN SELECT * FROM t2 WHERE (key1a = 
                       },
                       {
                         "index": "i1b",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "2 < key1b <= 3 AND 5 <= key1a <= 5",
                           "3 < key1b < 7",
@@ -2650,6 +2665,7 @@ EXPLAIN SELECT * FROM t2 WHERE (key1b < 
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "4 <= key1a <= 4 AND 7 < key1b < 10",
                           "5 <= key1a <= 5 AND 7 < key1b < 10"
@@ -2662,6 +2678,7 @@ EXPLAIN SELECT * FROM t2 WHERE (key1b < 
                       },
                       {
                         "index": "i1b",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "7 < key1b < 10 AND 4 <= key1a <= 4",
                           "7 < key1b < 10 AND 5 <= key1a <= 5"
@@ -2882,6 +2899,7 @@ EXPLAIN SELECT * FROM t1 WHERE (key1 > 1
                           "range_scan_alternatives": [
                             {
                               "index": "i1",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "1 < key1"
                               ] /* ranges */,
@@ -2900,6 +2918,7 @@ EXPLAIN SELECT * FROM t1 WHERE (key1 > 1
                           "range_scan_alternatives": [
                             {
                               "index": "i2",
+                              "index_dives_for_eq_ranges": true,
                               "ranges": [
                                 "2 < key2"
                               ] /* ranges */,
@@ -3129,6 +3148,7 @@ WHERE t1.key1=t2.key1a AND t1.key2 > 102
                     "range_scan_alternatives": [
                       {
                         "index": "i2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1020 < key2"
                         ] /* ranges */,
@@ -3384,6 +3404,7 @@ EXPLAIN SELECT * FROM t1 WHERE cola = 'f
                     "range_scan_alternatives": [
                       {
                         "index": "cola",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "foo <= cola <= foo"
                         ] /* ranges */,
@@ -3395,6 +3416,7 @@ EXPLAIN SELECT * FROM t1 WHERE cola = 'f
                       },
                       {
                         "index": "colb",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "bar <= colb <= bar"
                         ] /* ranges */,
@@ -3637,6 +3659,7 @@ EXPLAIN SELECT * FROM t1 WHERE cola = 'f
                     "range_scan_alternatives": [
                       {
                         "index": "cola",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "f\no <= cola <= f\no"
                         ] /* ranges */,
@@ -4510,6 +4533,7 @@ EXPLAIN SELECT * FROM t1 WHERE i1 > '2' 
                     "range_scan_alternatives": [
                       {
                         "index": "k1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "2 < i1"
                         ] /* ranges */,
@@ -4521,6 +4545,7 @@ EXPLAIN SELECT * FROM t1 WHERE i1 > '2' 
                       },
                       {
                         "index": "k2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "2 < i1"
                         ] /* ranges */,
@@ -4662,6 +4687,7 @@ EXPLAIN SELECT * FROM t1 WHERE i1 > '2' 
                     "range_scan_alternatives": [
                       {
                         "index": "k2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "2 < i1"
                         ] /* ranges */,
@@ -4807,6 +4833,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                       {
                         "index": "k1",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -4816,6 +4843,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                       {
                         "index": "k2",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -4846,6 +4874,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                     "range_scan_alternatives": [
                       {
                         "index": "k1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -4858,6 +4887,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                       },
                       {
                         "index": "k2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -4969,6 +4999,7 @@ EXPLAIN SELECT DISTINCT i1 FROM t1 WHERE
                     "range_scan_alternatives": [
                       {
                         "index": "k1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1"
                         ] /* ranges */,
@@ -5203,6 +5234,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "pk < 3"
                         ] /* ranges */,
@@ -5215,6 +5247,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                       },
                       {
                         "index": "i1_idx",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i1 <= 1"
                         ] /* ranges */,
@@ -5227,6 +5260,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                       },
                       {
                         "index": "v_idx",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "a <= v <= a AND 1 <= i1 <= 1"
                         ] /* ranges */,
@@ -5507,6 +5541,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "pk < 3"
                         ] /* ranges */,
@@ -5518,6 +5553,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                       },
                       {
                         "index": "v_idx",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "a <= v <= a AND 1 <= i1 <= 1"
                         ] /* ranges */,
@@ -5529,6 +5565,7 @@ EXPLAIN SELECT v FROM t1 WHERE i1 = 1 AN
                       },
                       {
                         "index": "i1_i2_idx",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= i2 <= 1 AND 1 <= i1 <= 1"
                         ] /* ranges */,
@@ -5782,6 +5819,7 @@ EXPLAIN SELECT MAX(b), a FROM t1 WHERE b
                       {
                         "index": "PRIMARY",
                         "covering": true,
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= a <= 1 AND b < 2"
                         ] /* ranges */,
@@ -5816,6 +5854,7 @@ EXPLAIN SELECT MAX(b), a FROM t1 WHERE b
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= a <= 1 AND b < 2"
                         ] /* ranges */,
@@ -5828,6 +5867,7 @@ EXPLAIN SELECT MAX(b), a FROM t1 WHERE b
                       },
                       {
                         "index": "b",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "b < 2"
                         ] /* ranges */,
@@ -6079,6 +6119,7 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = '1' 
                     "range_scan_alternatives": [
                       {
                         "index": "k1",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= c1 <= 1"
                         ] /* ranges */,
@@ -6090,6 +6131,7 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = '1' 
                       },
                       {
                         "index": "k2",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "1 <= c1 <= 1"
                         ] /* ranges */,

=== 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-10 18:58:10 +0000
+++ b/mysql-test/suite/opt_trace/r/subquery_no_prot.result	2012-01-26 13:09:59 +0000
@@ -1269,6 +1269,7 @@ field4,field5,field6	{
                     "range_scan_alternatives": [
                       {
                         "index": "col_int_key",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL < col_int_key < 214",
                           "214 < col_int_key"
@@ -1985,6 +1986,7 @@ table2.`col_int_nokey` <> any ( select 5
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "18 <= pk <= 18",
                           "192 <= pk <= 192"

=== 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-10 18:58:10 +0000
+++ b/mysql-test/suite/opt_trace/r/subquery_ps_prot.result	2012-01-30 08:57:24 +0000
@@ -1247,6 +1247,7 @@ field4,field5,field6	{
                     "range_scan_alternatives": [
                       {
                         "index": "col_int_key",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "NULL < col_int_key < 214",
                           "214 < col_int_key"
@@ -1953,6 +1954,7 @@ table2.`col_int_nokey` <> any ( select 5
                     "range_scan_alternatives": [
                       {
                         "index": "PRIMARY",
+                        "index_dives_for_eq_ranges": true,
                         "ranges": [
                           "18 <= pk <= 18",
                           "192 <= pk <= 192"

=== added file 'mysql-test/suite/opt_trace/t/eq_range_statistics.test'
--- a/mysql-test/suite/opt_trace/t/eq_range_statistics.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/opt_trace/t/eq_range_statistics.test	2012-01-26 13:09:59 +0000
@@ -0,0 +1,83 @@
+# Tests for eq_range_index_dive_limit variable: 
+#   test that the number of ranges are counted correctly and 
+#   index statistics kicks in when more than 
+#   eq_range_index_dive_limit equality ranges are in the 
+#   predicate
+
+--source include/have_optimizer_trace.inc
+
+SET optimizer_trace_max_mem_size=1048576; # 1MB
+SET optimizer_trace="enabled=on,end_marker=on,one_line=off";
+
+SET eq_range_index_dive_limit=default;
+SELECT @@eq_range_index_dive_limit;
+
+CREATE TABLE t1 (
+       a INT, 
+       b INT, 
+       KEY (a,b)
+);
+
+INSERT INTO t1 VALUES (1,1), (2,2), (3,3);
+INSERT INTO t1 VALUES (4,1), (4,2), (4,3);
+INSERT INTO t1 VALUES (5,1), (5,2), (5,3);
+
+SHOW INDEX FROM t1;
+ANALYZE TABLE t1;      
+SHOW INDEX FROM t1;
+
+--echo #####
+--echo # Apply knowledge about the statistics (each index value for 
+--echo # the first key part has an estimate of 2 rows) to ensure that 
+--echo # index statistics kicks in correctly.
+--echo #####
+
+--echo # Index dives are done, giving correct estimate of 3 records
+EXPLAIN SELECT * FROM t1 WHERE a IN (1,2,3);
+
+SET eq_range_index_dive_limit=3;
+SELECT @@eq_range_index_dive_limit;
+
+--echo # Index statistics kicks in, giving incorrect estimate of 3x2=6 records
+EXPLAIN SELECT * FROM t1 WHERE a IN (1,2,3);
+
+--echo #####
+--echo # Below: A number of tests to verify that the number of equality ranges
+--echo # are counted correctly
+--echo #####
+
+# The limit is 3
+
+--echo
+--echo # 2 equality ranges: should not use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 OR a>10 OR a IN (1);
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+
+--echo
+--echo # 3 equality ranges: should use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 OR a>10 OR a IN (1,2);
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+
+--echo
+--echo # 3 equality ranges: should use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b=4);
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+
+--echo
+--echo # 2 equality ranges: should not use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b>4);
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+
+--echo
+--echo # 2 equality ranges: should not use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a=5 AND (b=2 OR b=3 OR b IS NULL);
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+
+--echo
+--echo # 0 equality ranges: should not use index statistics
+EXPLAIN SELECT * FROM t1 WHERE a>5 AND (b=2 OR b=3 OR b=4);
+SELECT * FROM information_schema.OPTIMIZER_TRACE;
+
+DROP TABLE t1;
+
+SET eq_range_index_dive_limit=default;

=== added file 'mysql-test/suite/sys_vars/r/eq_range_index_dive_limit_basic.result'
--- a/mysql-test/suite/sys_vars/r/eq_range_index_dive_limit_basic.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/eq_range_index_dive_limit_basic.result	2012-01-26 13:09:59 +0000
@@ -0,0 +1,96 @@
+SET @start_global_value = @@global.eq_range_index_dive_limit;
+SELECT @start_global_value;
+@start_global_value
+10
+select @@global.eq_range_index_dive_limit;
+@@global.eq_range_index_dive_limit
+10
+select @@session.eq_range_index_dive_limit;
+@@session.eq_range_index_dive_limit
+10
+show global variables like 'eq_range_index_dive_limit';
+Variable_name	Value
+eq_range_index_dive_limit	10
+show session variables like 'eq_range_index_dive_limit';
+Variable_name	Value
+eq_range_index_dive_limit	10
+select * 
+from information_schema.global_variables 
+where variable_name='eq_range_index_dive_limit';
+VARIABLE_NAME	VARIABLE_VALUE
+EQ_RANGE_INDEX_DIVE_LIMIT	10
+select * 
+from information_schema.session_variables 
+where variable_name='eq_range_index_dive_limit';
+VARIABLE_NAME	VARIABLE_VALUE
+EQ_RANGE_INDEX_DIVE_LIMIT	10
+set global eq_range_index_dive_limit=10;
+select @@global.eq_range_index_dive_limit;
+@@global.eq_range_index_dive_limit
+10
+set session eq_range_index_dive_limit=10;
+select @@session.eq_range_index_dive_limit;
+@@session.eq_range_index_dive_limit
+10
+set global eq_range_index_dive_limit=0;
+select @@global.eq_range_index_dive_limit;
+@@global.eq_range_index_dive_limit
+0
+set session eq_range_index_dive_limit=0;
+select @@session.eq_range_index_dive_limit;
+@@session.eq_range_index_dive_limit
+0
+set global eq_range_index_dive_limit=4294967295;
+select @@global.eq_range_index_dive_limit;
+@@global.eq_range_index_dive_limit
+4294967295
+set session eq_range_index_dive_limit=4294967295;
+select @@session.eq_range_index_dive_limit;
+@@session.eq_range_index_dive_limit
+4294967295
+set session eq_range_index_dive_limit=default;
+select @@session.eq_range_index_dive_limit;
+@@session.eq_range_index_dive_limit
+4294967295
+set global eq_range_index_dive_limit=default;
+select @@global.eq_range_index_dive_limit;
+@@global.eq_range_index_dive_limit
+10
+set session eq_range_index_dive_limit=default;
+select @@session.eq_range_index_dive_limit;
+@@session.eq_range_index_dive_limit
+10
+set global eq_range_index_dive_limit=-1;
+Warnings:
+Warning	1292	Truncated incorrect eq_range_index_dive_limit value: '-1'
+select @@global.eq_range_index_dive_limit;
+@@global.eq_range_index_dive_limit
+0
+set session eq_range_index_dive_limit=-1;
+Warnings:
+Warning	1292	Truncated incorrect eq_range_index_dive_limit value: '-1'
+select @@session.eq_range_index_dive_limit;
+@@session.eq_range_index_dive_limit
+0
+set global eq_range_index_dive_limit=4294967296;
+Warnings:
+Warning	1292	Truncated incorrect eq_range_index_dive_limit value: '4294967296'
+select @@global.eq_range_index_dive_limit;
+@@global.eq_range_index_dive_limit
+4294967295
+set session eq_range_index_dive_limit=4294967296;
+Warnings:
+Warning	1292	Truncated incorrect eq_range_index_dive_limit value: '4294967296'
+select @@session.eq_range_index_dive_limit;
+@@session.eq_range_index_dive_limit
+4294967295
+set global eq_range_index_dive_limit=1.1;
+ERROR 42000: Incorrect argument type to variable 'eq_range_index_dive_limit'
+set global eq_range_index_dive_limit=1e1;
+ERROR 42000: Incorrect argument type to variable 'eq_range_index_dive_limit'
+set global eq_range_index_dive_limit="foobar";
+ERROR 42000: Incorrect argument type to variable 'eq_range_index_dive_limit'
+SET @@global.eq_range_index_dive_limit = @start_global_value;
+SELECT @@global.eq_range_index_dive_limit;
+@@global.eq_range_index_dive_limit
+10

=== added file 'mysql-test/suite/sys_vars/t/eq_range_index_dive_limit_basic.test'
--- a/mysql-test/suite/sys_vars/t/eq_range_index_dive_limit_basic.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/eq_range_index_dive_limit_basic.test	2012-01-26 13:09:59 +0000
@@ -0,0 +1,71 @@
+SET @start_global_value = @@global.eq_range_index_dive_limit;
+SELECT @start_global_value;
+
+#
+# exists as global and session
+#
+select @@global.eq_range_index_dive_limit;
+select @@session.eq_range_index_dive_limit;
+show global variables like 'eq_range_index_dive_limit';
+show session variables like 'eq_range_index_dive_limit';
+
+select * 
+from information_schema.global_variables 
+where variable_name='eq_range_index_dive_limit';
+
+select * 
+from information_schema.session_variables 
+where variable_name='eq_range_index_dive_limit';
+
+#
+# show that it's writable
+#
+set global eq_range_index_dive_limit=10;
+select @@global.eq_range_index_dive_limit;
+set session eq_range_index_dive_limit=10;
+select @@session.eq_range_index_dive_limit;
+
+set global eq_range_index_dive_limit=0;
+select @@global.eq_range_index_dive_limit;
+set session eq_range_index_dive_limit=0;
+select @@session.eq_range_index_dive_limit;
+
+set global eq_range_index_dive_limit=4294967295;
+select @@global.eq_range_index_dive_limit;
+set session eq_range_index_dive_limit=4294967295;
+select @@session.eq_range_index_dive_limit;
+
+set session eq_range_index_dive_limit=default;
+select @@session.eq_range_index_dive_limit;
+set global eq_range_index_dive_limit=default;
+select @@global.eq_range_index_dive_limit;
+set session eq_range_index_dive_limit=default;
+select @@session.eq_range_index_dive_limit;
+
+#
+# Incorrect assignments
+#
+
+# Allowed value range: (0, UINT_MAX32)
+# Value lower than allowed range
+set global eq_range_index_dive_limit=-1;
+select @@global.eq_range_index_dive_limit;
+set session eq_range_index_dive_limit=-1;
+select @@session.eq_range_index_dive_limit;
+
+# Value higher than allowed range
+set global eq_range_index_dive_limit=4294967296;
+select @@global.eq_range_index_dive_limit;
+set session eq_range_index_dive_limit=4294967296;
+select @@session.eq_range_index_dive_limit;
+
+# Incompatible value types
+--error ER_WRONG_TYPE_FOR_VAR
+set global eq_range_index_dive_limit=1.1;
+--error ER_WRONG_TYPE_FOR_VAR
+set global eq_range_index_dive_limit=1e1;
+--error ER_WRONG_TYPE_FOR_VAR
+set global eq_range_index_dive_limit="foobar";
+
+SET @@global.eq_range_index_dive_limit = @start_global_value;
+SELECT @@global.eq_range_index_dive_limit;

=== modified file 'sql/filesort.cc'
--- a/sql/filesort.cc	2012-01-18 13:03:10 +0000
+++ b/sql/filesort.cc	2012-01-18 14:42:16 +0000
@@ -292,8 +292,8 @@ ha_rows filesort(THD *thd, TABLE *table,
             table_sort.sort_buffer_properties())
         {
           /*
-           table->sort will still have a pointer to the same buffer,
-           but that will be overwritten by the assignment below.
+            table->sort will still have a pointer to the same buffer,
+            but that will be overwritten by the assignment below.
           */
           table_sort.free_sort_buffer();
         }

=== modified file 'sql/filesort_utils.h'
--- a/sql/filesort_utils.h	2012-01-18 13:03:10 +0000
+++ b/sql/filesort_utils.h	2012-01-18 14:42:16 +0000
@@ -89,7 +89,7 @@ public:
   uchar **alloc_sort_buffer(uint num_records, uint record_length);
 
   /// What is the <num_records, record_length> for the buffer?
-  std::pair<uint, uint> sort_buffer_properties()
+  std::pair<uint, uint> sort_buffer_properties() const
   { return std::make_pair(m_idx_array.size(), m_record_length); }
 
   /// Frees the buffer.

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2012-01-26 12:53:38 +0000
+++ b/sql/handler.cc	2012-01-30 10:34:28 +0000
@@ -37,6 +37,7 @@
 #include "probes_mysql.h"
 #include <mysql/psi/mysql_table.h>
 #include "debug_sync.h"         // DEBUG_SYNC
+#include <my_bit.h>
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
 #include "ha_partition.h"
@@ -4583,8 +4584,36 @@ handler::multi_range_read_info_const(uin
       min_endp= range.start_key.length? &range.start_key : NULL;
       max_endp= range.end_key.length? &range.end_key : NULL;
     }
-    if ((range.range_flag & UNIQUE_RANGE) && !(range.range_flag & NULL_RANGE))
+    /*
+      Get the number of rows in the range. This is done by calling
+      records_in_range() unless:
+
+        1) The range is an equality range and the index is unique.
+           There cannot be more than one matching row, so 1 is
+           assumed. Note that it is possible that the correct number
+           is actually 0, so the row estimate may be too high in this
+           case. Also note: ranges of the form "x IS NULL" may have more
+           than 1 mathing row so records_in_range() is called for these.
+        2) a) The range is an equality range but the index is either 
+              not unique or all of the keyparts are not used. 
+           b) The user has requested that index statistics should be used
+              for equality ranges to avoid the incurred overhead of 
+              index dives in records_in_range().
+           c) Index statistics is available.
+           Ranges of the form "x IS NULL" will not use index statistics 
+           because the number of rows with this value are likely to be 
+           very different than the values in the index statistics.
+    */
+    int keyparts_used= 0;
+    if ((range.range_flag & UNIQUE_RANGE) &&                        // 1)
+        !(range.range_flag & NULL_RANGE))
       rows= 1; /* there can be at most one row */
+    else if ((range.range_flag & EQ_RANGE) &&                       // 2a)
+             (range.range_flag & USE_INDEX_STATISTICS) &&           // 2b)
+             (keyparts_used= my_count_bits(range.start_key.keypart_map)) &&
+             table->key_info[keyno].rec_per_key[keyparts_used-1] && // 2c)
+             !(range.range_flag & NULL_RANGE))
+      rows= table->key_info[keyno].rec_per_key[keyparts_used-1];
     else
     {
       if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp, 

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2012-01-26 12:53:38 +0000
+++ b/sql/opt_range.cc	2012-01-30 10:34:28 +0000
@@ -213,7 +213,7 @@ class RANGE_OPT_PARAM;
         +---+       +---+   +---+       +---+
 
   In this tree,
-    * node0->prev == node7->next == NULL
+    * node1->prev == node7->next == NULL
     * node1->left == node1->right ==
       node3->left == ... node7->right == &null_element
 
@@ -789,6 +789,12 @@ public:
   /* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */
   uint alloced_sel_args; 
   bool force_default_mrr;
+  /** 
+    Whether index statistics or index dives should be used when
+    estimating the number of rows in an equality range. If true, index
+    statistics is used for these indexes.
+  */
+  bool use_index_statistics;
 };
 
 class PARAM : public RANGE_OPT_PARAM
@@ -897,6 +903,8 @@ bool get_quick_keys(PARAM *param,QUICK_R
                     SEL_ARG *key_tree, uchar *min_key,uint min_key_flag,
                     uchar *max_key,uint max_key_flag);
 static bool eq_tree(SEL_ARG* a,SEL_ARG *b);
+static bool eq_ranges_exceeds_limit(SEL_ARG *keypart_root, uint* count, 
+                                    uint limit);
 
 static SEL_ARG null_element(SEL_ARG::IMPOSSIBLE);
 static bool null_part_in_key(KEY_PART *key_part, const uchar *key,
@@ -2570,6 +2578,7 @@ int SQL_SELECT::test_quick_select(THD *t
     param.remove_jump_scans= TRUE;
     param.force_default_mrr= (interesting_order == ORDER::ORDER_DESC);
     param.order_direction= interesting_order;
+    param.use_index_statistics= false;
 
     thd->no_errors=1;				// Don't warn about NULL
     init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
@@ -5445,6 +5454,7 @@ static TRP_RANGE *get_key_scans_params(P
       if (found_records != HA_POS_ERROR &&
           param->thd->opt_trace.is_started())
       {
+        trace_idx.add("index_dives_for_eq_ranges", !param->use_index_statistics);
         Opt_trace_array trace_range(&param->thd->opt_trace, "ranges");
 
         const KEY &cur_key= param->table->key_info[keynr];
@@ -8372,6 +8382,12 @@ typedef struct st_range_seq_entry 
   
   /* Number of key parts */
   uint min_key_parts, max_key_parts;
+  /**
+    Pointer into the R-B tree for this keypart. It points to the
+    currently active range for the keypart, so calling next on it will
+    get to the next range. sel_arg_range_seq_next() uses this to avoid
+    reparsing the R-B range trees each time a new range is fetched.
+  */
   SEL_ARG *key_tree;
 } RANGE_SEQ_ENTRY;
 
@@ -8386,9 +8402,50 @@ typedef struct st_sel_arg_range_seq
   PARAM *param;
   SEL_ARG *start; /* Root node of the traversed SEL_ARG* graph */
   
+  /**
+    Stack of ranges for the curr_kp first keyparts. Used by
+    sel_arg_range_seq_next() so that if the next range is equal to the
+    previous one for the first x keyparts, stack[x-1] can be
+    accumulated with the new range in keyparts > x to quickly form
+    the next range to return.
+
+    Notation used below: "x:y" means a range where
+    "column_in_keypart_0=x" and "column_in_keypart_1=y". For
+    simplicity, only equality (no BETWEEN, < etc) is considered in the
+    example but the same principle applies to other range predicate
+    operators too.
+
+    Consider a query with these range predicates: 
+      (kp0=1 and kp1=2 and kp2=3) or
+      (kp0=1 and kp1=2 and kp2=4) or
+      (kp0=1 and kp1=3 and kp2=5) or
+      (kp0=1 and kp1=3 and kp2=6)
+
+    1) sel_arg_range_seq_next() is called the first time
+       - traverse the R-B tree (see SEL_ARG) to find the first range
+       - returns range "1:2:3"
+       - values in stack after this: stack[1, 1:2, 1:2:3]
+    2) sel_arg_range_seq_next() is called second time
+       - keypart 2 has another range, so the next range in 
+         keypart 2 is appended to stack[1] and saved 
+         in stack[2]
+       - returns range "1:2:4"
+       - values in stack after this: stack[1, 1:2, 1:2:4]
+    3) sel_arg_range_seq_next() is called the third time
+       - no more ranges in keypart 2, but keypart 1 has 
+         another range, so the next range in keypart 1 is
+         appended to stack[0] and saved in stack[1]. The first
+         range in keypart 2 is then appended to stack[1] and
+         saved in stack[2]
+       - returns range "1:3:5"
+       - values in stack after this: stack[1, 1:3, 1:3:5]
+    4) sel_arg_range_seq_next() is called the fourth time
+       - keypart 2 has another range, see 2)
+       - returns range "1:3:6"
+       - values in stack after this: stack[1, 1:3, 1:3:6]
+   */
   RANGE_SEQ_ENTRY stack[MAX_REF_PARTS];
-  int i; /* Index of last used element in the above array */
-  
+  int curr_kp; /* Index of last used element in the above array */
   bool at_start; /* TRUE <=> The traversal has just started */
 } SEL_ARG_RANGE_SEQ;
 
@@ -8418,16 +8475,16 @@ range_seq_t sel_arg_range_seq_init(void 
   seq->stack[0].max_key= (uchar*)seq->param->max_key;
   seq->stack[0].max_key_flag= 0;
   seq->stack[0].max_key_parts= 0;
-  seq->i= 0;
+  seq->curr_kp= 0;
   return init_param;
 }
 
 
-static void step_down_to(SEL_ARG_RANGE_SEQ *arg, SEL_ARG *key_tree)
+static void push_range_to_stack(SEL_ARG_RANGE_SEQ *arg, SEL_ARG *key_tree)
 {
 
-  RANGE_SEQ_ENTRY *cur= &arg->stack[arg->i+1];
-  RANGE_SEQ_ENTRY *prev= &arg->stack[arg->i];
+  RANGE_SEQ_ENTRY *cur= &arg->stack[arg->curr_kp+1];
+  RANGE_SEQ_ENTRY *prev= &arg->stack[arg->curr_kp];
   
   cur->key_tree= key_tree;
   cur->min_key= prev->min_key;
@@ -8451,12 +8508,13 @@ static void step_down_to(SEL_ARG_RANGE_S
 
   if (key_tree->is_null_interval())
     cur->min_key_flag |= NULL_RANGE;
-  (arg->i)++;
+  (arg->curr_kp)++;
 }
 
 
 /*
   Range sequence interface, SEL_ARG* implementation: get the next interval
+  in the R-B tree
   
   SYNOPSIS
     sel_arg_range_seq_next()
@@ -8486,67 +8544,118 @@ uint sel_arg_range_seq_next(range_seq_t 
 
   if (seq->at_start)
   {
+    /*
+      This is the first time sel_arg_range_seq_next is called.
+      seq->start points to the root of the R-B tree for the first
+      keypart
+    */
     key_tree= seq->start;
     seq->at_start= FALSE;
-    goto walk_up_n_right;
-  }
 
-  key_tree= seq->stack[seq->i].key_tree;
-  /* Ok, we're at some "full tuple" position in the tree */
- 
-  /* Step down if we can */
-  if (key_tree->next)
-  {
-    DBUG_ASSERT(key_tree->next != &null_element);
-    //step down; (update the tuple, we'll step right and stay there)
-    seq->i--;
-    step_down_to(seq, key_tree->next);
-    key_tree= key_tree->next;
-    seq->param->is_ror_scan= FALSE;
-    goto walk_right_n_up;
+    /*
+      Move to the first range for the first keypart. Save this range
+      in seq->stack[0] and carry on to ranges in the next keypart if
+      any
+    */
+    key_tree= key_tree->first();
+    push_range_to_stack(seq, key_tree);
   }
-
-  /* Ok, can't step down, walk left until we can step down */
-  while (1)
+  else
   {
-    if (seq->i == 1) // can't step left
-      return 1;
+    /*
+      This is not the first time sel_arg_range_seq_next is called, so
+      seq->stack is populated with the range the last call to this
+      function found. seq->stack[current_keypart].key_tree points to a
+      leaf in the R-B tree of the last keypart that was part of the
+      former range. This is the starting point for finding the next
+      range. @see SEL_ARG_RANGE_SEQ::stack
+    */
+    key_tree= seq->stack[seq->curr_kp].key_tree;
 
-    /* Step left */
-    seq->i--;
-    key_tree= seq->stack[seq->i].key_tree;
-
-    /* Step down if we can */
-    if (key_tree->next)
-    {
-      DBUG_ASSERT(key_tree->next != &null_element);
-      // Step down; update the tuple
-      seq->i--;
-      step_down_to(seq, key_tree->next);
-      key_tree= key_tree->next;
-      seq->param->is_ror_scan= FALSE;
-      break;
+    // See if there are more ranges in this or any of the previous keyparts
+    while (true)
+    {
+      if (key_tree->next)
+      {
+        /* This keypart has more ranges */
+        DBUG_ASSERT(key_tree->next != &null_element);
+        key_tree= key_tree->next;
+
+        seq->curr_kp--;
+        /*
+          save the next range for this keypart and carry on to ranges in
+          the next keypart if any
+        */
+        push_range_to_stack(seq, key_tree);
+        seq->param->is_ror_scan= FALSE;
+        break;
+      }
+
+      if (seq->curr_kp == 1) 
+      {
+        // There are no more ranges for the first keypart: we're done
+        return 1;
+      }
+
+      /* 
+         No more ranges for the current keypart. Step back to the
+         previous keypart
+      */
+      seq->curr_kp--;
+      key_tree= seq->stack[seq->curr_kp].key_tree;
     }
   }
 
   /*
-    Ok, we've stepped down from the path to previous tuple.
-    Walk right-up while we can
+    Add range info for the next keypart if
+      1) there is a range predicate for a later keypart
+      2) the range predicate is for the next keypart in the index: a
+         range predicate on keypartX+1 can only be used if there is a
+         range predicate on keypartX.
+      3) the range predicate on the next keypart is usable
   */
-walk_right_n_up:
-  while (key_tree->next_key_part && key_tree->next_key_part != &null_element && 
-         key_tree->next_key_part->part == key_tree->part + 1 &&
-         key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
-  {
-    {
-      RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
-      uint min_key_length= cur->min_key - seq->param->min_key;
-      uint max_key_length= cur->max_key - seq->param->max_key;
-      uint len= cur->min_key - cur[-1].min_key;
-      if (!(min_key_length == max_key_length &&
-            !memcmp(cur[-1].min_key, cur[-1].max_key, len) &&
-            !key_tree->min_flag && !key_tree->max_flag))
+  while (key_tree->next_key_part &&                              // 1)
+         key_tree->next_key_part != &null_element &&             // 1)
+         key_tree->next_key_part->part == key_tree->part + 1 &&  // 2)
+         key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)    // 3)
+  {
+    {
+      RANGE_SEQ_ENTRY *cur= &seq->stack[seq->curr_kp];
+      const uint min_key_length= cur->min_key - seq->param->min_key;
+      const uint max_key_length= cur->max_key - seq->param->max_key;
+      const uint len= cur->min_key - cur[-1].min_key;
+      
+      if ((min_key_length != max_key_length ||
+           memcmp(cur[-1].min_key, cur[-1].max_key, len) ||
+           key_tree->min_flag || key_tree->max_flag))
       {
+        /* 
+          The range predicate up to and including the one in key_tree
+          is usable by range access but does not allow subranges made
+          up from predicates in later keyparts. This may e.g. be
+          because the predicate operator is "<". Since there are range
+          predicates on more keyparts, we use those to more closely
+          specify the start and stop locations for the range. Example:
+
+                "SELECT * FROM t1 WHERE a >= 2 AND b >= 3":
+
+                t1 content:
+                -----------
+                1 1
+                2 1     <- 1)
+                2 2
+                2 3     <- 2)
+                2 4
+                3 1
+                3 2
+                3 3
+
+          The predicate cannot be translated into something like
+             "(a=2 and b>=3) or (a=3 and b>=3) or ..."
+          I.e., it cannot be divided into subranges, but by storing
+          min/max key below we can at least start the scan from 2)
+          instead of 1)
+        */
         SEL_ARG *store_key_part= key_tree->next_key_part;
         seq->param->is_ror_scan= FALSE;
         if (!key_tree->min_flag)
@@ -8566,31 +8675,27 @@ walk_right_n_up:
     }
   
     /*
-      Ok, current atomic interval is in form "t.field=const" and there is
-      next_key_part interval. Step right, and walk up from there.
-    */
-    key_tree= key_tree->next_key_part;
-
-walk_up_n_right:
-    while (key_tree->prev)
-    {
-      DBUG_ASSERT(key_tree->prev != &null_element);
-      /* Step up */
-      key_tree= key_tree->prev;
-    }
-    step_down_to(seq, key_tree);
+      There are usable range predicates for the next keypart and the
+      range predicate for the current keypart allows us to make use of
+      them. Move to the first range predicate for the next keypart.
+      Push this range predicate to seq->stack and move on to the next
+      keypart (if any). @see SEL_ARG_RANGE_SEQ::stack
+    */
+    key_tree= key_tree->next_key_part->first();
+    push_range_to_stack(seq, key_tree);
   }
 
-  /* Ok got a tuple */
-  RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
-  uint min_key_length= cur->min_key - seq->param->min_key;
+  // We now have a full range predicate in seq->stack[seq->curr_kp]
+  RANGE_SEQ_ENTRY *cur= &seq->stack[seq->curr_kp];
+  PARAM *param= seq->param;
+  uint min_key_length= cur->min_key - param->min_key;
 
   if (cur->min_key_flag & GEOM_FLAG)
   {
     range->range_flag= cur->min_key_flag;
 
     /* Here minimum contains also function code bits, and maximum is +inf */
-    range->start_key.key=    seq->param->min_key;
+    range->start_key.key=    param->min_key;
     range->start_key.length= min_key_length;
     range->start_key.flag=  (ha_rkey_function) (cur->min_key_flag ^ GEOM_FLAG);
   }
@@ -8598,27 +8703,51 @@ walk_up_n_right:
   {
     range->range_flag= cur->min_key_flag | cur->max_key_flag;
     
-    range->start_key.key=    seq->param->min_key;
-    range->start_key.length= cur->min_key - seq->param->min_key;
+    range->start_key.key=    param->min_key;
+    range->start_key.length= cur->min_key - param->min_key;
     range->start_key.keypart_map= make_prev_keypart_map(cur->min_key_parts);
     range->start_key.flag= (cur->min_key_flag & NEAR_MIN ? HA_READ_AFTER_KEY : 
                                                            HA_READ_KEY_EXACT);
 
-    range->end_key.key=    seq->param->max_key;
-    range->end_key.length= cur->max_key - seq->param->max_key;
+    range->end_key.key=    param->max_key;
+    range->end_key.length= cur->max_key - param->max_key;
     range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts);
     range->end_key.flag= (cur->max_key_flag & NEAR_MAX ? HA_READ_BEFORE_KEY : 
                                                          HA_READ_AFTER_KEY);
 
-    if (!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag &&
-        (uint)key_tree->part+1 == seq->param->table->key_info[seq->real_keyno].key_parts &&
-        (seq->param->table->key_info[seq->real_keyno].flags & HA_NOSAME) ==
-        HA_NOSAME &&
-        range->start_key.length == range->end_key.length &&
-        !memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length))
-      range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
-      
-    if (seq->param->is_ror_scan)
+    /* 
+      This is an equality range (keypart_0=X and ... and keypart_n=Z) if 
+        1) There are no flags indicating open range (e.g., 
+           "keypart_x > y") or GIS.
+        2) The lower bound and the upper bound of the range has the
+           same value (min_key == max_key).
+     */
+    if (!(cur->min_key_flag & (NO_MIN_RANGE | NO_MAX_RANGE | 
+                               NEAR_MIN | NEAR_MAX | GEOM_FLAG)) &&       // 1)
+        !(cur->max_key_flag & (NO_MIN_RANGE | NO_MAX_RANGE | 
+                               NEAR_MIN | NEAR_MAX | GEOM_FLAG)) &&       // 1)
+        range->start_key.length == range->end_key.length &&               // 2)
+        !memcmp(param->min_key, param->max_key, range->start_key.length)) // 2)
+    {
+      range->range_flag= EQ_RANGE;
+      /*
+        Use statistics instead of index dives for estimates of rows in
+        this range if the user requested it
+      */
+      if (param->use_index_statistics)
+        range->range_flag|= USE_INDEX_STATISTICS;
+
+      /* 
+        An equality range is a unique range (0 or 1 rows in the range)
+        if the index is unique (1) and all keyparts are used (2).
+      */
+      if (param->table->key_info[seq->real_keyno].flags & HA_NOSAME &&    // 1)
+          (uint)key_tree->part+1 == param->table->
+                                    key_info[seq->real_keyno].key_parts)  // 2)
+        range->range_flag|= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
+    }
+
+    if (param->is_ror_scan)
     {
       /*
         If we get here, the condition on the key was converted to form
@@ -8629,11 +8758,15 @@ walk_up_n_right:
           uncovered "tail" of KeyX parts is either empty or is identical to
           first members of clustered primary key.
       */
-      if (!(!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag &&
+      if (!(!(cur->min_key_flag & (NO_MIN_RANGE | NO_MAX_RANGE | 
+                                   NEAR_MIN | NEAR_MAX | GEOM_FLAG)) && 
+            !(cur->max_key_flag & (NO_MIN_RANGE | NO_MAX_RANGE | 
+                                   NEAR_MIN | NEAR_MAX | GEOM_FLAG)) && 
             (range->start_key.length == range->end_key.length) &&
-            !memcmp(range->start_key.key, range->end_key.key, range->start_key.length) &&
-            is_key_scan_ror(seq->param, seq->real_keyno, key_tree->part + 1)))
-        seq->param->is_ror_scan= FALSE;
+            !memcmp(range->start_key.key, range->end_key.key, 
+                    range->start_key.length) &&
+            is_key_scan_ror(param, seq->real_keyno, key_tree->part + 1)))
+        param->is_ror_scan= FALSE;
     }
   }
 
@@ -8700,6 +8833,16 @@ ha_rows check_quick_select(PARAM *param,
   param->range_count=0;
   param->max_key_part=0;
 
+  /* 
+    If there are more equality ranges than specified by the
+    eq_range_index_dive_limit variable we switches from using index
+    dives to use statistics.
+  */ 
+  uint range_count= 0;
+  param->use_index_statistics= 
+    eq_ranges_exceeds_limit(tree, &range_count, 
+                            param->thd->variables.eq_range_index_dive_limit);
+
   param->is_ror_scan= TRUE;
   if (file->index_flags(keynr, 0, TRUE) & HA_KEY_SCAN_NOT_ROR)
     param->is_ror_scan= FALSE;
@@ -10938,10 +11081,10 @@ get_best_group_min_max(PARAM *param, SEL
                                                    cur_index_tree, TRUE,
                                                    &mrr_flags, &mrr_bufsize,
                                                    &dummy_cost);
-
 #ifdef OPTIMIZER_TRACE
       if (unlikely(cur_index_tree && trace->is_started()))
       {
+        trace_idx.add("index_dives_for_eq_ranges", !param->use_index_statistics);
         Opt_trace_array trace_range(trace, "ranges");
 
         const KEY_PART_INFO *key_part= cur_index_info->key_part;
@@ -12675,6 +12818,63 @@ void QUICK_GROUP_MIN_MAX_SELECT::add_key
 }
 
 
+
+/**
+  Traverse the R-B range tree for this and later keyparts to see if
+  there are at least as many equality ranges as defined by the limit.
+
+  @param keypart_root   The root of a R-B tree of ranges for a given keypart.
+  @param count[in,out]  The number of equality ranges found so far
+  @param limit          The number of ranges 
+
+  @retval true if 'limit' or more equality ranges have been found in the 
+          range R-B trees
+  @retval false otherwise         
+
+*/
+static bool eq_ranges_exceeds_limit(SEL_ARG *keypart_root, uint* count, uint limit)
+{
+  if (limit == UINT_MAX32)
+    return false;
+  if (limit == 0)
+    return true;
+  
+  for(SEL_ARG *keypart_range= keypart_root->first(); 
+      keypart_range; keypart_range= keypart_range->next)
+  {
+    /*
+      This is an equality range predicate and should be counted if:
+      1) the range for this keypart does not have a min/max flag 
+         (which indicates <, <= etc), and
+      2) the lower and upper range boundaries have the same value
+         (it's not a "x BETWEEN a AND b")
+      
+      Note, however, that if this is an "x IS NULL" condition we don't
+      count it because the number of NULL-values is likely to be off
+      the index statistics we plan to use.
+    */
+    if (!keypart_range->min_flag && !keypart_range->max_flag && // 1)
+        !keypart_range->cmp_max_to_min(keypart_range) &&        // 2)
+        !keypart_range->is_null_interval())                     // "x IS NULL"
+    {
+      /* 
+         Count predicates in the next keypart, but only if that keypart
+         is the next in the index. 
+      */
+      if (keypart_range->next_key_part && 
+          keypart_range->next_key_part->part == keypart_range->part + 1)
+        eq_ranges_exceeds_limit(keypart_range->next_key_part, count, limit);
+      else
+        // We've found a path of equlity predicates down to a keypart leaf
+        (*count)++; 
+
+      if (*count >= limit)
+        return true;
+    }
+  }
+  return false;
+}
+
 #ifndef DBUG_OFF
 
 static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2012-01-02 05:52:38 +0000
+++ b/sql/sql_class.h	2012-01-26 13:09:59 +0000
@@ -455,6 +455,7 @@ typedef struct system_variables
   ha_rows max_join_size;
   ulong auto_increment_increment, auto_increment_offset;
   ulong bulk_insert_buff_size;
+  uint  eq_range_index_dive_limit;
   ulong join_buff_size;
   ulong lock_wait_timeout;
   ulong max_allowed_packet;

=== modified file 'sql/sql_join_buffer.cc'
--- a/sql/sql_join_buffer.cc	2011-12-15 09:00:42 +0000
+++ b/sql/sql_join_buffer.cc	2012-01-26 15:42:39 +0000
@@ -446,27 +446,20 @@ void JOIN_CACHE::set_constants()
 }
 
 
-/* 
-  Allocate memory for a join buffer      
+/**
+  Allocate memory for a join buffer.
 
-  SYNOPSIS
-    alloc_buffer()
+  The function allocates a lump of memory for the join buffer. The
+  size of the allocated memory is 'buff_size' bytes.
 
-  DESCRIPTION
-    The function allocates a lump of memory for the cache join buffer. The
-    size of the allocated memory is 'buff_size' bytes. 
-  
-  RETURN
-    0 - if the memory has been successfully allocated
-    1 - otherwise
+  @returns false if success, otherwise true.
 */
-
-int JOIN_CACHE::alloc_buffer()
+bool JOIN_CACHE::alloc_buffer()
 {
   buff= (uchar*) my_malloc(buff_size, MYF(0));
   return buff == NULL;
-}    	
-  
+}
+
 
 /* 
   Initialize a BNL cache       
@@ -1645,8 +1638,35 @@ void JOIN_CACHE::restore_last_record()
 enum_nested_loop_state JOIN_CACHE::join_records(bool skip_last)
 {
   enum_nested_loop_state rc= NESTED_LOOP_OK;
-  bool outer_join_first_inner= join_tab->is_first_inner_for_outer_join();
   DBUG_ENTER("JOIN_CACHE::join_records");
+
+  table_map saved_status_bits[3]= {0, 0, 0};
+  for (int cnt= 1; cnt <= static_cast<int>(tables); cnt++)
+  {
+    /*
+      We may have hit EOF on previous tables; this has set
+      STATUS_NOT_FOUND in their status. However, now we are going to load
+      table->record[0] from the join buffer so have to declare that there is a
+      record. @See convert_constant_item().
+      We first need to save bits of table->status; STATUS_DELETED and
+      STATUS_UPDATED cannot be on as multi-table DELETE/UPDATE never use join
+      buffering. So we only have three bits to save.
+    */
+    TABLE * const table= join_tab[- cnt].table;
+    const uint8 status= table->status;
+    const table_map map= table->map;
+    DBUG_ASSERT((status & (STATUS_DELETED | STATUS_UPDATED)) == 0);
+    if (status & STATUS_GARBAGE)
+      saved_status_bits[0]|= map;
+    if (status & STATUS_NOT_FOUND)
+      saved_status_bits[1]|= map;
+    if (status & STATUS_NULL_ROW)
+      saved_status_bits[2]|= map;
+    table->status= 0;                           // Record exists.
+  }
+
+  const bool outer_join_first_inner=
+    join_tab->is_first_inner_for_outer_join();
   if (outer_join_first_inner && !join_tab->first_unmatched)
     join_tab->not_null_compl= TRUE;   
 
@@ -1727,6 +1747,23 @@ finish:
          tab <= join_tab->last_inner; tab++)
       tab->first_unmatched= NULL;
   }
+  for (int cnt= 1; cnt <= static_cast<int>(tables); cnt++)
+  {
+    /*
+      We must restore the status of outer tables as it was before entering
+      this function.
+    */
+    TABLE * const table= join_tab[- cnt].table;
+    const table_map map= table->map;
+    uint8 status= 0;
+    if (saved_status_bits[0] & map)
+      status|= STATUS_GARBAGE;
+    if (saved_status_bits[1] & map)
+      status|= STATUS_NOT_FOUND;
+    if (saved_status_bits[2] & map)
+      status|= STATUS_NULL_ROW;
+    table->status= status;
+  }
   restore_last_record();
   reset(true);
   DBUG_RETURN(rc);

=== modified file 'sql/sql_join_buffer.h'
--- a/sql/sql_join_buffer.h	2012-01-11 09:33:52 +0000
+++ b/sql/sql_join_buffer.h	2012-01-19 09:57:18 +0000
@@ -277,7 +277,7 @@ protected:
   void create_flag_fields();
   void create_remaining_fields(bool all_read_fields);
   void set_constants();
-  int alloc_buffer();
+  bool alloc_buffer();
 
   uint get_size_of_rec_offset() { return size_of_rec_ofs; }
   uint get_size_of_rec_length() { return size_of_rec_len; }

=== modified file 'sql/sql_optimizer.cc'
--- a/sql/sql_optimizer.cc	2012-01-17 15:43:31 +0000
+++ b/sql/sql_optimizer.cc	2012-01-27 14:22:35 +0000
@@ -362,8 +362,6 @@ JOIN::optimize()
     DBUG_RETURN(1);
   }
 
-  drop_unused_derived_keys();
-
   if (rollup.state != ROLLUP::STATE_NONE)
   {
     if (rollup_process_const_fields())
@@ -378,12 +376,6 @@ JOIN::optimize()
     select_distinct= select_distinct && (const_tables != tables);
   }
 
-  THD_STAGE_INFO(thd, stage_preparing);
-  if (result->initialize_tables(this))
-  {
-    DBUG_PRINT("error",("Error: initialize_tables() failed"));
-    DBUG_RETURN(1);				// error == -1
-  }
   if (const_table_map != found_const_table_map &&
       !(select_options & SELECT_DESCRIBE) &&
       (!conds ||
@@ -438,8 +430,7 @@ JOIN::optimize()
   }
 
   /*
-    Permorm the the optimization on fields evaluation mentioned above
-    for all on expressions.
+    Perform the same optimization on field evaluation for all join conditions.
   */ 
   for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables ; tab++)
   {
@@ -464,6 +455,26 @@ JOIN::optimize()
     conds=new Item_int((longlong) 0,1);	// Always false
   }
 
+  if (set_access_methods())
+  {
+    error= 1;
+    DBUG_PRINT("error",("Error from set_access_methods"));
+    DBUG_RETURN(1);
+  }
+
+  // We need all derived keys until access methods have been set.
+  drop_unused_derived_keys();
+
+  // Update table dependencies after assigning ref access fields
+  update_depend_map(this);
+
+  THD_STAGE_INFO(thd, stage_preparing);
+  if (result->initialize_tables(this))
+  {
+    DBUG_PRINT("error",("Error: initialize_tables() failed"));
+    DBUG_RETURN(1);				// error == -1
+  }
+
   if (make_join_select(this, conds))
   {
     zero_result_cause=
@@ -984,7 +995,33 @@ finish:
   return item;
 }
 
-  
+
+/**
+  Get the best field substitution for a given field.
+
+  If the field is member of a multiple equality, look up that equality
+  and return the most appropriate field. Usually this is the equivalenced
+  field belonging to the outer-most table in the join order, but
+  @see Item_field::get_subst_item() for details.
+  Otherwise, return the same field.
+
+  @param item_field The field that we are seeking a substitution for.
+  @param cond_equal multiple equalities to search in
+
+  @return The substituted field.
+*/
+
+Item_field *get_best_field(Item_field *item_field, COND_EQUAL *cond_equal)
+{
+  bool dummy;
+  Item_equal *item_eq= find_item_equal(cond_equal, item_field->field, &dummy);
+  if (!item_eq)
+    return item_field;
+
+  return item_eq->get_subst_item(item_field);
+}
+
+
 /**
   Check whether an equality can be used to build multiple equalities.
 
@@ -2593,8 +2630,8 @@ void update_depend_map(JOIN *join)
     uint i;
     for (i=0 ; i < ref->key_parts ; i++,item++)
       depend_map|=(*item)->used_tables();
-    ref->depend_map=depend_map & ~OUTER_REF_TABLE_BIT;
-    depend_map&= ~OUTER_REF_TABLE_BIT;
+    depend_map&= ~PSEUDO_TABLE_BITS;
+    ref->depend_map= depend_map;
     for (JOIN_TAB **tab=join->map2table;
 	 depend_map ;
 	 tab++,depend_map>>=1 )
@@ -3028,7 +3065,7 @@ const_table_extraction_done:
           Mark a dependent table as constant if
            1. it has exactly zero or one rows (it is a system table), and
            2. it is not within a nested outer join, and
-           3. it does not have an expensive join condition.
+           3. it does not have an expensive outer join condition.
               This is because we have to determine whether an outer-joined table
               has a real row or a null-extended row in the optimizer phase.
               We have no possibility to evaluate its join condition at
@@ -3084,12 +3121,15 @@ const_table_extraction_done:
             Exclude tables that
              1. are full-text searched, or
              2. are part of nested outer join, or
-             3. are part of semi-join
+             3. are part of semi-join, or
+             4. have an expensive outer join condition.
+                DontEvaluateMaterializedSubqueryTooEarly
           */
 	  if (eq_part.is_prefix(table->key_info[key].key_parts) &&
               !table->fulltext_searched &&                           // 1
               !tl->in_outer_join_nest() &&                           // 2
-              !(tl->embedding && tl->embedding->sj_on_expr))         // 3
+              !(tl->embedding && tl->embedding->sj_on_expr) &&       // 3
+              !(*s->on_expr_ref && (*s->on_expr_ref)->is_expensive())) // 4
 	  {
             if (table->key_info[key].flags & HA_NOSAME)
             {

=== modified file 'sql/sql_optimizer.h'
--- a/sql/sql_optimizer.h	2011-12-15 09:00:42 +0000
+++ b/sql/sql_optimizer.h	2012-01-20 15:30:14 +0000
@@ -509,6 +509,7 @@ Item *remove_eq_conds(THD *thd, Item *co
 bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
 Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
                             bool *inherited_fl);
+Item_field *get_best_field(Item_field *item_field, COND_EQUAL *cond_equal);
 Item *
 make_cond_for_table(Item *cond, table_map tables, table_map used_table,
                     bool exclude_expensive_cond);

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2012-01-25 14:52:00 +0000
+++ b/sql/sql_select.cc	2012-01-30 10:34:28 +0000
@@ -1224,11 +1224,6 @@ bool JOIN::get_best_combination()
 
   set_semijoin_info();
 
-  if (set_access_methods())
-    DBUG_RETURN(true);
-
-  update_depend_map(this);
-
   DBUG_RETURN(false);
 }
 
@@ -1242,6 +1237,11 @@ bool JOIN::get_best_combination()
      - There is no key selected (use JT_ALL)
      - Loose scan semi-join strategy is selected (use JT_ALL)
      - A ref key can be used (use JT_REF, JT_REF_OR_NULL, JT_EQ_REF or JT_FT)
+
+  @note We cannot setup fields used for ref access before we have sorted
+        the items within multiple equalities according to the final order of
+        the tables involved in the join operation. Currently, this occurs in
+        @see substitute_for_best_equal_field().
 */
 bool JOIN::set_access_methods()
 {
@@ -1360,8 +1360,14 @@ void JOIN::set_semijoin_info()
   @details
     This function will set up a ref access using the best key found
     during access path analysis and cost analysis.
-*/
 
+  @note We cannot setup fields used for ref access before we have sorted
+        the items within multiple equalities according to the final order of
+        the tables involved in the join operation. Currently, this occurs in
+        @see substitute_for_best_equal_field().
+        The exception is ref access for const tables, which are fixed
+        before the greedy search planner is invoked.  
+*/
 
 bool create_ref_for_key(JOIN *join, JOIN_TAB *j, Key_use *org_keyuse,
                         table_map used_tables)
@@ -1452,6 +1458,14 @@ bool create_ref_for_key(JOIN *join, JOIN
         keyuse++;                               // Skip other parts
 
       uint maybe_null= test(keyinfo->key_part[part_no].null_bit);
+
+      if (keyuse->val->type() == Item::FIELD_ITEM)
+      {
+        // Look up the most appropriate field to base the ref access on.
+        keyuse->val= get_best_field(static_cast<Item_field *>(keyuse->val),
+                                    join->cond_equal);
+        keyuse->used_tables= keyuse->val->used_tables();
+      }
       j->ref.items[part_no]=keyuse->val;        // Save for cond removal
       j->ref.cond_guards[part_no]= keyuse->cond_guard;
       if (keyuse->null_rejecting) 
@@ -2579,14 +2593,11 @@ bool setup_sj_materialization(JOIN_TAB *
     it.rewind();
     for (uint i=0; i < sjm->table_cols.elements; i++)
     {
-      bool dummy;
-      Item_equal *item_eq;
       Item *item= (it++)->real_item();
       DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
-      Field *copy_to= ((Item_field*)item)->field;
       /*
-        Tricks with Item_equal are due to the following: suppose we have a
-        query:
+        The trick with get_best_field() is due to the following;
+        suppose we have a query:
         
         ... WHERE cond(ot.col) AND ot.col IN (SELECT it2.col FROM it1,it2
                                                WHERE it1.col= it2.col)
@@ -2609,21 +2620,8 @@ bool setup_sj_materialization(JOIN_TAB *
          element equality propagation member that refers to table that is
          within the subquery.
       */
-      item_eq= find_item_equal(tab->join->cond_equal, copy_to, &dummy);
-
-      if (item_eq)
-      {
-        List_iterator<Item_field> it(item_eq->fields);
-        Item_field *item;
-        while ((item= it++))
-        {
-          if (!(item->used_tables() & ~emb_sj_nest->sj_inner_tables))
-          {
-            copy_to= item->field;
-            break;
-          }
-        }
-      }
+      Field *copy_to= get_best_field(static_cast<Item_field *>(item),
+                                     tab->join->cond_equal)->field;
       sjm->copy_field[i].set(copy_to, sjm->table->field[i], FALSE);
       /* The write_set for source tables must be set up to allow the copying */
       bitmap_set_bit(copy_to->table->write_set, copy_to->field_index);
@@ -2634,8 +2632,6 @@ bool setup_sj_materialization(JOIN_TAB *
 }
 
 
-
-
 /**
   Plan refinement stage: do various setup things for the executor
 

=== modified file 'sql/structs.h'
--- a/sql/structs.h	2011-07-21 12:54:54 +0000
+++ b/sql/structs.h	2012-01-19 09:57:18 +0000
@@ -233,7 +233,13 @@ typedef struct  user_conn {
 #define REG_OVERWRITE		128
 #define REG_SKIP_DUP		256
 
-	/* Bits in form->status */
+/**
+  Flags for TABLE::status (maximum 8 bits). Do NOT add new ones.
+  @todo: GARBAGE and NOT_FOUND could be unified. UPDATED and DELETED could be
+  changed to "bool current_row_has_already_been_modified" in the
+  multi_update/delete objects (one such bool per to-be-modified table).
+  @todo aim at removing the status. There should be more local ways.
+*/
 #define STATUS_GARBAGE          1
 /**
    Means we were searching for a row and didn't find it. This is used by

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2012-01-25 10:07:23 +0000
+++ b/sql/sys_vars.cc	2012-01-30 10:34:28 +0000
@@ -2110,6 +2110,14 @@ static Sys_var_ulong Sys_div_precincreme
        SESSION_VAR(div_precincrement), CMD_LINE(REQUIRED_ARG),
        VALID_RANGE(0, DECIMAL_MAX_SCALE), DEFAULT(4), BLOCK_SIZE(1));
 
+static Sys_var_uint Sys_eq_range_index_dive_limit(
+       "eq_range_index_dive_limit",
+       "The optimizer will use existing index statistics instead of "
+       "doing index dives for equality ranges if the number of equality "
+       "ranges is larger than or equal to this number.",
+       SESSION_VAR(eq_range_index_dive_limit), CMD_LINE(REQUIRED_ARG),
+       VALID_RANGE(0, UINT_MAX32), DEFAULT(10), BLOCK_SIZE(1));
+
 static Sys_var_ulong Sys_range_alloc_block_size(
        "range_alloc_block_size",
        "Allocation block size for storing ranges during optimization",

=== modified file 'sql/table.h'
--- a/sql/table.h	2012-01-18 13:03:10 +0000
+++ b/sql/table.h	2012-01-26 15:42:39 +0000
@@ -337,7 +337,7 @@ public:
   uchar **alloc_sort_buffer(uint num_records, uint record_length)
   { return filesort_buffer.alloc_sort_buffer(num_records, record_length); }
 
-  std::pair<uint, uint> sort_buffer_properties()
+  std::pair<uint, uint> sort_buffer_properties() const
   { return filesort_buffer.sort_buffer_properties(); }
 
   void free_sort_buffer()
@@ -1086,12 +1086,10 @@ public:
   uint          lock_count;             /* Number of locks */
   uint		tablenr,used_fields;
   uint          temp_pool_slot;		/* Used by intern temp tables */
-  uint		status;                 /* What's in record[0] */
   uint		db_stat;		/* mode of file as in handler.h */
   /* number of select if it is derived table */
   uint          derived_select_number;
   int		current_lock;           /* Type of lock on table */
-  my_bool copy_blobs;			/* copy_blobs when storing */
 
   /*
     0 or JOIN_TYPE_{LEFT|RIGHT}. Currently this is only compared to 0.
@@ -1105,6 +1103,9 @@ public:
   */
   my_bool null_row;
 
+  uint8   status;                       /* What's in record[0] */
+  my_bool copy_blobs;                   /* copy_blobs when storing */
+
   /*
     TODO: Each of the following flags take up 8 bits. They can just as easily
     be put into one single unsigned long and instead of taking up 18

=== modified file 'unittest/gunit/filesort_buffer-t.cc'
--- a/unittest/gunit/filesort_buffer-t.cc	2012-01-18 13:03:10 +0000
+++ b/unittest/gunit/filesort_buffer-t.cc	2012-01-18 14:42:16 +0000
@@ -29,6 +29,10 @@ protected:
   virtual void TearDown()
   {
     fs_info.free_sort_buffer();
+    std::pair<uint, uint> buffer_properties= fs_info.sort_buffer_properties();
+    EXPECT_EQ(0U, buffer_properties.first);
+    EXPECT_EQ(0U, buffer_properties.second);
+    EXPECT_TRUE(NULL == fs_info.get_sort_keys());
   }
 
   Filesort_info fs_info;
@@ -49,6 +53,7 @@ TEST_F(FileSortBufferTest, FileSortBuffe
 
   uchar **null_sort_keys= NULL;
   EXPECT_NE(null_sort_keys, sort_keys);
+  EXPECT_NE(null_sort_keys, fs_info.get_sort_keys());
   for (uint ix= 0; ix < 10; ++ix)
   {
     uchar *ptr= fs_info.get_record_buffer(ix);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (tor.didriksen:3803 to 3804) Tor Didriksen30 Jan