[Commits] 9380850: MDEV-15777 Use inferred IS NOT NULL predicates in the range optimizer
by IgorBabaev 31 Aug '19
by IgorBabaev 31 Aug '19
31 Aug '19
revision-id: 9380850d874c77656d0c42cfa11bf0d187064849 (mariadb-10.4.4-307-g9380850)
parent(s): fac81c67527605710e1cc76db6df4b8fce34b06b
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-08-30 18:47:14 -0700
message:
MDEV-15777 Use inferred IS NOT NULL predicates in the range optimizer
This patch introduces the optimization that allows range optimizer to
consider index range scans that are built employing NOT NULL predicates
inferred from WHERE conditions and ON expressions.
The patch adds a new optimizer switch not_null_range_scan.
---
mysql-test/main/mysqld--help.result | 2 +-
mysql-test/main/range.result | 293 +++++++++++++++++++++
mysql-test/main/range.test | 184 ++++++++++++-
mysql-test/main/range_mrr_icp.result | 293 +++++++++++++++++++++
.../suite/sys_vars/r/optimizer_switch_basic.result | 36 +--
.../sys_vars/r/sysvars_server_embedded.result | 5 +
.../sys_vars/r/sysvars_server_notembedded.result | 8 +-
sql/item.cc | 10 +
sql/item.h | 43 +++
sql/item_cmpfunc.cc | 161 ++++++++++-
sql/item_cmpfunc.h | 11 +
sql/item_func.cc | 19 ++
sql/item_func.h | 22 ++
sql/item_row.cc | 19 ++
sql/item_row.h | 1 +
sql/opt_range.cc | 10 +
sql/sql_priv.h | 1 +
sql/sql_select.cc | 284 ++++++++++++++++++++
sql/sql_select.h | 1 +
sql/sys_vars.cc | 1 +
sql/table.cc | 2 +
sql/table.h | 7 +
.../mysql-test/tokudb/r/ext_key_1_innodb.result | 112 --------
.../mysql-test/tokudb/r/ext_key_1_tokudb.result | 112 --------
.../mysql-test/tokudb/r/ext_key_2_innodb.result | 43 ---
.../mysql-test/tokudb/r/ext_key_2_tokudb.result | 43 ---
26 files changed, 1388 insertions(+), 335 deletions(-)
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index 3f15567..056614b 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -710,7 +710,7 @@ The following specify which files/extra groups are read (specified before remain
extended_keys, exists_to_in, orderby_uses_equalities,
condition_pushdown_for_derived, split_materialized,
condition_pushdown_for_subquery, rowid_filter,
- condition_pushdown_from_having
+ condition_pushdown_from_having, not_null_range_scan
--optimizer-trace=name
Controls tracing of the Optimizer:
optimizer_trace=option=val[,option=val...], where option
diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result
index fe0e3ef..ae0a788 100644
--- a/mysql-test/main/range.result
+++ b/mysql-test/main/range.result
@@ -3122,6 +3122,299 @@ drop table t1,ten,t2;
#
# End of 10.2 tests
#
+#
+# MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+#
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+PRIMARY KEY (id),
+KEY t1_subset_id (subset_id));
+create table t2 (
+id int,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status Table is already up to date
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# with a subquery
+# expected the same plan as above
+explain SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition
+1 PRIMARY t2 ref id id 5 test.t1.subset_id 1 Using index; FirstMatch(t1)
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+# non-mergable subquery
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.subset_id 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1000 Using temporary
+SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+# with mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using index
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# with non-mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition
+1 PRIMARY <derived2> ref key0 key0 5 test.t1.subset_id 10
+2 DERIVED t2 ALL NULL NULL NULL NULL 1000 Using temporary; Using filesort
+SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# expected for t2 and for t1: range access
+explain SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range id id 5 NULL 3 Using index condition
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id col id subset_id
+0 0 0 0
+2 2 0 0
+4 4 0 0
+0 0 1 1
+2 2 1 1
+4 4 1 1
+0 0 2 2
+2 2 2 2
+4 4 2 2
+0 0 3 3
+2 2 3 3
+4 4 3 3
+0 0 4 4
+2 2 4 4
+4 4 4 4
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+5 NULL NULL NULL
+6 NULL NULL NULL
+7 NULL NULL NULL
+8 NULL NULL NULL
+9 NULL NULL NULL
+# expected for t1: range access
+explain SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE ten ALL NULL NULL NULL NULL 10
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 3 Using where
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+a id subset_id id col
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+1 SIMPLE ten ALL NULL NULL NULL NULL 10 Using where
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id subset_id id col a
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+drop index id on t2;
+# expected for t1: range access
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id subset_id id col
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id subset_id id col
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status Table is already up to date
+# expected for t1: range access by idx (keylen=9)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx idx 9 NULL 4 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id subset_id m id col
+0 0 0 0 0
+2 2 0 2 2
+4 4 0 4 4
+drop view v1,v2;
+drop table t1,t2;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+KEY key1(id, subset_id),
+KEY t1_subset_id (subset_id)
+);
+create table t2 (
+id int NOT NULL,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status Table is already up to date
+# expected for t1 :range access by index key1
+# rows 4 instead of 500
+explain SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1,t1_subset_id key1 9 NULL 3 Using where; Using index
+1 SIMPLE t2 ref id id 4 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id subset_id id col
+1 0 0 0
+1 1 1 1
+1 2 2 2
+1 3 3 3
+1 4 4 4
+drop table t1,t2;
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+# using key1 for range access on t1 and also using index for sorting,
+# no filesort, rows should be 75 not 500
+explain SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1 key1 5 NULL 74 Using index condition; Using where
+1 SIMPLE t2 ref id id 5 test.t1.id 2
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id col id col
+0 2 0 0
+0 2 0 0
+1 2 1 1
+1 2 1 1
+2 2 2 2
+2 2 2 2
+3 2 3 3
+3 2 3 3
+4 2 4 4
+4 2 4 4
+drop table t1,t2;
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+#
+# End of 10.5 tests
+#
set global innodb_stats_persistent= @innodb_stats_persistent_save;
set global innodb_stats_persistent_sample_pages=
@innodb_stats_persistent_sample_pages_save;
diff --git a/mysql-test/main/range.test b/mysql-test/main/range.test
index 76d893f..c064b7a 100644
--- a/mysql-test/main/range.test
+++ b/mysql-test/main/range.test
@@ -2101,6 +2101,188 @@ drop table t1,ten,t2;
--echo # End of 10.2 tests
--echo #
+--echo #
+--echo # MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+--echo #
+
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+
+create table t1 (
+ id int NOT NULL,
+ subset_id int DEFAULT NULL,
+ PRIMARY KEY (id),
+ KEY t1_subset_id (subset_id));
+
+create table t2 (
+ id int,
+ col int NOT NULL,
+ key (id)
+);
+
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+--echo # with a subquery
+--echo # expected the same plan as above
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1
+ WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+--echo # non-mergable subquery
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+
+let $q=
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+--echo # with mergeable view
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q= SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+--echo # with non-mergeable view
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+--echo # expected for t2 and for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+--echo # no range access expected for t1
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+--echo # expected for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+--echo # no range access expected for t1
+eval explain $q;
+eval $q;
+
+drop index id on t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+--echo # expected for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+--echo # expected impossible where after reading const tables
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+--echo # expected impossible where after reading const tables
+eval explain $q;
+eval $q;
+
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+--echo # expected for t1: range access by idx (keylen=9)
+eval explain $q;
+eval $q;
+
+
+drop view v1,v2;
+drop table t1,t2;
+
+create table t1 (
+ id int NOT NULL,
+ subset_id int DEFAULT NULL,
+ KEY key1(id, subset_id),
+ KEY t1_subset_id (subset_id)
+);
+
+create table t2 (
+ id int NOT NULL,
+ col int NOT NULL,
+ key (id)
+);
+
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+--echo # expected for t1 :range access by index key1
+--echo # rows 4 instead of 500
+eval explain $q;
+eval $q;
+
+drop table t1,t2;
+
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+--echo # using key1 for range access on t1 and also using index for sorting,
+--echo # no filesort, rows should be 75 not 500
+eval explain $q;
+eval $q;
+
+drop table t1,t2;
+
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+
+--echo #
+--echo # End of 10.5 tests
+--echo #
+
set global innodb_stats_persistent= @innodb_stats_persistent_save;
set global innodb_stats_persistent_sample_pages=
- @innodb_stats_persistent_sample_pages_save;
+ @innodb_stats_persistent_sample_pages_save;
diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result
index fbcee92..f0a9798 100644
--- a/mysql-test/main/range_mrr_icp.result
+++ b/mysql-test/main/range_mrr_icp.result
@@ -3119,6 +3119,299 @@ drop table t1,ten,t2;
#
# End of 10.2 tests
#
+#
+# MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+#
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+PRIMARY KEY (id),
+KEY t1_subset_id (subset_id));
+create table t2 (
+id int,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status Table is already up to date
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# with a subquery
+# expected the same plan as above
+explain SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 PRIMARY t2 ref id id 5 test.t1.subset_id 1 Using index; FirstMatch(t1)
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+# non-mergable subquery
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.subset_id 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1000 Using temporary
+SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+# with mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using index
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# with non-mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 PRIMARY <derived2> ref key0 key0 5 test.t1.subset_id 10
+2 DERIVED t2 ALL NULL NULL NULL NULL 1000 Using temporary; Using filesort
+SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# expected for t2 and for t1: range access
+explain SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range id id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where; Rowid-ordered scan; Using join buffer (flat, BNL join)
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id col id subset_id
+0 0 0 0
+2 2 0 0
+4 4 0 0
+0 0 1 1
+2 2 1 1
+4 4 1 1
+0 0 2 2
+2 2 2 2
+4 4 2 2
+0 0 3 3
+2 2 3 3
+4 4 3 3
+0 0 4 4
+2 2 4 4
+4 4 4 4
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+5 NULL NULL NULL
+6 NULL NULL NULL
+7 NULL NULL NULL
+8 NULL NULL NULL
+9 NULL NULL NULL
+# expected for t1: range access
+explain SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE ten ALL NULL NULL NULL NULL 10
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 3 Using where; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+a id subset_id id col
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+1 SIMPLE ten ALL NULL NULL NULL NULL 10 Using where
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id subset_id id col a
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+drop index id on t2;
+# expected for t1: range access
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id subset_id id col
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id subset_id id col
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status Table is already up to date
+# expected for t1: range access by idx (keylen=9)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx idx 9 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id subset_id m id col
+0 0 0 0 0
+2 2 0 2 2
+4 4 0 4 4
+drop view v1,v2;
+drop table t1,t2;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+KEY key1(id, subset_id),
+KEY t1_subset_id (subset_id)
+);
+create table t2 (
+id int NOT NULL,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status Table is already up to date
+# expected for t1 :range access by index key1
+# rows 4 instead of 500
+explain SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1,t1_subset_id key1 9 NULL 3 Using where; Using index
+1 SIMPLE t2 ref id id 4 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id subset_id id col
+1 0 0 0
+1 1 1 1
+1 2 2 2
+1 3 3 3
+1 4 4 4
+drop table t1,t2;
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
+test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze status OK
+# using key1 for range access on t1 and also using index for sorting,
+# no filesort, rows should be 75 not 500
+explain SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1 key1 5 NULL 74 Using index condition; Using where
+1 SIMPLE t2 ref id id 5 test.t1.id 2
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id col id col
+0 2 0 0
+0 2 0 0
+1 2 1 1
+1 2 1 1
+2 2 2 2
+2 2 2 2
+3 2 3 3
+3 2 3 3
+4 2 4 4
+4 2 4 4
+drop table t1,t2;
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+#
+# End of 10.5 tests
+#
set global innodb_stats_persistent= @innodb_stats_persistent_save;
set global innodb_stats_persistent_sample_pages=
@innodb_stats_persistent_sample_pages_save;
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
index 74f4fd1..58daf41 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
@@ -1,63 +1,63 @@
SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value;
@start_global_value
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
set global optimizer_switch=10;
set session optimizer_switch=5;
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
set global optimizer_switch="index_merge_sort_union=on";
set session optimizer_switch="index_merge=off";
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
set session optimizer_switch="default";
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off,not_null_range_scan=off
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
Warnings:
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=on
set global optimizer_switch=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
set global optimizer_switch=1e1;
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
index 5f77bd9..93eae92 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
@@ -2791,6 +2791,10 @@ SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,inde
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
@@ -2826,6 +2830,7 @@ NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 18446744073709551615
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,not_null_range_scan,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 524cc4c..8a32eea 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -3011,17 +3011,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having,not_null_range_scan,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_TRACE
diff --git a/sql/item.cc b/sql/item.cc
index 162e82c..98bc56c 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3336,6 +3336,16 @@ table_map Item_field::all_used_tables() const
}
+bool Item_field::find_not_null_fields(table_map allowed)
+{
+ if (field->table->const_table)
+ return false;
+ if (!get_depended_from() && field->real_maybe_null())
+ bitmap_set_bit(&field->table->tmp_set, field->field_index);
+ return false;
+}
+
+
/*
@Note thd->fatal_error can be set in case of OOM
*/
diff --git a/sql/item.h b/sql/item.h
index d220f17..6e1f1e3 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2011,6 +2011,44 @@ class Item: public Value_source,
virtual bool check_index_dependence(void *arg) { return 0; }
/*============== End of Item processor list ======================*/
+ /*
+ Given a condition P from the WHERE clause or from an ON expression of
+ the processed SELECT S and a set of join tables from S marked in the
+ parameter 'allowed'={T} a call of P->find_not_null_fields({T}) has to
+ find the set fields {F} of the tables from 'allowed' such that:
+ - each field from {F} is declared as nullable
+ - each record of table t from {T} that contains NULL as the value for at
+ at least one field from {F} can be ignored when building the result set
+ for S
+ It is assumed here that the condition P is conjunctive and all its column
+ references belong to T.
+
+ Examples:
+ CREATE TABLE t1 (a int, b int);
+ CREATE TABLE t2 (a int, b int);
+
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b > 5;
+ A call of find_not_null_fields() for the whole WHERE condition and {t1,t2}
+ should find {t1.a,t1.b,t2.a}
+
+ SELECT * FROM t1 LEFT JOIN ON (t1.a=t2.a and t2.a > t2.b);
+ A call of find_not_null_fields() for the ON expression and {t2}
+ should find {t2.a,t2.b}
+
+ The function returns TRUE if it succeeds to prove that all records of
+ a table from {T} can be ignored. Otherwise it always returns FALSE.
+
+ Example:
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t2.a IS NULL;
+ A call of find_not_null_fields() for the WHERE condition and {t1,t2}
+ will return TRUE.
+
+ It is assumed that the implementation of this virtual function saves
+ the info on the found set of fields in the structures associates with
+ tables from {T}.
+ */
+ virtual bool find_not_null_fields(table_map allowed) { return false; }
+
virtual Item *get_copy(THD *thd)=0;
bool cache_const_expr_analyzer(uchar **arg);
@@ -3356,6 +3394,7 @@ class Item_field :public Item_ident,
bool is_result_field() { return false; }
void save_in_result_field(bool no_conversions);
Item *get_tmp_table_item(THD *thd);
+ bool find_not_null_fields(table_map allowed);
bool collect_item_field_processor(void * arg);
bool add_field_to_set_processor(void * arg);
bool find_item_in_field_list_processor(void *arg);
@@ -5151,6 +5190,10 @@ class Item_ref :public Item_ident,
{
return depended_from ? 0 : (*ref)->not_null_tables();
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return depended_from ? false : (*ref)->find_not_null_fields(allowed);
+ }
void save_in_result_field(bool no_conversions)
{
(*ref)->save_in_field(result_field, no_conversions);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 24ffaea..4f950c0 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1215,6 +1215,15 @@ bool Item_in_optimizer::eval_not_null_tables(void *opt_arg)
}
+bool Item_in_optimizer::find_not_null_fields(table_map allowed)
+{
+ if (!(~allowed & used_tables()) && is_top_level_item())
+ {
+ return args[0]->find_not_null_fields(allowed);
+ }
+ return false;
+}
+
void Item_in_optimizer::print(String *str, enum_query_type query_type)
{
if (query_type & QT_PARSABLE)
@@ -2061,7 +2070,17 @@ bool Item_func_between::eval_not_null_tables(void *opt_arg)
(args[1]->not_null_tables() &
args[2]->not_null_tables()));
return 0;
-}
+}
+
+
+bool Item_func_between::find_not_null_fields(table_map allowed)
+{
+ if (negated || !is_top_level_item() || (~allowed & used_tables()))
+ return false;
+ return args[0]->find_not_null_fields(allowed) ||
+ args[1]->find_not_null_fields(allowed) ||
+ args[3]->find_not_null_fields(allowed);
+}
bool Item_func_between::count_sargable_conds(void *arg)
@@ -4327,6 +4346,15 @@ Item_func_in::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_func_in::find_not_null_fields(table_map allowed)
+{
+ if (negated || !is_top_level_item() || (~allowed & used_tables()))
+ return 0;
+ return args[0]->find_not_null_fields(allowed);
+}
+
+
void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
@@ -4930,6 +4958,82 @@ Item_cond::eval_not_null_tables(void *opt_arg)
}
+/**
+ @note
+ This implementation of the virtual function find_not_null_fields()
+ infers null-rejectedness if fields from tables marked in 'allowed' from
+ this condition.
+ Currently only top level AND conjuncts that are not disjunctions are used
+ for the inference. Usage of any top level and-or formula with l OR levels
+ would require a stack of bitmaps for fields of the height h=2*l+1 So we
+ would have to allocate h-1 additional field bitmaps for each table marked
+ in 'allowed'.
+*/
+
+bool
+Item_cond::find_not_null_fields(table_map allowed)
+{
+ Item *item;
+ bool is_and_cond= functype() == Item_func::COND_AND_FUNC;
+ if (!is_and_cond)
+ {
+ /* Now only fields of top AND level conjuncts are taken into account */
+ return false;
+ }
+ uint isnull_func_cnt= 0;
+ List_iterator<Item> li(list);
+ while ((item=li++))
+ {
+ bool is_mult_eq= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::MULT_EQUAL_FUNC;
+ if (is_mult_eq)
+ {
+ if (!item->find_not_null_fields(allowed))
+ continue;
+ }
+
+ if (~allowed & item->used_tables())
+ continue;
+
+ /* It is assumed that all constant conjuncts are already eliminated */
+
+ /*
+ First infer null-rejectedness of fields from all conjuncts but
+ IS NULL predicates
+ */
+ bool isnull_func= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::ISNULL_FUNC;
+ if (isnull_func)
+ {
+ isnull_func_cnt++;
+ continue;
+ }
+ if (!item->find_not_null_fields(allowed))
+ continue;
+ }
+
+ /* Now try no get contradictions using IS NULL conjuncts */
+ if (isnull_func_cnt)
+ {
+ li.rewind();
+ while ((item=li++) && isnull_func_cnt)
+ {
+ if (~allowed & item->used_tables())
+ continue;
+
+ bool isnull_func= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::ISNULL_FUNC;
+ if (isnull_func)
+ {
+ if (item->find_not_null_fields(allowed))
+ return true;
+ isnull_func_cnt--;
+ }
+ }
+ }
+ return false;
+}
+
void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
@@ -5375,6 +5479,19 @@ longlong Item_func_isnull::val_int()
}
+bool Item_func_isnull::find_not_null_fields(table_map allowed)
+{
+ if (!(~allowed & used_tables()) &&
+ args[0]->real_item()->type() == Item::FIELD_ITEM)
+ {
+ Field *field= ((Item_field *)(args[0]->real_item()))->field;
+ if (bitmap_is_set(&field->table->tmp_set, field->field_index))
+ return true;
+ }
+ return false;
+}
+
+
void Item_func_isnull::print(String *str, enum_query_type query_type)
{
if (const_item() && !args[0]->maybe_null &&
@@ -6938,6 +7055,48 @@ void Item_equal::update_used_tables()
}
+/**
+ @note
+ This multiple equality can contains elements belonging not to tables {T}
+ marked in 'allowed' . So we can ascertain null-rejectedness of field f
+ belonging to table t from {T} only if one of the following equality
+ predicate can be extracted from this multiple equality:
+ - f=const
+ - f=f' where f' is a field of some table from {T}
+*/
+
+bool Item_equal::find_not_null_fields(table_map allowed)
+{
+ if (!(allowed & used_tables()))
+ return false;
+ bool checked= false;
+ Item_equal_fields_iterator it(*this);
+ Item *item;
+ while ((item= it++))
+ {
+ if (~allowed & item->used_tables())
+ continue;
+ if ((with_const || checked) && !item->find_not_null_fields(allowed))
+ continue;
+ Item_equal_fields_iterator it1(*this);
+ Item *item1;
+ while ((item1= it1++) && item1 != item)
+ {
+ if (~allowed & item1->used_tables())
+ continue;
+ if (!item->find_not_null_fields(allowed) &&
+ !item1->find_not_null_fields(allowed))
+ {
+ checked= true;
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+
+
bool Item_equal::count_sargable_conds(void *arg)
{
SELECT_LEX *sel= (SELECT_LEX *) arg;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 0e9b573..c9f4d73 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -289,6 +289,7 @@ class Item_func_isnottrue : public Item_func_truth
Item_func_truth(thd, a, true, false) {}
~Item_func_isnottrue() {}
virtual const char* func_name() const { return "isnottrue"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnottrue>(thd, this); }
bool eval_not_null_tables(void *) { not_null_tables_cache= 0; return false; }
@@ -321,6 +322,7 @@ class Item_func_isnotfalse : public Item_func_truth
Item_func_truth(thd, a, false, false) {}
~Item_func_isnotfalse() {}
virtual const char* func_name() const { return "isnotfalse"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnotfalse>(thd, this); }
bool eval_not_null_tables(void *) { not_null_tables_cache= 0; return false; }
@@ -383,6 +385,7 @@ class Item_in_optimizer: public Item_bool_func
virtual void get_cache_parameters(List<Item> ¶meters);
bool is_top_level_item();
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool invisible_mode();
void reset_cache() { cache= NULL; }
@@ -578,6 +581,7 @@ class Item_func_xor :public Item_bool_func
void print(String *str, enum_query_type query_type)
{ Item_func::print_op(str, query_type); }
longlong val_int();
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *neg_transformer(THD *thd);
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
@@ -599,6 +603,7 @@ class Item_func_not :public Item_bool_func
longlong val_int();
enum Functype functype() const { return NOT_FUNC; }
const char *func_name() const { return "not"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
enum precedence precedence() const { return BANG_PRECEDENCE; }
Item *neg_transformer(THD *thd);
bool fix_fields(THD *, Item **);
@@ -743,6 +748,7 @@ class Item_func_equal :public Item_bool_rowready_func2
longlong val_int();
bool fix_length_and_dec();
table_map not_null_tables() const { return 0; }
+ bool find_not_null_fields(table_map allowed) { return false; }
enum Functype functype() const { return EQUAL_FUNC; }
enum Functype rev_functype() const { return EQUAL_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
@@ -920,6 +926,7 @@ class Item_func_between :public Item_func_opt_neg
bool fix_length_and_dec_numeric(THD *);
virtual void print(String *str, enum_query_type query_type);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg);
void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
@@ -2445,6 +2452,7 @@ class Item_func_in :public Item_func_opt_neg,
const char *func_name() const { return "in"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg);
Item *get_copy(THD *thd)
@@ -2588,6 +2596,7 @@ class Item_func_isnull :public Item_func_null_predicate
COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
bool top_level);
table_map not_null_tables() const { return 0; }
+ bool find_not_null_fields(table_map allowed);
Item *neg_transformer(THD *thd);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnull>(thd, this); }
@@ -3009,6 +3018,7 @@ class Item_cond :public Item_bool_func
Item *compile(THD *thd, Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
Item *build_clone(THD *thd);
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
@@ -3174,6 +3184,7 @@ class Item_equal: public Item_bool_func
eval_item= NULL;
}
void update_used_tables();
+ bool find_not_null_fields(table_map allowed);
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
bool link_item_fields,
COND_EQUAL **cond_equal_ref);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 913442e..af908d9 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -404,6 +404,25 @@ Item_func::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_func::find_not_null_fields(table_map allowed)
+{
+ if (~allowed & used_tables())
+ return false;
+
+ Item **arg,**arg_end;
+ if (arg_count)
+ {
+ for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
+ {
+ if (!(*arg)->find_not_null_fields(allowed))
+ continue;
+ }
+ }
+ return false;
+}
+
+
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index eeb8a18..2283254 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -210,6 +210,7 @@ class Item_func :public Item_func_or_sum,
void traverse_cond(Cond_traverser traverser,
void * arg, traverse_order order);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
// bool is_expensive_processor(void *arg);
// virtual bool is_expensive() { return 0; }
inline void raise_numeric_overflow(const char *type_name)
@@ -873,6 +874,7 @@ class Item_func_case_expression: public Item_func_hybrid_field_type
Item_func_case_expression(THD *thd, List<Item> &list):
Item_func_hybrid_field_type(thd, list)
{ }
+ bool find_not_null_fields(table_map allowed) { return false; }
};
@@ -2009,6 +2011,10 @@ class Item_func_coercibility :public Item_long_func
not_null_tables_cache= 0;
return false;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{ return this; }
bool const_item() const { return true; }
@@ -2381,6 +2387,10 @@ class Item_udf_func :public Item_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool is_expensive() { return 1; }
virtual void print(String *str, enum_query_type query_type);
bool check_vcol_func_processor(void *arg)
@@ -3000,6 +3010,10 @@ class Item_func_match :public Item_real_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool fix_fields(THD *thd, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
/* The following should be safe, even if we compare doubles */
@@ -3303,6 +3317,10 @@ class Item_func_sp :public Item_func,
}
bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return false; }
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
};
@@ -3407,6 +3425,10 @@ class Item_func_last_value :public Item_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool const_item() const { return 0; }
void evaluate_sideeffects();
void update_used_tables()
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 150d572..def1458 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -87,6 +87,25 @@ Item_row::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_row::find_not_null_fields(table_map allowed)
+{
+ if (~allowed & used_tables())
+ return false;
+
+ Item **arg,**arg_end;
+ if (arg_count)
+ {
+ for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++)
+ {
+ if (!(*arg)->find_not_null_fields(allowed))
+ continue;
+ }
+ }
+ return false;
+}
+
+
void Item_row::cleanup()
{
DBUG_ENTER("Item_row::cleanup");
diff --git a/sql/item_row.h b/sql/item_row.h
index 28e6c09..2872a49 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -121,6 +121,7 @@ class Item_row: public Item_fixed_hybrid,
}
Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
uint cols() const { return arg_count; }
Item* element_index(uint i) { return args[i]; }
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9e6b786..2987f2e 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2645,6 +2645,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
uint idx;
double scan_time;
+ Item *notnull_cond= NULL;
DBUG_ENTER("SQL_SELECT::test_quick_select");
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
(ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables,
@@ -2659,6 +2660,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (keys_to_use.is_clear_all() || head->is_filled_at_execution())
DBUG_RETURN(0);
records= head->stat_records();
+ notnull_cond= head->notnull_cond;
if (!records)
records++; /* purecov: inspected */
scan_time= (double) records / TIME_FOR_COMPARE + 1;
@@ -2666,7 +2668,10 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (head->force_index)
scan_time= read_time= DBL_MAX;
if (limit < records)
+ {
read_time= (double) records + scan_time + 1; // Force to use index
+ notnull_cond= NULL;
+ }
possible_keys.clear_all();
@@ -2689,6 +2694,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
uchar buff[STACK_BUFF_ALLOC];
MEM_ROOT alloc;
SEL_TREE *tree= NULL;
+ SEL_TREE *notnull_cond_tree= NULL;
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
@@ -2825,6 +2831,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
TRP_GROUP_MIN_MAX *group_trp= NULL;
double best_read_time= read_time;
+ if (notnull_cond)
+ notnull_cond_tree= notnull_cond->get_mm_tree(¶m, ¬null_cond);
+
if (cond)
{
{
@@ -2852,6 +2861,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
}
}
}
+ tree= tree_and(¶m, tree, notnull_cond_tree);
/*
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 0d1c988..7aca1d2 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -229,6 +229,7 @@
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
#define OPTIMIZER_SWITCH_USE_ROWID_FILTER (1ULL << 33)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING (1ULL << 34)
+#define OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN (1ULL << 35)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0e8f331..46c68d7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -305,6 +305,14 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab);
static Item **get_sargable_cond(JOIN *join, TABLE *table);
+static
+bool build_notnull_conds_for_range_scans(JOIN *join, COND *cond,
+ table_map allowed);
+static
+void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join,
+ TABLE_LIST *nest_tbl);
+
+
#ifndef DBUG_OFF
/*
@@ -5309,6 +5317,9 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
}
+ join->join_tab= stat;
+ join->make_notnull_conds_for_range_scans();
+
/* Calc how many (possible) matched records in each table */
/*
@@ -28680,5 +28691,278 @@ select_handler *SELECT_LEX::find_select_handler(THD *thd)
/**
+ @brief
+ Construct not null conditions for provingly not nullable fields
+
+ @details
+ For each non-constant joined table the function creates a conjunction
+ of IS NOT NULL predicates containing a predicate for each field used
+ in the WHERE clause or an OR expression such that
+ - is declared as nullable
+ - for which it can proved be that it is null-rejected
+ - is a part of some index.
+ This conjunction could be anded with either the WHERE condition or with
+ an ON expression and the modified join query would produce the same
+ result set as the original one.
+ If a conjunction of IS NOT NULL predicates is constructed for an inner
+ table of an outer join OJ that is not an inner table of embedded outer
+ joins then it is to be anded with the ON expression of OJ.
+ The constructed conjunctions of IS NOT NULL predicates are attached
+ to the corresponding tables. They used for range analysis complementary
+ to other sargable range conditions.
+
+ @note
+ Let f be a field of the joined table t. In the context of the upper
+ paragraph field f is called null-rejected if any the following holds:
+
+ - t is a table of a top inner join and a conjunctive formula that rejects
+ rows with null values for f can be extracted from the WHERE condition
+
+ - t is an outer table of a top outer join operation and a conjunctive
+ formula over the outer tables of the outer join that rejects rows with
+ null values for can be extracted from the WHERE condition
+
+ - t is an outer table of a non-top outer join operation and a conjunctive
+ formula over the outer tables of the outer join that rejects rows with
+ null values for f can be extracted from the ON expression of the
+ embedding outer join
+
+ - the joined table is an inner table of a outer join operation and
+ a conjunctive formula over inner tables of the outer join that rejects
+ rows with null values for f can be extracted from the ON expression of
+ the outer join operation.
+
+ It is assumed above that all inner join nests have been eliminated and
+ that all possible conversions of outer joins into inner joins have been
+ already done.
+*/
+
+void JOIN::make_notnull_conds_for_range_scans()
+{
+ DBUG_ENTER("JOIN::make_notnull_conds_for_range_scans");
+
+
+ if (impossible_where ||
+ !optimizer_flag(thd, OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN))
+ {
+ /* Complementary range analysis is not needed */
+ DBUG_VOID_RETURN;
+ }
+
+ if (conds && build_notnull_conds_for_range_scans(this, conds,
+ conds->used_tables()))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ {
+ /*
+ Found a IS NULL conjunctive predicate for a null-rejected field
+ in the WHERE clause
+ */
+ conds= false_cond;
+ cond_equal= 0;
+ impossible_where= true;
+ }
+ DBUG_VOID_RETURN;
+ }
+
+ List_iterator<TABLE_LIST> li(*join_list);
+ TABLE_LIST *tbl;
+ while ((tbl= li++))
+ {
+ if (tbl->on_expr)
+ {
+ if (tbl->nested_join)
+ {
+ build_notnull_conds_for_inner_nest_of_outer_join(this, tbl);
+ }
+ else if (build_notnull_conds_for_range_scans(this, tbl->on_expr,
+ tbl->table->map))
+ {
+ /*
+ Found a IS NULL conjunctive predicate for a null-rejected field
+ of the inner table of an outer join with ON expression tbl->on_expr
+ */
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ tbl->on_expr= false_cond;
+ }
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ @brief
+ Build not null conditions for range scans of given join tables
+
+ @param join the join for whose tables not null conditions are to be built
+ @param cond the condition from which not null predicates are to be inferred
+ @param allowed the bit map of join tables to be taken into account
+
+ @details
+ For each join table t from the 'allowed' set of tables the function finds
+ all fields whose null-rejectedness can be inferred from null-rejectedness
+ of the condition cond. For each found field f from table t such that it
+ participates at least in one index on table t a NOT NULL predicate is
+ constructed and a conjunction of all such predicates is attached to t.
+ If when looking for null-rejecting fields of t it is discovered one of its
+ fields has to be null-rejected and there is IS NULL conjunctive top level
+ predicate for this field then the function immediately returns true.
+ The function uses the bitmap TABLE::tmp_set to mark found null-rejected
+ fields of table t.
+
+ @note
+ Currently only top level conjuncts without disjunctive sub-formulas are
+ are taken into account when looking for null-rejected fields.
+
+ @retval
+ true if a contradiction is inferred
+ false otherwise
+*/
+
+static
+bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond,
+ table_map allowed)
+{
+ THD *thd= join->thd;
+
+ DBUG_ENTER("build_notnull_conds_for_range_scans");
+
+ for (JOIN_TAB *s= join->join_tab + join->const_tables ;
+ s < join->join_tab + join->table_count ; s++)
+ {
+ /* Clear all needed bitmaps to mark found fields */
+ if (allowed & s->table->map)
+ bitmap_clear_all(&s->table->tmp_set);
+ }
+
+ /*
+ Find all null-rejected fields assuming that cond is null-rejected and
+ only formulas over tables from 'allowed' are to be taken into account
+ */
+ if (cond->find_not_null_fields(allowed))
+ DBUG_RETURN(true);
+
+ /*
+ For each table t from 'allowed' build a conjunction of NOT NULL predicates
+ constructed for all found fields if they are included in some indexes.
+ If the construction of the conjunction succeeds attach the formula to
+ t->table->notnull_cond. The condition will be used to look for complementary
+ range scans.
+ */
+ for (JOIN_TAB *s= join->join_tab + join->const_tables ;
+ s < join->join_tab + join->table_count ; s++)
+ {
+ TABLE *tab= s->table;
+ List<Item> notnull_list;
+ Item *notnull_cond= 0;
+
+ if (!(allowed & tab->map))
+ continue;
+
+ for (Field** field_ptr= tab->field; *field_ptr; field_ptr++)
+ {
+ Field *field= *field_ptr;
+ if (field->part_of_key.is_clear_all())
+ continue;
+ if (!bitmap_is_set(&tab->tmp_set, field->field_index))
+ continue;
+ Item_field *field_item= new (thd->mem_root) Item_field(thd, field);
+ if (!field_item)
+ continue;
+ Item *isnotnull_item=
+ new (thd->mem_root) Item_func_isnotnull(thd, field_item);
+ if (!isnotnull_item)
+ continue;
+ if (notnull_list.push_back(isnotnull_item, thd->mem_root))
+ continue;
+ s->const_keys.merge(field->part_of_key);
+ }
+
+ switch (notnull_list.elements) {
+ case 0:
+ break;
+ case 1:
+ notnull_cond= notnull_list.head();
+ break;
+ default:
+ notnull_cond=
+ new (thd->mem_root) Item_cond_and(thd, notnull_list);
+ }
+ if (notnull_cond && !notnull_cond->fix_fields(thd, 0))
+ {
+ tab->notnull_cond= notnull_cond;
+ }
+ }
+ DBUG_RETURN(false);
+}
+
+
+/**
+ @brief
+ Build not null conditions for inner nest tables of an outer join
+
+ @param join the join for whose table nest not null conditions are to be built
+ @param nest_tbl the nest of the inner tables of an outer join
+
+ @details
+ The function assumes that nest_tbl is the nest of the inner tables of an
+ outer join and so an ON expression for this outer join is attached to
+ nest_tbl.
+ The function selects the tables of the nest_tbl that are not inner tables of
+ embedded outer joins and then it calls build_notnull_conds_for_range_scans()
+ for nest_tbl->on_expr and the bitmap for the selected tables. This call
+ finds all fields belonging to the selected tables whose null-rejectedness
+ can be inferred from the null-rejectedness of nest_tbl->on_expr. After this
+ the function recursively finds all null_rejected fields for the remaining
+ tables from the nest of nest_tbl.
+*/
+
+static
+void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join,
+ TABLE_LIST *nest_tbl)
+{
+ TABLE_LIST *tbl;
+ table_map used_tables= 0;
+ THD *thd= join->thd;
+ List_iterator<TABLE_LIST> li(nest_tbl->nested_join->join_list);
+
+ while ((tbl= li++))
+ {
+ if (!tbl->on_expr)
+ used_tables|= tbl->table->map;
+ }
+ if (used_tables &&
+ build_notnull_conds_for_range_scans(join, nest_tbl->on_expr, used_tables))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ nest_tbl->on_expr= false_cond;
+ }
+
+ li.rewind();
+ while ((tbl= li++))
+ {
+ if (tbl->on_expr)
+ {
+ if (tbl->nested_join)
+ {
+ build_notnull_conds_for_inner_nest_of_outer_join(join, tbl);
+ }
+ else if (build_notnull_conds_for_range_scans(join, tbl->on_expr,
+ tbl->table->map))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ tbl->on_expr= false_cond;
+ }
+ }
+ }
+}
+
+
+/**
@} (end of group Query_Optimizer)
*/
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 40a9ed3..0c226e5 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1781,6 +1781,7 @@ class JOIN :public Sql_alloc
void add_keyuses_for_splitting();
bool inject_best_splitting_cond(table_map remaining_tables);
bool fix_all_splittings_in_plan();
+ void make_notnull_conds_for_range_scans();
bool transform_in_predicates_into_in_subq(THD *thd);
private:
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 250f4d6..29c938a 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2598,6 +2598,7 @@ export const char *optimizer_switch_names[]=
"condition_pushdown_for_subquery",
"rowid_filter",
"condition_pushdown_from_having",
+ "not_null_range_scan",
"default",
NullS
};
diff --git a/sql/table.cc b/sql/table.cc
index 6951b21..3b3a1fa 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -5167,6 +5167,8 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
(*f_ptr)->cond_selectivity= 1.0;
}
+ notnull_cond= 0;
+
DBUG_ASSERT(!file->keyread_enabled());
restore_record(this, s->default_values);
diff --git a/sql/table.h b/sql/table.h
index 2b86615..ecfe539 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1395,6 +1395,13 @@ struct TABLE
SplM_opt_info *spl_opt_info;
key_map keys_usable_for_splitting;
+ /*
+ Conjunction of the predicates of the form IS NOT NULL(f) where f refers to
+ a column of this TABLE such that they can be inferred from the condition
+ of the WHERE clause or from some ON expression of the processed select
+ and can be useful for range optimizer.
+ */
+ Item *notnull_cond;
inline void reset() { bzero((void*)this, sizeof(*this)); }
void init(THD *thd, TABLE_LIST *tl);
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
deleted file mode 100644
index b24c2fa..0000000
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
+++ /dev/null
@@ -1,112 +0,0 @@
-drop table if exists t;
-select @@optimizer_switch;
-@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
-create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
-insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
-explain select x,id from t force index (x) where x=0 and id=0;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1 Using index
-flush status;
-select x,id from t force index (x) where x=0 and id=0;
-x id
-0 0
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select y,id from t force index (x) where x=0 and id=0;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1
-flush status;
-select y,id from t force index (x) where x=0 and id=0;
-y id
-0 0
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select x,id from t force index (x) where x=0 and id=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1 Using index
-flush status;
-select x,id from t force index (x) where x=0 and id=1;
-x id
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select y,id from t force index (x)where x=0 and id=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1
-flush status;
-select y,id from t force index(x) where x=0 and id=1;
-y id
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select x,id from t force index (x) where x=2 and id=3;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1 Using index
-flush status;
-select x,id from t force index (x) where x=2 and id=3;
-x id
-2 3
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select x,id from t force index (x) where x=2 and id=0;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1 Using index
-flush status;
-select x,id from t force index (x) where x=2 and id=0;
-x id
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
deleted file mode 100644
index 8b7f4d8..0000000
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
+++ /dev/null
@@ -1,112 +0,0 @@
-drop table if exists t;
-select @@optimizer_switch;
-@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
-create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
-insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
-explain select x,id from t force index (x) where x=0 and id=0;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1 Using index
-flush status;
-select x,id from t force index (x) where x=0 and id=0;
-x id
-0 0
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select y,id from t force index (x) where x=0 and id=0;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1
-flush status;
-select y,id from t force index (x) where x=0 and id=0;
-y id
-0 0
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select x,id from t force index (x) where x=0 and id=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1 Using index
-flush status;
-select x,id from t force index (x) where x=0 and id=1;
-x id
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select y,id from t force index (x)where x=0 and id=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1
-flush status;
-select y,id from t force index(x) where x=0 and id=1;
-y id
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select x,id from t force index (x) where x=2 and id=3;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1 Using index
-flush status;
-select x,id from t force index (x) where x=2 and id=3;
-x id
-2 3
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select x,id from t force index (x) where x=2 and id=0;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const x x 8 const,const 1 Using index
-flush status;
-select x,id from t force index (x) where x=2 and id=0;
-x id
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
deleted file mode 100644
index 8e95644..0000000
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
+++ /dev/null
@@ -1,43 +0,0 @@
-drop table if exists t;
-select @@optimizer_switch;
-@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
-create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
-insert into t values (0,0,0,0),(0,1,0,1);
-explain select c,a,b from t where c=0 and a=0 and b=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const PRIMARY,c PRIMARY 8 const,const 1
-flush status;
-select c,a,b from t where c=0 and a=0 and b=1;
-c a b
-0 0 1
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select c,a,b from t force index (c) where c=0 and a=0 and b=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const c c 12 const,const,const 1 Using index
-flush status;
-select c,a,b from t force index (c) where c=0 and a=0 and b=1;
-c a b
-0 0 1
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
deleted file mode 100644
index 740e78f..0000000
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
+++ /dev/null
@@ -1,43 +0,0 @@
-drop table if exists t;
-select @@optimizer_switch;
-@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
-create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
-insert into t values (0,0,0,0),(0,1,0,1);
-explain select c,a,b from t where c=0 and a=0 and b=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const PRIMARY,c PRIMARY 8 const,const 1
-flush status;
-select c,a,b from t where c=0 and a=0 and b=1;
-c a b
-0 0 1
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-explain select c,a,b from t force index (c) where c=0 and a=0 and b=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t const c c 12 const,const,const 1 Using index
-flush status;
-select c,a,b from t force index (c) where c=0 and a=0 and b=1;
-c a b
-0 0 1
-show status like 'handler_read%';
-Variable_name Value
-Handler_read_first 0
-Handler_read_key 1
-Handler_read_last 0
-Handler_read_next 0
-Handler_read_prev 0
-Handler_read_retry 0
-Handler_read_rnd 0
-Handler_read_rnd_deleted 0
-Handler_read_rnd_next 0
-drop table t;
1
0
[Commits] d1490c1: MDEV-15777 Use inferred IS NOT NULL predicates in the range optimizer
by IgorBabaev 30 Aug '19
by IgorBabaev 30 Aug '19
30 Aug '19
revision-id: d1490c177139faa71cd88af71fdb7d88a8f45000 (mariadb-10.3.12-226-gd1490c1)
parent(s): 7060b0320d1479bb9476e0cbd4acc584e059e1ff
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-08-30 15:49:07 -0700
message:
MDEV-15777 Use inferred IS NOT NULL predicates in the range optimizer
This patch introduces the optimization that allows range optimizer to
consider index range scans that are built employing NOT NULL predicates
inferred from WHERE conditions and ON expressions.
The patch adds a new optimizer switch not_null_range_scan.
---
mysql-test/main/mysqld--help.result | 3 +-
mysql-test/main/range.result | 285 +++++++++++++++++++++
mysql-test/main/range.test | 182 +++++++++++++
mysql-test/main/range_mrr_icp.result | 285 +++++++++++++++++++++
.../suite/sys_vars/r/optimizer_switch_basic.result | 36 +--
.../sys_vars/r/sysvars_server_embedded.result | 8 +-
.../sys_vars/r/sysvars_server_notembedded.result | 8 +-
sql/item.cc | 10 +
sql/item.h | 43 ++++
sql/item_cmpfunc.cc | 161 +++++++++++-
sql/item_cmpfunc.h | 11 +
sql/item_func.cc | 19 ++
sql/item_func.h | 22 ++
sql/item_row.cc | 19 ++
sql/item_row.h | 1 +
sql/opt_range.cc | 10 +
sql/sql_priv.h | 1 +
sql/sql_select.cc | 285 +++++++++++++++++++++
sql/sql_select.h | 3 +-
sql/sys_vars.cc | 1 +
sql/table.cc | 2 +
sql/table.h | 7 +
.../mysql-test/tokudb/r/ext_key_1_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_1_tokudb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_tokudb.result | 2 +-
26 files changed, 1377 insertions(+), 33 deletions(-)
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index 1c7e9cd..19b4319 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -678,7 +678,8 @@ The following specify which files/extra groups are read (specified before remain
join_cache_hashed, join_cache_bka,
optimize_join_buffer_size, table_elimination,
extended_keys, exists_to_in, orderby_uses_equalities,
- condition_pushdown_for_derived, split_materialized
+ condition_pushdown_for_derived, split_materialized,
+ not_null_range_scan
--optimizer-use-condition-selectivity=#
Controls selectivity of which conditions the optimizer
takes into account to calculate cardinality of a partial
diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result
index 32e0cf2..807ca16 100644
--- a/mysql-test/main/range.result
+++ b/mysql-test/main/range.result
@@ -3024,3 +3024,288 @@ drop table t1;
#
# End of 10.2 tests
#
+#
+# MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+#
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+PRIMARY KEY (id),
+KEY t1_subset_id (subset_id));
+create table t2 (
+id int,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# with a subquery
+# expected the same plan as above
+explain SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 PRIMARY t2 ref id id 5 test.t1.subset_id 1 Using index; FirstMatch(t1)
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+# non-mergable subquery
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.subset_id 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1000 Using temporary
+SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+# with mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using index
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# with non-mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 PRIMARY <derived2> ref key0 key0 5 test.t1.subset_id 10
+2 DERIVED t2 ALL NULL NULL NULL NULL 1000 Using temporary; Using filesort
+SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# expected for t2 and for t1: range access
+explain SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range id id 5 NULL 3 Using index condition
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id col id subset_id
+0 0 0 0
+2 2 0 0
+4 4 0 0
+0 0 1 1
+2 2 1 1
+4 4 1 1
+0 0 2 2
+2 2 2 2
+4 4 2 2
+0 0 3 3
+2 2 3 3
+4 4 3 3
+0 0 4 4
+2 2 4 4
+4 4 4 4
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+5 NULL NULL NULL
+6 NULL NULL NULL
+7 NULL NULL NULL
+8 NULL NULL NULL
+9 NULL NULL NULL
+# expected for t1: range access
+explain SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE ten ALL NULL NULL NULL NULL 10
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+a id subset_id id col
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+1 SIMPLE ten ALL NULL NULL NULL NULL 10 Using where
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id subset_id id col a
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+drop index id on t2;
+# expected for t1: range access
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id subset_id id col
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id subset_id id col
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1: range access by idx (keylen=9)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx idx 9 NULL 4 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id subset_id m id col
+0 0 0 0 0
+2 2 0 2 2
+4 4 0 4 4
+drop view v1,v2;
+drop table t1,t2;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+KEY key1(id, subset_id),
+KEY t1_subset_id (subset_id)
+);
+create table t2 (
+id int NOT NULL,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1 :range access by index key1
+# rows 4 instead of 500
+explain SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1,t1_subset_id key1 9 NULL 4 Using where; Using index
+1 SIMPLE t2 ref id id 4 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id subset_id id col
+1 0 0 0
+1 1 1 1
+1 2 2 2
+1 3 3 3
+1 4 4 4
+drop table t1,t2;
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+# using key1 for range access on t1 and also using index for sorting,
+# no filesort, rows should be 75 not 500
+explain SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1 key1 5 NULL 75 Using index condition; Using where
+1 SIMPLE t2 ref id id 5 test.t1.id 2
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id col id col
+0 2 0 0
+0 2 0 0
+1 2 1 1
+1 2 1 1
+2 2 2 2
+2 2 2 2
+3 2 3 3
+3 2 3 3
+4 2 4 4
+4 2 4 4
+drop table t1,t2;
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/main/range.test b/mysql-test/main/range.test
index bd2299b..014916a 100644
--- a/mysql-test/main/range.test
+++ b/mysql-test/main/range.test
@@ -2053,3 +2053,185 @@ drop table t1;
--echo #
--echo # End of 10.2 tests
--echo #
+
+--echo #
+--echo # MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+--echo #
+
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+
+create table t1 (
+ id int NOT NULL,
+ subset_id int DEFAULT NULL,
+ PRIMARY KEY (id),
+ KEY t1_subset_id (subset_id));
+
+create table t2 (
+ id int,
+ col int NOT NULL,
+ key (id)
+);
+
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+--echo # with a subquery
+--echo # expected the same plan as above
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1
+ WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+--echo # non-mergable subquery
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+
+let $q=
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+--echo # with mergeable view
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q= SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+--echo # with non-mergeable view
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+--echo # expected for t2 and for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+--echo # no range access expected for t1
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+--echo # expected for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+--echo # no range access expected for t1
+eval explain $q;
+eval $q;
+
+drop index id on t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+--echo # expected for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+--echo # expected impossible where after reading const tables
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+--echo # expected impossible where after reading const tables
+eval explain $q;
+eval $q;
+
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+--echo # expected for t1: range access by idx (keylen=9)
+eval explain $q;
+eval $q;
+
+
+drop view v1,v2;
+drop table t1,t2;
+
+create table t1 (
+ id int NOT NULL,
+ subset_id int DEFAULT NULL,
+ KEY key1(id, subset_id),
+ KEY t1_subset_id (subset_id)
+);
+
+create table t2 (
+ id int NOT NULL,
+ col int NOT NULL,
+ key (id)
+);
+
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+--echo # expected for t1 :range access by index key1
+--echo # rows 4 instead of 500
+eval explain $q;
+eval $q;
+
+drop table t1,t2;
+
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+--echo # using key1 for range access on t1 and also using index for sorting,
+--echo # no filesort, rows should be 75 not 500
+eval explain $q;
+eval $q;
+
+drop table t1,t2;
+
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result
index 6b5bf33..d484d51 100644
--- a/mysql-test/main/range_mrr_icp.result
+++ b/mysql-test/main/range_mrr_icp.result
@@ -3036,4 +3036,289 @@ drop table t1;
#
# End of 10.2 tests
#
+#
+# MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+#
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+PRIMARY KEY (id),
+KEY t1_subset_id (subset_id));
+create table t2 (
+id int,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# with a subquery
+# expected the same plan as above
+explain SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 PRIMARY t2 ref id id 5 test.t1.subset_id 1 Using index; FirstMatch(t1)
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+# non-mergable subquery
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.subset_id 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1000 Using temporary
+SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+# with mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using index
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# with non-mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 PRIMARY <derived2> ref key0 key0 5 test.t1.subset_id 10
+2 DERIVED t2 ALL NULL NULL NULL NULL 1000 Using temporary; Using filesort
+SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# expected for t2 and for t1: range access
+explain SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range id id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where; Rowid-ordered scan; Using join buffer (flat, BNL join)
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id col id subset_id
+0 0 0 0
+2 2 0 0
+4 4 0 0
+0 0 1 1
+2 2 1 1
+4 4 1 1
+0 0 2 2
+2 2 2 2
+4 4 2 2
+0 0 3 3
+2 2 3 3
+4 4 3 3
+0 0 4 4
+2 2 4 4
+4 4 4 4
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+5 NULL NULL NULL
+6 NULL NULL NULL
+7 NULL NULL NULL
+8 NULL NULL NULL
+9 NULL NULL NULL
+# expected for t1: range access
+explain SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE ten ALL NULL NULL NULL NULL 10
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+a id subset_id id col
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+1 SIMPLE ten ALL NULL NULL NULL NULL 10 Using where
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id subset_id id col a
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+drop index id on t2;
+# expected for t1: range access
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id subset_id id col
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id subset_id id col
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1: range access by idx (keylen=9)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx idx 9 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id subset_id m id col
+0 0 0 0 0
+2 2 0 2 2
+4 4 0 4 4
+drop view v1,v2;
+drop table t1,t2;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+KEY key1(id, subset_id),
+KEY t1_subset_id (subset_id)
+);
+create table t2 (
+id int NOT NULL,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1 :range access by index key1
+# rows 4 instead of 500
+explain SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1,t1_subset_id key1 9 NULL 4 Using where; Using index
+1 SIMPLE t2 ref id id 4 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id subset_id id col
+1 0 0 0
+1 1 1 1
+1 2 2 2
+1 3 3 3
+1 4 4 4
+drop table t1,t2;
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+# using key1 for range access on t1 and also using index for sorting,
+# no filesort, rows should be 75 not 500
+explain SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1 key1 5 NULL 75 Using index condition; Using where
+1 SIMPLE t2 ref id id 5 test.t1.id 2
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id col id col
+0 2 0 0
+0 2 0 0
+1 2 1 1
+1 2 1 1
+2 2 2 2
+2 2 2 2
+3 2 3 3
+3 2 3 3
+4 2 4 4
+4 2 4 4
+drop table t1,t2;
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+#
+# End of 10.3 tests
+#
set optimizer_switch=@mrr_icp_extra_tmp;
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
index 87c8379..ba40512 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
@@ -1,63 +1,63 @@
SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value;
@start_global_value
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
set global optimizer_switch=10;
set session optimizer_switch=5;
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
set global optimizer_switch="index_merge_sort_union=on";
set session optimizer_switch="index_merge=off";
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
set session optimizer_switch="default";
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
Warnings:
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=on
set global optimizer_switch=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
set global optimizer_switch=1e1;
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
index 89e5fef..714b55c 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
@@ -2715,17 +2715,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,not_null_range_scan,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index ca875e7..dd9d9eb 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -2925,17 +2925,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,not_null_range_scan,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
diff --git a/sql/item.cc b/sql/item.cc
index 3584230..9c95611 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3556,6 +3556,16 @@ table_map Item_field::all_used_tables() const
}
+bool Item_field::find_not_null_fields(table_map allowed)
+{
+ if (field->table->const_table)
+ return false;
+ if (!get_depended_from() && field->real_maybe_null())
+ bitmap_set_bit(&field->table->tmp_set, field->field_index);
+ return false;
+}
+
+
/*
@Note thd->fatal_error can be set in case of OOM
*/
diff --git a/sql/item.h b/sql/item.h
index 2adc111..c2dbdb1 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1818,6 +1818,44 @@ class Item: public Value_source,
virtual bool set_fields_as_dependent_processor(void *arg) { return 0; }
/*============== End of Item processor list ======================*/
+ /*
+ Given a condition P from the WHERE clause or from an ON expression of
+ the processed SELECT S and a set of join tables from S marked in the
+ parameter 'allowed'={T} a call of P->find_not_null_fields({T}) has to
+ find the set fields {F} of the tables from 'allowed' such that:
+ - each field from {F} is declared as nullable
+ - each record of table t from {T} that contains NULL as the value for at
+ at least one field from {F} can be ignored when building the result set
+ for S
+ It is assumed here that the condition P is conjunctive and all its column
+ references belong to T.
+
+ Examples:
+ CREATE TABLE t1 (a int, b int);
+ CREATE TABLE t2 (a int, b int);
+
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b > 5;
+ A call of find_not_null_fields() for the whole WHERE condition and {t1,t2}
+ should find {t1.a,t1.b,t2.a}
+
+ SELECT * FROM t1 LEFT JOIN ON (t1.a=t2.a and t2.a > t2.b);
+ A call of find_not_null_fields() for the ON expression and {t2}
+ should find {t2.a,t2.b}
+
+ The function returns TRUE if it succeeds to prove that all records of
+ a table from {T} can be ignored. Otherwise it always returns FALSE.
+
+ Example:
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t2.a IS NULL;
+ A call of find_not_null_fields() for the WHERE condition and {t1,t2}
+ will return TRUE.
+
+ It is assumed that the implementation of this virtual function saves
+ the info on the found set of fields in the structures associates with
+ tables from {T}.
+ */
+ virtual bool find_not_null_fields(table_map allowed) { return false; }
+
virtual Item *get_copy(THD *thd)=0;
bool cache_const_expr_analyzer(uchar **arg);
@@ -3079,6 +3117,7 @@ class Item_field :public Item_ident,
bool is_result_field() { return false; }
void save_in_result_field(bool no_conversions);
Item *get_tmp_table_item(THD *thd);
+ bool find_not_null_fields(table_map allowed);
bool collect_item_field_processor(void * arg);
bool add_field_to_set_processor(void * arg);
bool find_item_in_field_list_processor(void *arg);
@@ -4858,6 +4897,10 @@ class Item_ref :public Item_ident
{
return depended_from ? 0 : (*ref)->not_null_tables();
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return depended_from ? false : (*ref)->find_not_null_fields(allowed);
+ }
void save_in_result_field(bool no_conversions)
{
(*ref)->save_in_field(result_field, no_conversions);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 49e0a94..c4b43a7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1192,6 +1192,15 @@ bool Item_in_optimizer::eval_not_null_tables(void *opt_arg)
}
+bool Item_in_optimizer::find_not_null_fields(table_map allowed)
+{
+ if (!(~allowed & used_tables()) && is_top_level_item())
+ {
+ return args[0]->find_not_null_fields(allowed);
+ }
+ return false;
+}
+
void Item_in_optimizer::print(String *str, enum_query_type query_type)
{
restore_first_argument();
@@ -2035,7 +2044,17 @@ bool Item_func_between::eval_not_null_tables(void *opt_arg)
(args[1]->not_null_tables() &
args[2]->not_null_tables()));
return 0;
-}
+}
+
+
+bool Item_func_between::find_not_null_fields(table_map allowed)
+{
+ if (negated || !is_top_level_item() || (~allowed & used_tables()))
+ return false;
+ return args[0]->find_not_null_fields(allowed) ||
+ args[1]->find_not_null_fields(allowed) ||
+ args[3]->find_not_null_fields(allowed);
+}
bool Item_func_between::count_sargable_conds(void *arg)
@@ -4151,6 +4170,15 @@ Item_func_in::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_func_in::find_not_null_fields(table_map allowed)
+{
+ if (negated || !is_top_level_item() || (~allowed & used_tables()))
+ return 0;
+ return args[0]->find_not_null_fields(allowed);
+}
+
+
void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
@@ -4705,6 +4733,82 @@ Item_cond::eval_not_null_tables(void *opt_arg)
}
+/**
+ @note
+ This implementation of the virtual function find_not_null_fields()
+ infers null-rejectedness if fields from tables marked in 'allowed' from
+ this condition.
+ Currently only top level AND conjuncts that are not disjunctions are used
+ for the inference. Usage of any top level and-or formula with l OR levels
+ would require a stack of bitmaps for fields of the height h=2*l+1 So we
+ would have to allocate h-1 additional field bitmaps for each table marked
+ in 'allowed'.
+*/
+
+bool
+Item_cond::find_not_null_fields(table_map allowed)
+{
+ Item *item;
+ bool is_and_cond= functype() == Item_func::COND_AND_FUNC;
+ if (!is_and_cond)
+ {
+ /* Now only fields of top AND level conjuncts are taken into account */
+ return false;
+ }
+ uint isnull_func_cnt= 0;
+ List_iterator<Item> li(list);
+ while ((item=li++))
+ {
+ bool is_mult_eq= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::MULT_EQUAL_FUNC;
+ if (is_mult_eq)
+ {
+ if (!item->find_not_null_fields(allowed))
+ continue;
+ }
+
+ if (~allowed & item->used_tables())
+ continue;
+
+ /* It is assumed that all constant conjuncts are already eliminated */
+
+ /*
+ First infer null-rejectedness of fields from all conjuncts but
+ IS NULL predicates
+ */
+ bool isnull_func= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::ISNULL_FUNC;
+ if (isnull_func)
+ {
+ isnull_func_cnt++;
+ continue;
+ }
+ if (!item->find_not_null_fields(allowed))
+ continue;
+ }
+
+ /* Now try no get contradictions using IS NULL conjuncts */
+ if (isnull_func_cnt)
+ {
+ li.rewind();
+ while ((item=li++) && isnull_func_cnt)
+ {
+ if (~allowed & item->used_tables())
+ continue;
+
+ bool isnull_func= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::ISNULL_FUNC;
+ if (isnull_func)
+ {
+ if (item->find_not_null_fields(allowed))
+ return true;
+ isnull_func_cnt--;
+ }
+ }
+ }
+ return false;
+}
+
void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
@@ -5148,6 +5252,19 @@ longlong Item_func_isnull::val_int()
}
+bool Item_func_isnull::find_not_null_fields(table_map allowed)
+{
+ if (!(~allowed & used_tables()) &&
+ args[0]->real_item()->type() == Item::FIELD_ITEM)
+ {
+ Field *field= ((Item_field *)(args[0]->real_item()))->field;
+ if (bitmap_is_set(&field->table->tmp_set, field->field_index))
+ return true;
+ }
+ return false;
+}
+
+
void Item_func_isnull::print(String *str, enum_query_type query_type)
{
if (const_item() && !args[0]->maybe_null &&
@@ -6734,6 +6851,48 @@ void Item_equal::update_used_tables()
}
+/**
+ @note
+ This multiple equality can contains elements belonging not to tables {T}
+ marked in 'allowed' . So we can ascertain null-rejectedness of field f
+ belonging to table t from {T} only if one of the following equality
+ predicate can be extracted from this multiple equality:
+ - f=const
+ - f=f' where f' is a field of some table from {T}
+*/
+
+bool Item_equal::find_not_null_fields(table_map allowed)
+{
+ if (!(allowed & used_tables()))
+ return false;
+ bool checked= false;
+ Item_equal_fields_iterator it(*this);
+ Item *item;
+ while ((item= it++))
+ {
+ if (~allowed & item->used_tables())
+ continue;
+ if ((with_const || checked) && !item->find_not_null_fields(allowed))
+ continue;
+ Item_equal_fields_iterator it1(*this);
+ Item *item1;
+ while ((item1= it1++) && item1 != item)
+ {
+ if (~allowed & item1->used_tables())
+ continue;
+ if (!item->find_not_null_fields(allowed) &&
+ !item1->find_not_null_fields(allowed))
+ {
+ checked= true;
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+
+
bool Item_equal::count_sargable_conds(void *arg)
{
SELECT_LEX *sel= (SELECT_LEX *) arg;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 7d99cbd..8f01e4f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -284,6 +284,7 @@ class Item_func_isnottrue : public Item_func_truth
Item_func_truth(thd, a, true, false) {}
~Item_func_isnottrue() {}
virtual const char* func_name() const { return "isnottrue"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnottrue>(thd, this); }
};
@@ -315,6 +316,7 @@ class Item_func_isnotfalse : public Item_func_truth
Item_func_truth(thd, a, false, false) {}
~Item_func_isnotfalse() {}
virtual const char* func_name() const { return "isnotfalse"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnotfalse>(thd, this); }
};
@@ -376,6 +378,7 @@ class Item_in_optimizer: public Item_bool_func
virtual void get_cache_parameters(List<Item> ¶meters);
bool is_top_level_item();
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool invisible_mode();
void reset_cache() { cache= NULL; }
@@ -571,6 +574,7 @@ class Item_func_xor :public Item_bool_func
void print(String *str, enum_query_type query_type)
{ Item_func::print_op(str, query_type); }
longlong val_int();
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *neg_transformer(THD *thd);
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
@@ -592,6 +596,7 @@ class Item_func_not :public Item_bool_func
longlong val_int();
enum Functype functype() const { return NOT_FUNC; }
const char *func_name() const { return "not"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
enum precedence precedence() const { return BANG_PRECEDENCE; }
Item *neg_transformer(THD *thd);
bool fix_fields(THD *, Item **);
@@ -736,6 +741,7 @@ class Item_func_equal :public Item_bool_rowready_func2
longlong val_int();
bool fix_length_and_dec();
table_map not_null_tables() const { return 0; }
+ bool find_not_null_fields(table_map allowed) { return false; }
enum Functype functype() const { return EQUAL_FUNC; }
enum Functype rev_functype() const { return EQUAL_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
@@ -912,6 +918,7 @@ class Item_func_between :public Item_func_opt_neg
bool fix_length_and_dec_numeric(THD *);
virtual void print(String *str, enum_query_type query_type);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg);
void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
@@ -2396,6 +2403,7 @@ class Item_func_in :public Item_func_opt_neg,
const char *func_name() const { return "in"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg);
Item *get_copy(THD *thd)
@@ -2533,6 +2541,7 @@ class Item_func_isnull :public Item_func_null_predicate
COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
bool top_level);
table_map not_null_tables() const { return 0; }
+ bool find_not_null_fields(table_map allowed);
Item *neg_transformer(THD *thd);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnull>(thd, this); }
@@ -2953,6 +2962,7 @@ class Item_cond :public Item_bool_func
Item *compile(THD *thd, Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
Item *build_clone(THD *thd);
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
@@ -3119,6 +3129,7 @@ class Item_equal: public Item_bool_func
eval_item= NULL;
}
void update_used_tables();
+ bool find_not_null_fields(table_map allowed);
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
bool link_item_fields,
COND_EQUAL **cond_equal_ref);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index a030d2f..41bbd2e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -403,6 +403,25 @@ Item_func::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_func::find_not_null_fields(table_map allowed)
+{
+ if (~allowed & used_tables())
+ return false;
+
+ Item **arg,**arg_end;
+ if (arg_count)
+ {
+ for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
+ {
+ if (!(*arg)->find_not_null_fields(allowed))
+ continue;
+ }
+ }
+ return false;
+}
+
+
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 6345dd4..325a796 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -210,6 +210,7 @@ class Item_func :public Item_func_or_sum
void traverse_cond(Cond_traverser traverser,
void * arg, traverse_order order);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
// bool is_expensive_processor(void *arg);
// virtual bool is_expensive() { return 0; }
inline void raise_numeric_overflow(const char *type_name)
@@ -671,6 +672,7 @@ class Item_func_case_expression: public Item_func_hybrid_field_type
Item_func_case_expression(THD *thd, List<Item> &list):
Item_func_hybrid_field_type(thd, list)
{ }
+ bool find_not_null_fields(table_map allowed) { return false; }
};
@@ -1759,6 +1761,10 @@ class Item_func_coercibility :public Item_long_func
not_null_tables_cache= 0;
return false;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{ return this; }
bool const_item() const { return true; }
@@ -2119,6 +2125,10 @@ class Item_udf_func :public Item_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool is_expensive() { return 1; }
virtual void print(String *str, enum_query_type query_type);
bool check_vcol_func_processor(void *arg)
@@ -2711,6 +2721,10 @@ class Item_func_match :public Item_real_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool fix_fields(THD *thd, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
/* The following should be safe, even if we compare doubles */
@@ -3000,6 +3014,10 @@ class Item_func_sp :public Item_func,
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
};
@@ -3103,6 +3121,10 @@ class Item_func_last_value :public Item_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool const_item() const { return 0; }
void evaluate_sideeffects();
void update_used_tables()
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 70a9fe5..0b55ae5 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -87,6 +87,25 @@ Item_row::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_row::find_not_null_fields(table_map allowed)
+{
+ if (~allowed & used_tables())
+ return false;
+
+ Item **arg,**arg_end;
+ if (arg_count)
+ {
+ for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++)
+ {
+ if (!(*arg)->find_not_null_fields(allowed))
+ continue;
+ }
+ }
+ return false;
+}
+
+
void Item_row::cleanup()
{
DBUG_ENTER("Item_row::cleanup");
diff --git a/sql/item_row.h b/sql/item_row.h
index 0d6a6db..0efa29f 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -110,6 +110,7 @@ class Item_row: public Item,
}
Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
uint cols() const { return arg_count; }
Item* element_index(uint i) { return args[i]; }
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index ec7b3db..91103a5 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2399,6 +2399,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
uint idx;
double scan_time;
+ Item *notnull_cond= NULL;
DBUG_ENTER("SQL_SELECT::test_quick_select");
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
(ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables,
@@ -2412,6 +2413,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (keys_to_use.is_clear_all() || head->is_filled_at_execution())
DBUG_RETURN(0);
records= head->stat_records();
+ notnull_cond= head->notnull_cond;
if (!records)
records++; /* purecov: inspected */
scan_time= (double) records / TIME_FOR_COMPARE + 1;
@@ -2419,7 +2421,10 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (head->force_index)
scan_time= read_time= DBL_MAX;
if (limit < records)
+ {
read_time= (double) records + scan_time + 1; // Force to use index
+ notnull_cond= NULL;
+ }
possible_keys.clear_all();
@@ -2431,6 +2436,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
uchar buff[STACK_BUFF_ALLOC];
MEM_ROOT alloc;
SEL_TREE *tree= NULL;
+ SEL_TREE *notnull_cond_tree= NULL;
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
@@ -2539,6 +2545,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
TRP_GROUP_MIN_MAX *group_trp;
double best_read_time= read_time;
+ if (notnull_cond)
+ notnull_cond_tree= notnull_cond->get_mm_tree(¶m, ¬null_cond);
+
if (cond)
{
if ((tree= cond->get_mm_tree(¶m, &cond)))
@@ -2557,6 +2566,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
tree= NULL;
}
}
+ tree= tree_and(¶m, tree, notnull_cond_tree);
/*
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 2f37e11..ec7b2cc 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -222,6 +222,7 @@
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
+#define OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN (1ULL << 32)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0fbc4ba..dae2cd7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -295,6 +295,14 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab);
static Item **get_sargable_cond(JOIN *join, TABLE *table);
+static
+bool build_notnull_conds_for_range_scans(JOIN *join, COND *cond,
+ table_map allowed);
+static
+void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join,
+ TABLE_LIST *nest_tbl);
+
+
#ifndef DBUG_OFF
/*
@@ -4907,6 +4915,9 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
}
+ join->join_tab= stat;
+ join->make_notnull_conds_for_range_scans();
+
/* Calc how many (possible) matched records in each table */
for (s=stat ; s < stat_end ; s++)
@@ -27572,6 +27583,280 @@ Item *remove_pushed_top_conjuncts(THD *thd, Item *cond)
return cond;
}
+
+/**
+ @brief
+ Construct not null conditions for provingly not nullable fields
+
+ @details
+ For each non-constant joined table the function creates a conjunction
+ of IS NOT NULL predicates containing a predicate for each field used
+ in the WHERE clause or an OR expression such that
+ - is declared as nullable
+ - for which it can proved be that it is null-rejected
+ - is a part of some index.
+ This conjunction could be anded with either the WHERE condition or with
+ an ON expression and the modified join query would produce the same
+ result set as the original one.
+ If a conjunction of IS NOT NULL predicates is constructed for an inner
+ table of an outer join OJ that is not an inner table of embedded outer
+ joins then it is to be anded with the ON expression of OJ.
+ The constructed conjunctions of IS NOT NULL predicates are attached
+ to the corresponding tables. They used for range analysis complementary
+ to other sargable range conditions.
+
+ @note
+ Let f be a field of the joined table t. In the context of the upper
+ paragraph field f is called null-rejected if any the following holds:
+
+ - t is a table of a top inner join and a conjunctive formula that rejects
+ rows with null values for f can be extracted from the WHERE condition
+
+ - t is an outer table of a top outer join operation and a conjunctive
+ formula over the outer tables of the outer join that rejects rows with
+ null values for can be extracted from the WHERE condition
+
+ - t is an outer table of a non-top outer join operation and a conjunctive
+ formula over the outer tables of the outer join that rejects rows with
+ null values for f can be extracted from the ON expression of the
+ embedding outer join
+
+ - the joined table is an inner table of a outer join operation and
+ a conjunctive formula over inner tables of the outer join that rejects
+ rows with null values for f can be extracted from the ON expression of
+ the outer join operation.
+
+ It is assumed above that all inner join nests have been eliminated and
+ that all possible conversions of outer joins into inner joins have been
+ already done.
+*/
+
+void JOIN::make_notnull_conds_for_range_scans()
+{
+ DBUG_ENTER("JOIN::make_notnull_conds_for_range_scans");
+
+
+ if (impossible_where ||
+ !optimizer_flag(thd, OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN))
+ {
+ /* Complementary range analysis is not needed */
+ DBUG_VOID_RETURN;
+ }
+
+ if (conds && build_notnull_conds_for_range_scans(this, conds,
+ conds->used_tables()))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ {
+ /*
+ Found a IS NULL conjunctive predicate for a null-rejected field
+ in the WHERE clause
+ */
+ conds= false_cond;
+ cond_equal= 0;
+ impossible_where= true;
+ }
+ DBUG_VOID_RETURN;
+ }
+
+ List_iterator<TABLE_LIST> li(*join_list);
+ TABLE_LIST *tbl;
+ while ((tbl= li++))
+ {
+ if (tbl->on_expr)
+ {
+ if (tbl->nested_join)
+ {
+ build_notnull_conds_for_inner_nest_of_outer_join(this, tbl);
+ }
+ else if (build_notnull_conds_for_range_scans(this, tbl->on_expr,
+ tbl->table->map))
+ {
+ /*
+ Found a IS NULL conjunctive predicate for a null-rejected field
+ of the inner table of an outer join with ON expression tbl->on_expr
+ */
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ tbl->on_expr= false_cond;
+ }
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ @brief
+ Build not null conditions for range scans of given join tables
+
+ @param join the join for whose tables not null conditions are to be built
+ @param cond the condition from which not null predicates are to be inferred
+ @param allowed the bit map of join tables to be taken into account
+
+ @details
+ For each join table t from the 'allowed' set of tables the function finds
+ all fields whose null-rejectedness can be inferred from null-rejectedness
+ of the condition cond. For each found field f from table t such that it
+ participates at least in one index on table t a NOT NULL predicate is
+ constructed and a conjunction of all such predicates is attached to t.
+ If when looking for null-rejecting fields of t it is discovered one of its
+ fields has to be null-rejected and there is IS NULL conjunctive top level
+ predicate for this field then the function immediately returns true.
+ The function uses the bitmap TABLE::tmp_set to mark found null-rejected
+ fields of table t.
+
+ @note
+ Currently only top level conjuncts without disjunctive sub-formulas are
+ are taken into account when looking for null-rejected fields.
+
+ @retval
+ true if a contradiction is inferred
+ false otherwise
+*/
+
+static
+bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond,
+ table_map allowed)
+{
+ THD *thd= join->thd;
+
+ DBUG_ENTER("build_notnull_conds_for_range_scans");
+
+ for (JOIN_TAB *s= join->join_tab + join->const_tables ;
+ s < join->join_tab + join->table_count ; s++)
+ {
+ /* Clear all needed bitmaps to mark found fields */
+ if (allowed & s->table->map)
+ bitmap_clear_all(&s->table->tmp_set);
+ }
+
+ /*
+ Find all null-rejected fields assuming that cond is null-rejected and
+ only formulas over tables from 'allowed' are to be taken into account
+ */
+ if (cond->find_not_null_fields(allowed))
+ DBUG_RETURN(true);
+
+ /*
+ For each table t from 'allowed' build a conjunction of NOT NULL predicates
+ constructed for all found fields if they are included in some indexes.
+ If the construction of the conjunction succeeds attach the formula to
+ t->table->notnull_cond. The condition will be used to look for complementary
+ range scans.
+ */
+ for (JOIN_TAB *s= join->join_tab + join->const_tables ;
+ s < join->join_tab + join->table_count ; s++)
+ {
+ TABLE *tab= s->table;
+ List<Item> notnull_list;
+ Item *notnull_cond= 0;
+
+ if (!(allowed & tab->map))
+ continue;
+
+ for (Field** field_ptr= tab->field; *field_ptr; field_ptr++)
+ {
+ Field *field= *field_ptr;
+ if (field->part_of_key.is_clear_all())
+ continue;
+ if (!bitmap_is_set(&tab->tmp_set, field->field_index))
+ continue;
+ Item_field *field_item= new (thd->mem_root) Item_field(thd, field);
+ if (!field_item)
+ continue;
+ Item *isnotnull_item=
+ new (thd->mem_root) Item_func_isnotnull(thd, field_item);
+ if (!isnotnull_item)
+ continue;
+ if (notnull_list.push_back(isnotnull_item, thd->mem_root))
+ continue;
+ s->const_keys.merge(field->part_of_key);
+ }
+
+ switch (notnull_list.elements) {
+ case 0:
+ break;
+ case 1:
+ notnull_cond= notnull_list.head();
+ break;
+ default:
+ notnull_cond=
+ new (thd->mem_root) Item_cond_and(thd, notnull_list);
+ }
+ if (notnull_cond && !notnull_cond->fix_fields(thd, 0))
+ {
+ tab->notnull_cond= notnull_cond;
+ }
+ }
+ DBUG_RETURN(false);
+}
+
+
+/**
+ @brief
+ Build not null conditions for inner nest tables of an outer join
+
+ @param join the join for whose table nest not null conditions are to be built
+ @param nest_tbl the nest of the inner tables of an outer join
+
+ @details
+ The function assumes that nest_tbl is the nest of the inner tables of an
+ outer join and so an ON expression for this outer join is attached to
+ nest_tbl.
+ The function selects the tables of the nest_tbl that are not inner tables of
+ embedded outer joins and then it calls build_notnull_conds_for_range_scans()
+ for nest_tbl->on_expr and the bitmap for the selected tables. This call
+ finds all fields belonging to the selected tables whose null-rejectedness
+ can be inferred from the null-rejectedness of nest_tbl->on_expr. After this
+ the function recursively finds all null_rejected fields for the remaining
+ tables from the nest of nest_tbl.
+*/
+
+static
+void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join,
+ TABLE_LIST *nest_tbl)
+{
+ TABLE_LIST *tbl;
+ table_map used_tables= 0;
+ THD *thd= join->thd;
+ List_iterator<TABLE_LIST> li(nest_tbl->nested_join->join_list);
+
+ while ((tbl= li++))
+ {
+ if (!tbl->on_expr)
+ used_tables|= tbl->table->map;
+ }
+ if (used_tables &&
+ build_notnull_conds_for_range_scans(join, nest_tbl->on_expr, used_tables))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ nest_tbl->on_expr= false_cond;
+ }
+
+ li.rewind();
+ while ((tbl= li++))
+ {
+ if (tbl->on_expr)
+ {
+ if (tbl->nested_join)
+ {
+ build_notnull_conds_for_inner_nest_of_outer_join(join, tbl);
+ }
+ else if (build_notnull_conds_for_range_scans(join, tbl->on_expr,
+ tbl->table->map))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ tbl->on_expr= false_cond;
+ }
+ }
+ }
+}
+
+
/**
@} (end of group Query_Optimizer)
*/
diff --git a/sql/sql_select.h b/sql/sql_select.h
index dd823a7..2b40a41 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1749,6 +1749,7 @@ class JOIN :public Sql_alloc
void add_keyuses_for_splitting();
bool inject_best_splitting_cond(table_map remaining_tables);
bool fix_all_splittings_in_plan();
+ void make_notnull_conds_for_range_scans();
bool transform_in_predicates_into_in_subq(THD *thd);
private:
@@ -2343,7 +2344,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
extern bool test_if_ref(Item *,
Item_field *left_item,Item *right_item);
-inline bool optimizer_flag(THD *thd, uint flag)
+inline bool optimizer_flag(THD *thd, ulonglong flag)
{
return (thd->variables.optimizer_switch & flag);
}
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index b50f697..58b6da5 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2544,6 +2544,7 @@ export const char *optimizer_switch_names[]=
"orderby_uses_equalities",
"condition_pushdown_for_derived",
"split_materialized",
+ "not_null_range_scan",
"default",
NullS
};
diff --git a/sql/table.cc b/sql/table.cc
index 4805017..34fb6d5 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4658,6 +4658,8 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
(*f_ptr)->cond_selectivity= 1.0;
}
+ notnull_cond= 0;
+
DBUG_ASSERT(!file->keyread_enabled());
restore_record(this, s->default_values);
diff --git a/sql/table.h b/sql/table.h
index fa6cb70..47096aa 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1344,6 +1344,13 @@ struct TABLE
SplM_opt_info *spl_opt_info;
key_map keys_usable_for_splitting;
+ /*
+ Conjunction of the predicates of the form IS NOT NULL(f) where f refers to
+ a column of this TABLE such that they can be inferred from the condition
+ of the WHERE clause or from some ON expression of the processed select
+ and can be useful for range optimizer.
+ */
+ Item *notnull_cond;
inline void reset() { bzero((void*)this, sizeof(*this)); }
void init(THD *thd, TABLE_LIST *tl);
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
index a80e166..5d471d2 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
index 96d6814..a3c518a 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
index 43737c7..21dadb8 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
index 1dcb1ee..41c3f2b 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
1
0
[Commits] 53c79c5: MDEV-15777 Use inferred IS NOT NULL predicates in the range optimizer
by IgorBabaev 30 Aug '19
by IgorBabaev 30 Aug '19
30 Aug '19
revision-id: 53c79c5eda06f404b40c9dc8e83f355fe0e4d29e (mariadb-10.3.12-226-g53c79c5)
parent(s): 7060b0320d1479bb9476e0cbd4acc584e059e1ff
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-08-30 15:46:11 -0700
message:
MDEV-15777 Use inferred IS NOT NULL predicates in the range optimizer
This patch introduces the optimization that allows range optimizer to
consider index range scans that are built employing NOT NULL predicates
inferred from WHERE conditions and ON expressions.
The patch adds a new optimizer switch not_null_range_scan that is 'off'
by default in 10.3.
---
mysql-test/main/mysqld--help.result | 3 +-
mysql-test/main/range.result | 285 +++++++++++++++++++++
mysql-test/main/range.test | 182 +++++++++++++
mysql-test/main/range_mrr_icp.result | 285 +++++++++++++++++++++
.../suite/sys_vars/r/optimizer_switch_basic.result | 36 +--
.../sys_vars/r/sysvars_server_embedded.result | 8 +-
.../sys_vars/r/sysvars_server_notembedded.result | 8 +-
sql/item.cc | 10 +
sql/item.h | 43 ++++
sql/item_cmpfunc.cc | 161 +++++++++++-
sql/item_cmpfunc.h | 11 +
sql/item_func.cc | 19 ++
sql/item_func.h | 22 ++
sql/item_row.cc | 19 ++
sql/item_row.h | 1 +
sql/opt_range.cc | 10 +
sql/sql_priv.h | 1 +
sql/sql_select.cc | 285 +++++++++++++++++++++
sql/sql_select.h | 3 +-
sql/sys_vars.cc | 1 +
sql/table.cc | 2 +
sql/table.h | 7 +
.../mysql-test/tokudb/r/ext_key_1_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_1_tokudb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_tokudb.result | 2 +-
26 files changed, 1377 insertions(+), 33 deletions(-)
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index 1c7e9cd..19b4319 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -678,7 +678,8 @@ The following specify which files/extra groups are read (specified before remain
join_cache_hashed, join_cache_bka,
optimize_join_buffer_size, table_elimination,
extended_keys, exists_to_in, orderby_uses_equalities,
- condition_pushdown_for_derived, split_materialized
+ condition_pushdown_for_derived, split_materialized,
+ not_null_range_scan
--optimizer-use-condition-selectivity=#
Controls selectivity of which conditions the optimizer
takes into account to calculate cardinality of a partial
diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result
index 32e0cf2..807ca16 100644
--- a/mysql-test/main/range.result
+++ b/mysql-test/main/range.result
@@ -3024,3 +3024,288 @@ drop table t1;
#
# End of 10.2 tests
#
+#
+# MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+#
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+PRIMARY KEY (id),
+KEY t1_subset_id (subset_id));
+create table t2 (
+id int,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# with a subquery
+# expected the same plan as above
+explain SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 PRIMARY t2 ref id id 5 test.t1.subset_id 1 Using index; FirstMatch(t1)
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+# non-mergable subquery
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.subset_id 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1000 Using temporary
+SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+# with mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using index
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# with non-mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 PRIMARY <derived2> ref key0 key0 5 test.t1.subset_id 10
+2 DERIVED t2 ALL NULL NULL NULL NULL 1000 Using temporary; Using filesort
+SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# expected for t2 and for t1: range access
+explain SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range id id 5 NULL 3 Using index condition
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id col id subset_id
+0 0 0 0
+2 2 0 0
+4 4 0 0
+0 0 1 1
+2 2 1 1
+4 4 1 1
+0 0 2 2
+2 2 2 2
+4 4 2 2
+0 0 3 3
+2 2 3 3
+4 4 3 3
+0 0 4 4
+2 2 4 4
+4 4 4 4
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+5 NULL NULL NULL
+6 NULL NULL NULL
+7 NULL NULL NULL
+8 NULL NULL NULL
+9 NULL NULL NULL
+# expected for t1: range access
+explain SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE ten ALL NULL NULL NULL NULL 10
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+a id subset_id id col
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+1 SIMPLE ten ALL NULL NULL NULL NULL 10 Using where
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id subset_id id col a
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+drop index id on t2;
+# expected for t1: range access
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id subset_id id col
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id subset_id id col
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1: range access by idx (keylen=9)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx idx 9 NULL 4 Using index condition
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id subset_id m id col
+0 0 0 0 0
+2 2 0 2 2
+4 4 0 4 4
+drop view v1,v2;
+drop table t1,t2;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+KEY key1(id, subset_id),
+KEY t1_subset_id (subset_id)
+);
+create table t2 (
+id int NOT NULL,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1 :range access by index key1
+# rows 4 instead of 500
+explain SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1,t1_subset_id key1 9 NULL 4 Using where; Using index
+1 SIMPLE t2 ref id id 4 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id subset_id id col
+1 0 0 0
+1 1 1 1
+1 2 2 2
+1 3 3 3
+1 4 4 4
+drop table t1,t2;
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+# using key1 for range access on t1 and also using index for sorting,
+# no filesort, rows should be 75 not 500
+explain SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1 key1 5 NULL 75 Using index condition; Using where
+1 SIMPLE t2 ref id id 5 test.t1.id 2
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id col id col
+0 2 0 0
+0 2 0 0
+1 2 1 1
+1 2 1 1
+2 2 2 2
+2 2 2 2
+3 2 3 3
+3 2 3 3
+4 2 4 4
+4 2 4 4
+drop table t1,t2;
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+#
+# End of 10.3 tests
+#
diff --git a/mysql-test/main/range.test b/mysql-test/main/range.test
index bd2299b..014916a 100644
--- a/mysql-test/main/range.test
+++ b/mysql-test/main/range.test
@@ -2053,3 +2053,185 @@ drop table t1;
--echo #
--echo # End of 10.2 tests
--echo #
+
+--echo #
+--echo # MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+--echo #
+
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+
+create table t1 (
+ id int NOT NULL,
+ subset_id int DEFAULT NULL,
+ PRIMARY KEY (id),
+ KEY t1_subset_id (subset_id));
+
+create table t2 (
+ id int,
+ col int NOT NULL,
+ key (id)
+);
+
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+--echo # with a subquery
+--echo # expected the same plan as above
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1
+ WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+--echo # non-mergable subquery
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+
+let $q=
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+--echo # with mergeable view
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q= SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+--echo # with non-mergeable view
+--echo # expected for t1: range access and rows = 4 (not 1000)
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+--echo # expected for t2 and for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+--echo # no range access expected for t1
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+--echo # expected for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+--echo # no range access expected for t1
+eval explain $q;
+eval $q;
+
+drop index id on t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+--echo # expected for t1: range access
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+--echo # expected impossible where after reading const tables
+eval explain $q;
+eval $q;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+--echo # expected impossible where after reading const tables
+eval explain $q;
+eval $q;
+
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+--echo # expected for t1: range access by idx (keylen=9)
+eval explain $q;
+eval $q;
+
+
+drop view v1,v2;
+drop table t1,t2;
+
+create table t1 (
+ id int NOT NULL,
+ subset_id int DEFAULT NULL,
+ KEY key1(id, subset_id),
+ KEY t1_subset_id (subset_id)
+);
+
+create table t2 (
+ id int NOT NULL,
+ col int NOT NULL,
+ key (id)
+);
+
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+--echo # expected for t1 :range access by index key1
+--echo # rows 4 instead of 500
+eval explain $q;
+eval $q;
+
+drop table t1,t2;
+
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+
+analyze table t1,t2;
+
+let $q=
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+--echo # using key1 for range access on t1 and also using index for sorting,
+--echo # no filesort, rows should be 75 not 500
+eval explain $q;
+eval $q;
+
+drop table t1,t2;
+
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result
index 6b5bf33..d484d51 100644
--- a/mysql-test/main/range_mrr_icp.result
+++ b/mysql-test/main/range_mrr_icp.result
@@ -3036,4 +3036,289 @@ drop table t1;
#
# End of 10.2 tests
#
+#
+# MDEV-15777: Use inferred IS NOT NULL predicates in the range optimizer
+#
+set @save_optimizer_switch= @@optimizer_switch;
+set @@optimizer_switch='not_null_range_scan=on';
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+PRIMARY KEY (id),
+KEY t1_subset_id (subset_id));
+create table t2 (
+id int,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select a,a from one_k limit 5;
+insert into t1 select a+5,NULL from one_k limit 995;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# with a subquery
+# expected the same plan as above
+explain SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 PRIMARY t2 ref id id 5 test.t1.subset_id 1 Using index; FirstMatch(t1)
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t2.id FROM t2);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+# non-mergable subquery
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.subset_id 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1000 Using temporary
+SELECT * FROM t1
+WHERE t1.subset_id IN (SELECT max(t2.id) FROM t2 group by t2.col);
+id subset_id
+0 0
+1 1
+2 2
+3 3
+4 4
+create view v1 as SELECT t2.id FROM t2;
+create view v2 as SELECT t2.id FROM t2 group by t2.col;
+# with mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using index
+SELECT * FROM t1, v1 where t1.subset_id=v1.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# with non-mergeable view
+# expected for t1: range access and rows = 4 (not 1000)
+explain SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 PRIMARY <derived2> ref key0 key0 5 test.t1.subset_id 10
+2 DERIVED t2 ALL NULL NULL NULL NULL 1000 Using temporary; Using filesort
+SELECT * FROM t1, v2 where t1.subset_id=v2.id;
+id subset_id id
+0 0 0
+1 1 1
+2 2 2
+3 3 3
+4 4 4
+# expected for t2 and for t1: range access
+explain SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range id id 5 NULL 3 Using index condition; Rowid-ordered scan
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where; Rowid-ordered scan; Using join buffer (flat, BNL join)
+SELECT * FROM t2 LEFT JOIN t1 ON t1.subset_id != 5 WHERE t2.id in (0,2,4);
+id col id subset_id
+0 0 0 0
+2 2 0 0
+4 4 0 0
+0 0 1 1
+2 2 1 1
+4 4 1 1
+0 0 2 2
+2 2 2 2
+4 4 2 2
+0 0 3 3
+2 2 3 3
+4 4 3 3
+0 0 4 4
+2 2 4 4
+4 4 4 4
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM t1 LEFT JOIN t2 ON t1.subset_id=t2.id LIMIT 10;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+5 NULL NULL NULL
+6 NULL NULL NULL
+7 NULL NULL NULL
+8 NULL NULL NULL
+9 NULL NULL NULL
+# expected for t1: range access
+explain SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE ten ALL NULL NULL NULL NULL 10
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using where; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+SELECT * FROM ten LEFT JOIN (t1,t2) ON ten.a=t2.col AND t1.subset_id=t2.id;
+a id subset_id id col
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+# no range access expected for t1
+explain SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1 Using where
+1 SIMPLE ten ALL NULL NULL NULL NULL 10 Using where
+SELECT * FROM t1 LEFT JOIN (t2,ten) ON ten.a=t2.col AND t1.subset_id=t2.id
+LIMIT 10;
+id subset_id id col a
+0 0 0 0 0
+1 1 1 1 1
+2 2 2 2 2
+3 3 3 3 3
+4 4 4 4 4
+5 NULL NULL NULL NULL
+6 NULL NULL NULL NULL
+7 NULL NULL NULL NULL
+8 NULL NULL NULL NULL
+9 NULL NULL NULL NULL
+drop index id on t2;
+# expected for t1: range access
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t1_subset_id t1_subset_id 5 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id;
+id subset_id id col
+0 0 0 0
+1 1 1 1
+2 2 2 2
+3 3 3 3
+4 4 4 4
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t1.subset_id IS NULL;
+id subset_id id col
+# expected impossible where after reading const tables
+explain SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
+SELECT * FROM t1,t2 WHERE t1.subset_id > t2.id AND t2.id IS NULL;
+id subset_id id col
+drop index t1_subset_id on t1;
+alter table t1 add column m int not null default 0;
+alter table t1 add index idx(m,subset_id);
+alter table t2 add index (id);
+update t1 set m = id mod 2;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1: range access by idx (keylen=9)
+explain SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range idx idx 9 NULL 4 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref id id 5 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.subset_id=t2.id and t1.m=0 ;
+id subset_id m id col
+0 0 0 0 0
+2 2 0 2 2
+4 4 0 4 4
+drop view v1,v2;
+drop table t1,t2;
+create table t1 (
+id int NOT NULL,
+subset_id int DEFAULT NULL,
+KEY key1(id, subset_id),
+KEY t1_subset_id (subset_id)
+);
+create table t2 (
+id int NOT NULL,
+col int NOT NULL,
+key (id)
+);
+insert into t1 select 1,a from one_k limit 5;
+insert into t1 select 1,NULL from one_k limit 495;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status Table is already up to date
+# expected for t1 :range access by index key1
+# rows 4 instead of 500
+explain SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1,t1_subset_id key1 9 NULL 4 Using where; Using index
+1 SIMPLE t2 ref id id 4 test.t1.subset_id 1
+SELECT * FROM t1,t2 WHERE t1.id>=1 and t1.subset_id=t2.id;
+id subset_id id col
+1 0 0 0
+1 1 1 1
+1 2 2 2
+1 3 3 3
+1 4 4 4
+drop table t1,t2;
+create table t1 (id int unsigned,col int, KEY key1(id));
+create table t2 (id int unsigned,col int DEFAULT NULL,key (id));
+insert into t1 select a,2 from one_k limit 50;
+insert into t1 select NULL,2 from one_k limit 450;
+insert into t2 select a,a from one_k;
+insert into t2 select a,a from one_k;
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+# using key1 for range access on t1 and also using index for sorting,
+# no filesort, rows should be 75 not 500
+explain SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range key1 key1 5 NULL 75 Using index condition; Using where
+1 SIMPLE t2 ref id id 5 test.t1.id 2
+SELECT * FROM t1,t2 WHERE t1.id=t2.id AND t1.col=2 ORDER BY t2.id LIMIT 10;
+id col id col
+0 2 0 0
+0 2 0 0
+1 2 1 1
+1 2 1 1
+2 2 2 2
+2 2 2 2
+3 2 3 3
+3 2 3 3
+4 2 4 4
+4 2 4 4
+drop table t1,t2;
+drop table ten,one_k;
+set @@optimizer_switch= @save_optimizer_switch;
+#
+# End of 10.3 tests
+#
set optimizer_switch=@mrr_icp_extra_tmp;
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
index 87c8379..ba40512 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
@@ -1,63 +1,63 @@
SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value;
@start_global_value
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
set global optimizer_switch=10;
set session optimizer_switch=5;
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
set global optimizer_switch="index_merge_sort_union=on";
set session optimizer_switch="index_merge=off";
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
set session optimizer_switch="default";
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,not_null_range_scan=off
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
Warnings:
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=on
set global optimizer_switch=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
set global optimizer_switch=1e1;
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
index 89e5fef..714b55c 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
@@ -2715,17 +2715,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,not_null_range_scan,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index ca875e7..dd9d9eb 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -2925,17 +2925,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,not_null_range_scan,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
diff --git a/sql/item.cc b/sql/item.cc
index 3584230..9c95611 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3556,6 +3556,16 @@ table_map Item_field::all_used_tables() const
}
+bool Item_field::find_not_null_fields(table_map allowed)
+{
+ if (field->table->const_table)
+ return false;
+ if (!get_depended_from() && field->real_maybe_null())
+ bitmap_set_bit(&field->table->tmp_set, field->field_index);
+ return false;
+}
+
+
/*
@Note thd->fatal_error can be set in case of OOM
*/
diff --git a/sql/item.h b/sql/item.h
index 2adc111..c2dbdb1 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1818,6 +1818,44 @@ class Item: public Value_source,
virtual bool set_fields_as_dependent_processor(void *arg) { return 0; }
/*============== End of Item processor list ======================*/
+ /*
+ Given a condition P from the WHERE clause or from an ON expression of
+ the processed SELECT S and a set of join tables from S marked in the
+ parameter 'allowed'={T} a call of P->find_not_null_fields({T}) has to
+ find the set fields {F} of the tables from 'allowed' such that:
+ - each field from {F} is declared as nullable
+ - each record of table t from {T} that contains NULL as the value for at
+ at least one field from {F} can be ignored when building the result set
+ for S
+ It is assumed here that the condition P is conjunctive and all its column
+ references belong to T.
+
+ Examples:
+ CREATE TABLE t1 (a int, b int);
+ CREATE TABLE t2 (a int, b int);
+
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b > 5;
+ A call of find_not_null_fields() for the whole WHERE condition and {t1,t2}
+ should find {t1.a,t1.b,t2.a}
+
+ SELECT * FROM t1 LEFT JOIN ON (t1.a=t2.a and t2.a > t2.b);
+ A call of find_not_null_fields() for the ON expression and {t2}
+ should find {t2.a,t2.b}
+
+ The function returns TRUE if it succeeds to prove that all records of
+ a table from {T} can be ignored. Otherwise it always returns FALSE.
+
+ Example:
+ SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t2.a IS NULL;
+ A call of find_not_null_fields() for the WHERE condition and {t1,t2}
+ will return TRUE.
+
+ It is assumed that the implementation of this virtual function saves
+ the info on the found set of fields in the structures associates with
+ tables from {T}.
+ */
+ virtual bool find_not_null_fields(table_map allowed) { return false; }
+
virtual Item *get_copy(THD *thd)=0;
bool cache_const_expr_analyzer(uchar **arg);
@@ -3079,6 +3117,7 @@ class Item_field :public Item_ident,
bool is_result_field() { return false; }
void save_in_result_field(bool no_conversions);
Item *get_tmp_table_item(THD *thd);
+ bool find_not_null_fields(table_map allowed);
bool collect_item_field_processor(void * arg);
bool add_field_to_set_processor(void * arg);
bool find_item_in_field_list_processor(void *arg);
@@ -4858,6 +4897,10 @@ class Item_ref :public Item_ident
{
return depended_from ? 0 : (*ref)->not_null_tables();
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return depended_from ? false : (*ref)->find_not_null_fields(allowed);
+ }
void save_in_result_field(bool no_conversions)
{
(*ref)->save_in_field(result_field, no_conversions);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 49e0a94..c4b43a7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1192,6 +1192,15 @@ bool Item_in_optimizer::eval_not_null_tables(void *opt_arg)
}
+bool Item_in_optimizer::find_not_null_fields(table_map allowed)
+{
+ if (!(~allowed & used_tables()) && is_top_level_item())
+ {
+ return args[0]->find_not_null_fields(allowed);
+ }
+ return false;
+}
+
void Item_in_optimizer::print(String *str, enum_query_type query_type)
{
restore_first_argument();
@@ -2035,7 +2044,17 @@ bool Item_func_between::eval_not_null_tables(void *opt_arg)
(args[1]->not_null_tables() &
args[2]->not_null_tables()));
return 0;
-}
+}
+
+
+bool Item_func_between::find_not_null_fields(table_map allowed)
+{
+ if (negated || !is_top_level_item() || (~allowed & used_tables()))
+ return false;
+ return args[0]->find_not_null_fields(allowed) ||
+ args[1]->find_not_null_fields(allowed) ||
+ args[3]->find_not_null_fields(allowed);
+}
bool Item_func_between::count_sargable_conds(void *arg)
@@ -4151,6 +4170,15 @@ Item_func_in::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_func_in::find_not_null_fields(table_map allowed)
+{
+ if (negated || !is_top_level_item() || (~allowed & used_tables()))
+ return 0;
+ return args[0]->find_not_null_fields(allowed);
+}
+
+
void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
@@ -4705,6 +4733,82 @@ Item_cond::eval_not_null_tables(void *opt_arg)
}
+/**
+ @note
+ This implementation of the virtual function find_not_null_fields()
+ infers null-rejectedness if fields from tables marked in 'allowed' from
+ this condition.
+ Currently only top level AND conjuncts that are not disjunctions are used
+ for the inference. Usage of any top level and-or formula with l OR levels
+ would require a stack of bitmaps for fields of the height h=2*l+1 So we
+ would have to allocate h-1 additional field bitmaps for each table marked
+ in 'allowed'.
+*/
+
+bool
+Item_cond::find_not_null_fields(table_map allowed)
+{
+ Item *item;
+ bool is_and_cond= functype() == Item_func::COND_AND_FUNC;
+ if (!is_and_cond)
+ {
+ /* Now only fields of top AND level conjuncts are taken into account */
+ return false;
+ }
+ uint isnull_func_cnt= 0;
+ List_iterator<Item> li(list);
+ while ((item=li++))
+ {
+ bool is_mult_eq= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::MULT_EQUAL_FUNC;
+ if (is_mult_eq)
+ {
+ if (!item->find_not_null_fields(allowed))
+ continue;
+ }
+
+ if (~allowed & item->used_tables())
+ continue;
+
+ /* It is assumed that all constant conjuncts are already eliminated */
+
+ /*
+ First infer null-rejectedness of fields from all conjuncts but
+ IS NULL predicates
+ */
+ bool isnull_func= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::ISNULL_FUNC;
+ if (isnull_func)
+ {
+ isnull_func_cnt++;
+ continue;
+ }
+ if (!item->find_not_null_fields(allowed))
+ continue;
+ }
+
+ /* Now try no get contradictions using IS NULL conjuncts */
+ if (isnull_func_cnt)
+ {
+ li.rewind();
+ while ((item=li++) && isnull_func_cnt)
+ {
+ if (~allowed & item->used_tables())
+ continue;
+
+ bool isnull_func= item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::ISNULL_FUNC;
+ if (isnull_func)
+ {
+ if (item->find_not_null_fields(allowed))
+ return true;
+ isnull_func_cnt--;
+ }
+ }
+ }
+ return false;
+}
+
void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
@@ -5148,6 +5252,19 @@ longlong Item_func_isnull::val_int()
}
+bool Item_func_isnull::find_not_null_fields(table_map allowed)
+{
+ if (!(~allowed & used_tables()) &&
+ args[0]->real_item()->type() == Item::FIELD_ITEM)
+ {
+ Field *field= ((Item_field *)(args[0]->real_item()))->field;
+ if (bitmap_is_set(&field->table->tmp_set, field->field_index))
+ return true;
+ }
+ return false;
+}
+
+
void Item_func_isnull::print(String *str, enum_query_type query_type)
{
if (const_item() && !args[0]->maybe_null &&
@@ -6734,6 +6851,48 @@ void Item_equal::update_used_tables()
}
+/**
+ @note
+ This multiple equality can contains elements belonging not to tables {T}
+ marked in 'allowed' . So we can ascertain null-rejectedness of field f
+ belonging to table t from {T} only if one of the following equality
+ predicate can be extracted from this multiple equality:
+ - f=const
+ - f=f' where f' is a field of some table from {T}
+*/
+
+bool Item_equal::find_not_null_fields(table_map allowed)
+{
+ if (!(allowed & used_tables()))
+ return false;
+ bool checked= false;
+ Item_equal_fields_iterator it(*this);
+ Item *item;
+ while ((item= it++))
+ {
+ if (~allowed & item->used_tables())
+ continue;
+ if ((with_const || checked) && !item->find_not_null_fields(allowed))
+ continue;
+ Item_equal_fields_iterator it1(*this);
+ Item *item1;
+ while ((item1= it1++) && item1 != item)
+ {
+ if (~allowed & item1->used_tables())
+ continue;
+ if (!item->find_not_null_fields(allowed) &&
+ !item1->find_not_null_fields(allowed))
+ {
+ checked= true;
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+
+
bool Item_equal::count_sargable_conds(void *arg)
{
SELECT_LEX *sel= (SELECT_LEX *) arg;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 7d99cbd..8f01e4f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -284,6 +284,7 @@ class Item_func_isnottrue : public Item_func_truth
Item_func_truth(thd, a, true, false) {}
~Item_func_isnottrue() {}
virtual const char* func_name() const { return "isnottrue"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnottrue>(thd, this); }
};
@@ -315,6 +316,7 @@ class Item_func_isnotfalse : public Item_func_truth
Item_func_truth(thd, a, false, false) {}
~Item_func_isnotfalse() {}
virtual const char* func_name() const { return "isnotfalse"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnotfalse>(thd, this); }
};
@@ -376,6 +378,7 @@ class Item_in_optimizer: public Item_bool_func
virtual void get_cache_parameters(List<Item> ¶meters);
bool is_top_level_item();
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool invisible_mode();
void reset_cache() { cache= NULL; }
@@ -571,6 +574,7 @@ class Item_func_xor :public Item_bool_func
void print(String *str, enum_query_type query_type)
{ Item_func::print_op(str, query_type); }
longlong val_int();
+ bool find_not_null_fields(table_map allowed) { return false; }
Item *neg_transformer(THD *thd);
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
@@ -592,6 +596,7 @@ class Item_func_not :public Item_bool_func
longlong val_int();
enum Functype functype() const { return NOT_FUNC; }
const char *func_name() const { return "not"; }
+ bool find_not_null_fields(table_map allowed) { return false; }
enum precedence precedence() const { return BANG_PRECEDENCE; }
Item *neg_transformer(THD *thd);
bool fix_fields(THD *, Item **);
@@ -736,6 +741,7 @@ class Item_func_equal :public Item_bool_rowready_func2
longlong val_int();
bool fix_length_and_dec();
table_map not_null_tables() const { return 0; }
+ bool find_not_null_fields(table_map allowed) { return false; }
enum Functype functype() const { return EQUAL_FUNC; }
enum Functype rev_functype() const { return EQUAL_FUNC; }
cond_result eq_cmp_result() const { return COND_TRUE; }
@@ -912,6 +918,7 @@ class Item_func_between :public Item_func_opt_neg
bool fix_length_and_dec_numeric(THD *);
virtual void print(String *str, enum_query_type query_type);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg);
void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
@@ -2396,6 +2403,7 @@ class Item_func_in :public Item_func_opt_neg,
const char *func_name() const { return "in"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg);
Item *get_copy(THD *thd)
@@ -2533,6 +2541,7 @@ class Item_func_isnull :public Item_func_null_predicate
COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
bool top_level);
table_map not_null_tables() const { return 0; }
+ bool find_not_null_fields(table_map allowed);
Item *neg_transformer(THD *thd);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isnull>(thd, this); }
@@ -2953,6 +2962,7 @@ class Item_cond :public Item_bool_func
Item *compile(THD *thd, Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
Item *build_clone(THD *thd);
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
@@ -3119,6 +3129,7 @@ class Item_equal: public Item_bool_func
eval_item= NULL;
}
void update_used_tables();
+ bool find_not_null_fields(table_map allowed);
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
bool link_item_fields,
COND_EQUAL **cond_equal_ref);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index a030d2f..41bbd2e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -403,6 +403,25 @@ Item_func::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_func::find_not_null_fields(table_map allowed)
+{
+ if (~allowed & used_tables())
+ return false;
+
+ Item **arg,**arg_end;
+ if (arg_count)
+ {
+ for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
+ {
+ if (!(*arg)->find_not_null_fields(allowed))
+ continue;
+ }
+ }
+ return false;
+}
+
+
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 6345dd4..325a796 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -210,6 +210,7 @@ class Item_func :public Item_func_or_sum
void traverse_cond(Cond_traverser traverser,
void * arg, traverse_order order);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
// bool is_expensive_processor(void *arg);
// virtual bool is_expensive() { return 0; }
inline void raise_numeric_overflow(const char *type_name)
@@ -671,6 +672,7 @@ class Item_func_case_expression: public Item_func_hybrid_field_type
Item_func_case_expression(THD *thd, List<Item> &list):
Item_func_hybrid_field_type(thd, list)
{ }
+ bool find_not_null_fields(table_map allowed) { return false; }
};
@@ -1759,6 +1761,10 @@ class Item_func_coercibility :public Item_long_func
not_null_tables_cache= 0;
return false;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{ return this; }
bool const_item() const { return true; }
@@ -2119,6 +2125,10 @@ class Item_udf_func :public Item_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool is_expensive() { return 1; }
virtual void print(String *str, enum_query_type query_type);
bool check_vcol_func_processor(void *arg)
@@ -2711,6 +2721,10 @@ class Item_func_match :public Item_real_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool fix_fields(THD *thd, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
/* The following should be safe, even if we compare doubles */
@@ -3000,6 +3014,10 @@ class Item_func_sp :public Item_func,
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
};
@@ -3103,6 +3121,10 @@ class Item_func_last_value :public Item_func
not_null_tables_cache= 0;
return 0;
}
+ bool find_not_null_fields(table_map allowed)
+ {
+ return false;
+ }
bool const_item() const { return 0; }
void evaluate_sideeffects();
void update_used_tables()
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 70a9fe5..0b55ae5 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -87,6 +87,25 @@ Item_row::eval_not_null_tables(void *opt_arg)
}
+bool
+Item_row::find_not_null_fields(table_map allowed)
+{
+ if (~allowed & used_tables())
+ return false;
+
+ Item **arg,**arg_end;
+ if (arg_count)
+ {
+ for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++)
+ {
+ if (!(*arg)->find_not_null_fields(allowed))
+ continue;
+ }
+ }
+ return false;
+}
+
+
void Item_row::cleanup()
{
DBUG_ENTER("Item_row::cleanup");
diff --git a/sql/item_row.h b/sql/item_row.h
index 0d6a6db..0efa29f 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -110,6 +110,7 @@ class Item_row: public Item,
}
Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
bool eval_not_null_tables(void *opt_arg);
+ bool find_not_null_fields(table_map allowed);
uint cols() const { return arg_count; }
Item* element_index(uint i) { return args[i]; }
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index ec7b3db..91103a5 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2399,6 +2399,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
uint idx;
double scan_time;
+ Item *notnull_cond= NULL;
DBUG_ENTER("SQL_SELECT::test_quick_select");
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
(ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables,
@@ -2412,6 +2413,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (keys_to_use.is_clear_all() || head->is_filled_at_execution())
DBUG_RETURN(0);
records= head->stat_records();
+ notnull_cond= head->notnull_cond;
if (!records)
records++; /* purecov: inspected */
scan_time= (double) records / TIME_FOR_COMPARE + 1;
@@ -2419,7 +2421,10 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
if (head->force_index)
scan_time= read_time= DBL_MAX;
if (limit < records)
+ {
read_time= (double) records + scan_time + 1; // Force to use index
+ notnull_cond= NULL;
+ }
possible_keys.clear_all();
@@ -2431,6 +2436,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
uchar buff[STACK_BUFF_ALLOC];
MEM_ROOT alloc;
SEL_TREE *tree= NULL;
+ SEL_TREE *notnull_cond_tree= NULL;
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
@@ -2539,6 +2545,9 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
TRP_GROUP_MIN_MAX *group_trp;
double best_read_time= read_time;
+ if (notnull_cond)
+ notnull_cond_tree= notnull_cond->get_mm_tree(¶m, ¬null_cond);
+
if (cond)
{
if ((tree= cond->get_mm_tree(¶m, &cond)))
@@ -2557,6 +2566,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
tree= NULL;
}
}
+ tree= tree_and(¶m, tree, notnull_cond_tree);
/*
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 2f37e11..ec7b2cc 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -222,6 +222,7 @@
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
+#define OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN (1ULL << 32)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0fbc4ba..dae2cd7 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -295,6 +295,14 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab);
static Item **get_sargable_cond(JOIN *join, TABLE *table);
+static
+bool build_notnull_conds_for_range_scans(JOIN *join, COND *cond,
+ table_map allowed);
+static
+void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join,
+ TABLE_LIST *nest_tbl);
+
+
#ifndef DBUG_OFF
/*
@@ -4907,6 +4915,9 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
}
}
+ join->join_tab= stat;
+ join->make_notnull_conds_for_range_scans();
+
/* Calc how many (possible) matched records in each table */
for (s=stat ; s < stat_end ; s++)
@@ -27572,6 +27583,280 @@ Item *remove_pushed_top_conjuncts(THD *thd, Item *cond)
return cond;
}
+
+/**
+ @brief
+ Construct not null conditions for provingly not nullable fields
+
+ @details
+ For each non-constant joined table the function creates a conjunction
+ of IS NOT NULL predicates containing a predicate for each field used
+ in the WHERE clause or an OR expression such that
+ - is declared as nullable
+ - for which it can proved be that it is null-rejected
+ - is a part of some index.
+ This conjunction could be anded with either the WHERE condition or with
+ an ON expression and the modified join query would produce the same
+ result set as the original one.
+ If a conjunction of IS NOT NULL predicates is constructed for an inner
+ table of an outer join OJ that is not an inner table of embedded outer
+ joins then it is to be anded with the ON expression of OJ.
+ The constructed conjunctions of IS NOT NULL predicates are attached
+ to the corresponding tables. They used for range analysis complementary
+ to other sargable range conditions.
+
+ @note
+ Let f be a field of the joined table t. In the context of the upper
+ paragraph field f is called null-rejected if any the following holds:
+
+ - t is a table of a top inner join and a conjunctive formula that rejects
+ rows with null values for f can be extracted from the WHERE condition
+
+ - t is an outer table of a top outer join operation and a conjunctive
+ formula over the outer tables of the outer join that rejects rows with
+ null values for can be extracted from the WHERE condition
+
+ - t is an outer table of a non-top outer join operation and a conjunctive
+ formula over the outer tables of the outer join that rejects rows with
+ null values for f can be extracted from the ON expression of the
+ embedding outer join
+
+ - the joined table is an inner table of a outer join operation and
+ a conjunctive formula over inner tables of the outer join that rejects
+ rows with null values for f can be extracted from the ON expression of
+ the outer join operation.
+
+ It is assumed above that all inner join nests have been eliminated and
+ that all possible conversions of outer joins into inner joins have been
+ already done.
+*/
+
+void JOIN::make_notnull_conds_for_range_scans()
+{
+ DBUG_ENTER("JOIN::make_notnull_conds_for_range_scans");
+
+
+ if (impossible_where ||
+ !optimizer_flag(thd, OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN))
+ {
+ /* Complementary range analysis is not needed */
+ DBUG_VOID_RETURN;
+ }
+
+ if (conds && build_notnull_conds_for_range_scans(this, conds,
+ conds->used_tables()))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ {
+ /*
+ Found a IS NULL conjunctive predicate for a null-rejected field
+ in the WHERE clause
+ */
+ conds= false_cond;
+ cond_equal= 0;
+ impossible_where= true;
+ }
+ DBUG_VOID_RETURN;
+ }
+
+ List_iterator<TABLE_LIST> li(*join_list);
+ TABLE_LIST *tbl;
+ while ((tbl= li++))
+ {
+ if (tbl->on_expr)
+ {
+ if (tbl->nested_join)
+ {
+ build_notnull_conds_for_inner_nest_of_outer_join(this, tbl);
+ }
+ else if (build_notnull_conds_for_range_scans(this, tbl->on_expr,
+ tbl->table->map))
+ {
+ /*
+ Found a IS NULL conjunctive predicate for a null-rejected field
+ of the inner table of an outer join with ON expression tbl->on_expr
+ */
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ tbl->on_expr= false_cond;
+ }
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ @brief
+ Build not null conditions for range scans of given join tables
+
+ @param join the join for whose tables not null conditions are to be built
+ @param cond the condition from which not null predicates are to be inferred
+ @param allowed the bit map of join tables to be taken into account
+
+ @details
+ For each join table t from the 'allowed' set of tables the function finds
+ all fields whose null-rejectedness can be inferred from null-rejectedness
+ of the condition cond. For each found field f from table t such that it
+ participates at least in one index on table t a NOT NULL predicate is
+ constructed and a conjunction of all such predicates is attached to t.
+ If when looking for null-rejecting fields of t it is discovered one of its
+ fields has to be null-rejected and there is IS NULL conjunctive top level
+ predicate for this field then the function immediately returns true.
+ The function uses the bitmap TABLE::tmp_set to mark found null-rejected
+ fields of table t.
+
+ @note
+ Currently only top level conjuncts without disjunctive sub-formulas are
+ are taken into account when looking for null-rejected fields.
+
+ @retval
+ true if a contradiction is inferred
+ false otherwise
+*/
+
+static
+bool build_notnull_conds_for_range_scans(JOIN *join, Item *cond,
+ table_map allowed)
+{
+ THD *thd= join->thd;
+
+ DBUG_ENTER("build_notnull_conds_for_range_scans");
+
+ for (JOIN_TAB *s= join->join_tab + join->const_tables ;
+ s < join->join_tab + join->table_count ; s++)
+ {
+ /* Clear all needed bitmaps to mark found fields */
+ if (allowed & s->table->map)
+ bitmap_clear_all(&s->table->tmp_set);
+ }
+
+ /*
+ Find all null-rejected fields assuming that cond is null-rejected and
+ only formulas over tables from 'allowed' are to be taken into account
+ */
+ if (cond->find_not_null_fields(allowed))
+ DBUG_RETURN(true);
+
+ /*
+ For each table t from 'allowed' build a conjunction of NOT NULL predicates
+ constructed for all found fields if they are included in some indexes.
+ If the construction of the conjunction succeeds attach the formula to
+ t->table->notnull_cond. The condition will be used to look for complementary
+ range scans.
+ */
+ for (JOIN_TAB *s= join->join_tab + join->const_tables ;
+ s < join->join_tab + join->table_count ; s++)
+ {
+ TABLE *tab= s->table;
+ List<Item> notnull_list;
+ Item *notnull_cond= 0;
+
+ if (!(allowed & tab->map))
+ continue;
+
+ for (Field** field_ptr= tab->field; *field_ptr; field_ptr++)
+ {
+ Field *field= *field_ptr;
+ if (field->part_of_key.is_clear_all())
+ continue;
+ if (!bitmap_is_set(&tab->tmp_set, field->field_index))
+ continue;
+ Item_field *field_item= new (thd->mem_root) Item_field(thd, field);
+ if (!field_item)
+ continue;
+ Item *isnotnull_item=
+ new (thd->mem_root) Item_func_isnotnull(thd, field_item);
+ if (!isnotnull_item)
+ continue;
+ if (notnull_list.push_back(isnotnull_item, thd->mem_root))
+ continue;
+ s->const_keys.merge(field->part_of_key);
+ }
+
+ switch (notnull_list.elements) {
+ case 0:
+ break;
+ case 1:
+ notnull_cond= notnull_list.head();
+ break;
+ default:
+ notnull_cond=
+ new (thd->mem_root) Item_cond_and(thd, notnull_list);
+ }
+ if (notnull_cond && !notnull_cond->fix_fields(thd, 0))
+ {
+ tab->notnull_cond= notnull_cond;
+ }
+ }
+ DBUG_RETURN(false);
+}
+
+
+/**
+ @brief
+ Build not null conditions for inner nest tables of an outer join
+
+ @param join the join for whose table nest not null conditions are to be built
+ @param nest_tbl the nest of the inner tables of an outer join
+
+ @details
+ The function assumes that nest_tbl is the nest of the inner tables of an
+ outer join and so an ON expression for this outer join is attached to
+ nest_tbl.
+ The function selects the tables of the nest_tbl that are not inner tables of
+ embedded outer joins and then it calls build_notnull_conds_for_range_scans()
+ for nest_tbl->on_expr and the bitmap for the selected tables. This call
+ finds all fields belonging to the selected tables whose null-rejectedness
+ can be inferred from the null-rejectedness of nest_tbl->on_expr. After this
+ the function recursively finds all null_rejected fields for the remaining
+ tables from the nest of nest_tbl.
+*/
+
+static
+void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join,
+ TABLE_LIST *nest_tbl)
+{
+ TABLE_LIST *tbl;
+ table_map used_tables= 0;
+ THD *thd= join->thd;
+ List_iterator<TABLE_LIST> li(nest_tbl->nested_join->join_list);
+
+ while ((tbl= li++))
+ {
+ if (!tbl->on_expr)
+ used_tables|= tbl->table->map;
+ }
+ if (used_tables &&
+ build_notnull_conds_for_range_scans(join, nest_tbl->on_expr, used_tables))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ nest_tbl->on_expr= false_cond;
+ }
+
+ li.rewind();
+ while ((tbl= li++))
+ {
+ if (tbl->on_expr)
+ {
+ if (tbl->nested_join)
+ {
+ build_notnull_conds_for_inner_nest_of_outer_join(join, tbl);
+ }
+ else if (build_notnull_conds_for_range_scans(join, tbl->on_expr,
+ tbl->table->map))
+ {
+ Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ if (false_cond)
+ tbl->on_expr= false_cond;
+ }
+ }
+ }
+}
+
+
/**
@} (end of group Query_Optimizer)
*/
diff --git a/sql/sql_select.h b/sql/sql_select.h
index dd823a7..2b40a41 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1749,6 +1749,7 @@ class JOIN :public Sql_alloc
void add_keyuses_for_splitting();
bool inject_best_splitting_cond(table_map remaining_tables);
bool fix_all_splittings_in_plan();
+ void make_notnull_conds_for_range_scans();
bool transform_in_predicates_into_in_subq(THD *thd);
private:
@@ -2343,7 +2344,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
extern bool test_if_ref(Item *,
Item_field *left_item,Item *right_item);
-inline bool optimizer_flag(THD *thd, uint flag)
+inline bool optimizer_flag(THD *thd, ulonglong flag)
{
return (thd->variables.optimizer_switch & flag);
}
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index b50f697..58b6da5 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2544,6 +2544,7 @@ export const char *optimizer_switch_names[]=
"orderby_uses_equalities",
"condition_pushdown_for_derived",
"split_materialized",
+ "not_null_range_scan",
"default",
NullS
};
diff --git a/sql/table.cc b/sql/table.cc
index 4805017..34fb6d5 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4658,6 +4658,8 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
(*f_ptr)->cond_selectivity= 1.0;
}
+ notnull_cond= 0;
+
DBUG_ASSERT(!file->keyread_enabled());
restore_record(this, s->default_values);
diff --git a/sql/table.h b/sql/table.h
index fa6cb70..47096aa 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1344,6 +1344,13 @@ struct TABLE
SplM_opt_info *spl_opt_info;
key_map keys_usable_for_splitting;
+ /*
+ Conjunction of the predicates of the form IS NOT NULL(f) where f refers to
+ a column of this TABLE such that they can be inferred from the condition
+ of the WHERE clause or from some ON expression of the processed select
+ and can be useful for range optimizer.
+ */
+ Item *notnull_cond;
inline void reset() { bzero((void*)this, sizeof(*this)); }
void init(THD *thd, TABLE_LIST *tl);
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
index a80e166..5d471d2 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
index 96d6814..a3c518a 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
index 43737c7..21dadb8 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
index 1dcb1ee..41c3f2b 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,not_null_range_scan=off
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
1
0
revision-id: 659f4e5955f1f794b3daef43a65230223f1af38d (mariadb-10.4.7-44-g659f4e5)
parent(s): 9487e0b259e7f410f5f93ae59851be60d6a5112c
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-08-30 09:58:24 -0700
message:
MDEV-20265 Unknown column in field list
This patch corrects the fix of the patch for mdev-19421 that resolved
the problem of parsing some embedded join expressions such as
t1 join t2 left join t3 on t2.a=t3.a on t1.a=t2.a.
Yet the patch contained a bug that prevented proper context analysis
of the queries where such expressions were used together with comma
separated table references in from clauses.
---
mysql-test/main/join.result | 326 ++++++++++++++++++++++++++++++++++++++++++++
mysql-test/main/join.test | 59 ++++++++
sql/sql_parse.cc | 101 ++++++++++----
3 files changed, 458 insertions(+), 28 deletions(-)
diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result
index edca290..f714785 100644
--- a/mysql-test/main/join.result
+++ b/mysql-test/main/join.result
@@ -2935,6 +2935,332 @@ NULL NULL NULL 9
NULL NULL NULL 5
drop table t1,t2,t3,t4,s1,s2;
#
+# MDEV-20265: Mix of comma joins with JOIN expressions
+# (correction of the fix for MDEV-19421)
+# MDEV-20330: duplicate
+#
+create table t1 (a int);
+insert into t1 values (7), (5), (3);
+create table t2 (a int);
+insert into t2 values (5), (1), (7);
+create table t3 (a int);
+insert into t3 values (2), (7), (3);
+create table t4 (a int);
+insert into t4 values (4), (7), (9), (5);
+create table t5 (a int);
+insert into t5 values (3), (7), (9), (2);
+explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a
+from t1, t2 join t3 left join t4 on t3.a=t4.a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join)
+1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (incremental, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a` from `test`.`t1` join `test`.`t2` join `test`.`t3` left join `test`.`t4` on(`test`.`t4`.`a` = `test`.`t3`.`a`) where 1
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a
+from t1, t2 join t3 left join t4 on t3.a=t4.a;
+t1_a t2_a t3_a t4_a
+7 5 7 7
+5 5 7 7
+3 5 7 7
+7 1 7 7
+5 1 7 7
+3 1 7 7
+7 7 7 7
+5 7 7 7
+3 7 7 7
+7 5 2 NULL
+5 5 2 NULL
+3 5 2 NULL
+7 1 2 NULL
+5 1 2 NULL
+3 1 2 NULL
+7 7 2 NULL
+5 7 2 NULL
+3 7 2 NULL
+7 5 3 NULL
+5 5 3 NULL
+3 5 3 NULL
+7 1 3 NULL
+5 1 3 NULL
+3 1 3 NULL
+7 7 3 NULL
+5 7 3 NULL
+3 7 3 NULL
+explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a
+from t1, t2 join t3 right join t4 on t3.a=t4.a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
+1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (flat, BNL join)
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join)
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (incremental, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a` from `test`.`t1` join `test`.`t4` left join (`test`.`t2` join `test`.`t3`) on(`test`.`t3`.`a` = `test`.`t4`.`a`) where 1
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a
+from t1, t2 join t3 right join t4 on t3.a=t4.a;
+t1_a t2_a t3_a t4_a
+7 5 7 7
+5 5 7 7
+3 5 7 7
+7 1 7 7
+5 1 7 7
+3 1 7 7
+7 7 7 7
+5 7 7 7
+3 7 7 7
+7 NULL NULL 4
+5 NULL NULL 4
+3 NULL NULL 4
+7 NULL NULL 9
+5 NULL NULL 9
+3 NULL NULL 9
+7 NULL NULL 5
+5 NULL NULL 5
+3 NULL NULL 5
+explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1, t2 join t3 join t4 left join t5 on t4.a=t5.a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (flat, BNL join)
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join)
+1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (incremental, BNL join)
+1 SIMPLE t5 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (incremental, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a`,`test`.`t5`.`a` AS `t5_a` from `test`.`t1` join `test`.`t2` join `test`.`t3` join `test`.`t4` left join `test`.`t5` on(`test`.`t5`.`a` = `test`.`t4`.`a`) where 1
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1, t2 join t3 join t4 left join t5 on t4.a=t5.a;
+t1_a t2_a t3_a t4_a t5_a
+7 5 2 7 7
+5 5 2 7 7
+3 5 2 7 7
+7 1 2 7 7
+5 1 2 7 7
+3 1 2 7 7
+7 7 2 7 7
+5 7 2 7 7
+3 7 2 7 7
+7 5 7 7 7
+5 5 7 7 7
+3 5 7 7 7
+7 1 7 7 7
+5 1 7 7 7
+3 1 7 7 7
+7 7 7 7 7
+5 7 7 7 7
+3 7 7 7 7
+7 5 3 7 7
+5 5 3 7 7
+3 5 3 7 7
+7 1 3 7 7
+5 1 3 7 7
+3 1 3 7 7
+7 7 3 7 7
+5 7 3 7 7
+3 7 3 7 7
+7 5 2 9 9
+5 5 2 9 9
+3 5 2 9 9
+7 1 2 9 9
+5 1 2 9 9
+3 1 2 9 9
+7 7 2 9 9
+5 7 2 9 9
+3 7 2 9 9
+7 5 7 9 9
+5 5 7 9 9
+3 5 7 9 9
+7 1 7 9 9
+5 1 7 9 9
+3 1 7 9 9
+7 7 7 9 9
+5 7 7 9 9
+3 7 7 9 9
+7 5 3 9 9
+5 5 3 9 9
+3 5 3 9 9
+7 1 3 9 9
+5 1 3 9 9
+3 1 3 9 9
+7 7 3 9 9
+5 7 3 9 9
+3 7 3 9 9
+7 5 2 4 NULL
+5 5 2 4 NULL
+3 5 2 4 NULL
+7 1 2 4 NULL
+5 1 2 4 NULL
+3 1 2 4 NULL
+7 7 2 4 NULL
+5 7 2 4 NULL
+3 7 2 4 NULL
+7 5 7 4 NULL
+5 5 7 4 NULL
+3 5 7 4 NULL
+7 1 7 4 NULL
+5 1 7 4 NULL
+3 1 7 4 NULL
+7 7 7 4 NULL
+5 7 7 4 NULL
+3 7 7 4 NULL
+7 5 3 4 NULL
+5 5 3 4 NULL
+3 5 3 4 NULL
+7 1 3 4 NULL
+5 1 3 4 NULL
+3 1 3 4 NULL
+7 7 3 4 NULL
+5 7 3 4 NULL
+3 7 3 4 NULL
+7 5 2 5 NULL
+5 5 2 5 NULL
+3 5 2 5 NULL
+7 1 2 5 NULL
+5 1 2 5 NULL
+3 1 2 5 NULL
+7 7 2 5 NULL
+5 7 2 5 NULL
+3 7 2 5 NULL
+7 5 7 5 NULL
+5 5 7 5 NULL
+3 5 7 5 NULL
+7 1 7 5 NULL
+5 1 7 5 NULL
+3 1 7 5 NULL
+7 7 7 5 NULL
+5 7 7 5 NULL
+3 7 7 5 NULL
+7 5 3 5 NULL
+5 5 3 5 NULL
+3 5 3 5 NULL
+7 1 3 5 NULL
+5 1 3 5 NULL
+3 1 3 5 NULL
+7 7 3 5 NULL
+5 7 3 5 NULL
+3 7 3 5 NULL
+explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1, t2 join t3 join t4 right join t5 on t4.a=t5.a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
+1 SIMPLE t5 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (flat, BNL join)
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join)
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join)
+1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (incremental, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a`,`test`.`t5`.`a` AS `t5_a` from `test`.`t1` join `test`.`t5` left join (`test`.`t2` join `test`.`t3` join `test`.`t4`) on(`test`.`t4`.`a` = `test`.`t5`.`a`) where 1
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1, t2 join t3 join t4 right join t5 on t4.a=t5.a;
+t1_a t2_a t3_a t4_a t5_a
+7 5 2 7 7
+5 5 2 7 7
+3 5 2 7 7
+7 1 2 7 7
+5 1 2 7 7
+3 1 2 7 7
+7 7 2 7 7
+5 7 2 7 7
+3 7 2 7 7
+7 5 7 7 7
+5 5 7 7 7
+3 5 7 7 7
+7 1 7 7 7
+5 1 7 7 7
+3 1 7 7 7
+7 7 7 7 7
+5 7 7 7 7
+3 7 7 7 7
+7 5 3 7 7
+5 5 3 7 7
+3 5 3 7 7
+7 1 3 7 7
+5 1 3 7 7
+3 1 3 7 7
+7 7 3 7 7
+5 7 3 7 7
+3 7 3 7 7
+7 5 2 9 9
+5 5 2 9 9
+3 5 2 9 9
+7 1 2 9 9
+5 1 2 9 9
+3 1 2 9 9
+7 7 2 9 9
+5 7 2 9 9
+3 7 2 9 9
+7 5 7 9 9
+5 5 7 9 9
+3 5 7 9 9
+7 1 7 9 9
+5 1 7 9 9
+3 1 7 9 9
+7 7 7 9 9
+5 7 7 9 9
+3 7 7 9 9
+7 5 3 9 9
+5 5 3 9 9
+3 5 3 9 9
+7 1 3 9 9
+5 1 3 9 9
+3 1 3 9 9
+7 7 3 9 9
+5 7 3 9 9
+3 7 3 9 9
+7 NULL NULL NULL 3
+5 NULL NULL NULL 3
+3 NULL NULL NULL 3
+7 NULL NULL NULL 2
+5 NULL NULL NULL 2
+3 NULL NULL NULL 2
+explain extended select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1 left join t2 on t1.a=t2.a, t3 join t4 right join t5 on t4.a=t5.a;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
+1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t5 ALL NULL NULL NULL NULL 4 100.00 Using join buffer (incremental, BNL join)
+1 SIMPLE t3 ALL NULL NULL NULL NULL 3 100.00 Using join buffer (incremental, BNL join)
+1 SIMPLE t4 ALL NULL NULL NULL NULL 4 100.00 Using where; Using join buffer (incremental, BNL join)
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `t1_a`,`test`.`t2`.`a` AS `t2_a`,`test`.`t3`.`a` AS `t3_a`,`test`.`t4`.`a` AS `t4_a`,`test`.`t5`.`a` AS `t5_a` from `test`.`t1` left join `test`.`t2` on(`test`.`t2`.`a` = `test`.`t1`.`a`) join `test`.`t5` left join (`test`.`t3` join `test`.`t4`) on(`test`.`t4`.`a` = `test`.`t5`.`a`) where 1
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1 left join t2 on t1.a=t2.a, t3 join t4 right join t5 on t4.a=t5.a;
+t1_a t2_a t3_a t4_a t5_a
+5 5 2 7 7
+7 7 2 7 7
+3 NULL 2 7 7
+5 5 7 7 7
+7 7 7 7 7
+3 NULL 7 7 7
+5 5 3 7 7
+7 7 3 7 7
+3 NULL 3 7 7
+5 5 2 9 9
+7 7 2 9 9
+3 NULL 2 9 9
+5 5 7 9 9
+7 7 7 9 9
+3 NULL 7 9 9
+5 5 3 9 9
+7 7 3 9 9
+3 NULL 3 9 9
+5 5 NULL NULL 3
+7 7 NULL NULL 3
+3 NULL NULL NULL 3
+5 5 NULL NULL 2
+7 7 NULL NULL 2
+3 NULL NULL NULL 2
+drop table t1,t2,t3,t4,t5;
+select a.a
+from (select 1 as a) a,
+(select 2 as b) b
+cross join
+(select 3 as c) c
+left join
+(select 4 as d) d
+on 1;
+a
+1
+#
# End of MariaDB 5.5 tests
#
#
diff --git a/mysql-test/main/join.test b/mysql-test/main/join.test
index b36b0ac..cf24fb0 100644
--- a/mysql-test/main/join.test
+++ b/mysql-test/main/join.test
@@ -1615,6 +1615,65 @@ eval $q;
drop table t1,t2,t3,t4,s1,s2;
--echo #
+--echo # MDEV-20265: Mix of comma joins with JOIN expressions
+--echo # (correction of the fix for MDEV-19421)
+--echo # MDEV-20330: duplicate
+--echo #
+
+create table t1 (a int);
+insert into t1 values (7), (5), (3);
+create table t2 (a int);
+insert into t2 values (5), (1), (7);
+create table t3 (a int);
+insert into t3 values (2), (7), (3);
+create table t4 (a int);
+insert into t4 values (4), (7), (9), (5);
+create table t5 (a int);
+insert into t5 values (3), (7), (9), (2);
+
+
+let $q=
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a
+from t1, t2 join t3 left join t4 on t3.a=t4.a;
+eval explain extended $q;
+eval $q;
+
+let $q=
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a
+from t1, t2 join t3 right join t4 on t3.a=t4.a;
+eval explain extended $q;
+eval $q;
+
+let $q=
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1, t2 join t3 join t4 left join t5 on t4.a=t5.a;
+eval explain extended $q;
+eval $q;
+
+let $q=
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1, t2 join t3 join t4 right join t5 on t4.a=t5.a;
+eval explain extended $q;
+eval $q;
+
+let $q=
+select t1.a as t1_a, t2.a as t2_a, t3.a as t3_a, t4.a as t4_a, t5.a as t5_a
+from t1 left join t2 on t1.a=t2.a, t3 join t4 right join t5 on t4.a=t5.a;
+eval explain extended $q;
+eval $q;
+
+drop table t1,t2,t3,t4,t5;
+
+select a.a
+from (select 1 as a) a,
+ (select 2 as b) b
+ cross join
+ (select 3 as c) c
+ left join
+ (select 4 as d) d
+ on 1;
+
+--echo #
--echo # End of MariaDB 5.5 tests
--echo #
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index ccc1806..1f612ff 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -8324,9 +8324,9 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
DBUG_ENTER("nest_last_join");
TABLE_LIST *head= join_list->head();
- if (head->nested_join && head->nested_join->nest_type & REBALANCED_NEST)
+ if (head->nested_join && (head->nested_join->nest_type & REBALANCED_NEST))
{
- join_list->empty();
+ head= join_list->pop();
DBUG_RETURN(head);
}
@@ -8410,13 +8410,13 @@ void st_select_lex::add_joined_table(TABLE_LIST *table)
context and right-associative in another context.
In this query
- SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a (Q1)
+ SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a (Q1)
JOIN is left-associative and the query Q1 is interpreted as
- SELECT * FROM (t1 JOIN t2) LEFT JOIN t3 ON t2.a=t3.a.
+ SELECT * FROM (t1 JOIN t2) LEFT JOIN t3 ON t2.a=t3.a.
While in this query
- SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.b=t2.b (Q2)
+ SELECT * FROM t1 JOIN t2 LEFT JOIN t3 ON t2.a=t3.a ON t1.b=t2.b (Q2)
JOIN is right-associative and the query Q2 is interpreted as
- SELECT * FROM t1 JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a) ON t1.b=t2.b
+ SELECT * FROM t1 JOIN (t2 LEFT JOIN t3 ON t2.a=t3.a) ON t1.b=t2.b
JOIN is right-associative if it is used with ON clause or with USING clause.
Otherwise it is left-associative.
@@ -8462,9 +8462,9 @@ void st_select_lex::add_joined_table(TABLE_LIST *table)
J LJ - ON
/ \ / \
- t1 LJ - ON (TQ3*) => J t2
- / \ / \
- t3 t2 t1 t3
+ t1 LJ - ON (TQ3*) => t3 J
+ / \ / \
+ t3 t2 t1 t2
With several left associative JOINs
SELECT * FROM t1 JOIN t2 JOIN t3 LEFT JOIN t4 ON t3.a=t4.a (Q4)
@@ -8472,15 +8472,15 @@ void st_select_lex::add_joined_table(TABLE_LIST *table)
J1 LJ - ON
/ \ / \
- t1 LJ - ON J2 t4
+ t1 J2 J2 t4
/ \ => / \
- J2 t4 J1 t3
- / \ / \
- t2 t3 t1 t2
+ t2 LJ - ON J1 t3
+ / \ / \
+ t3 t4 t1 t2
- Here's another example:
- SELECT *
- FROM t1 JOIN t2 LEFT JOIN t3 JOIN t4 ON t3.a=t4.a ON t2.b=t3.b (Q5)
+ Here's another example:
+ SELECT *
+ FROM t1 JOIN t2 LEFT JOIN t3 JOIN t4 ON t3.a=t4.a ON t2.b=t3.b (Q5)
J LJ - ON
/ \ / \
@@ -8490,15 +8490,58 @@ void st_select_lex::add_joined_table(TABLE_LIST *table)
/ \
t3 t4
- If the transformed nested join node node is a natural join node like in
- the following query
- SELECT * FROM t1 JOIN t2 LEFT JOIN t3 USING(a) (Q6)
- the transformation additionally has to take care about setting proper
- references in the field natural_join for both operands of the natural
- join operation.
- The function also has to change the name resolution context for ON
- expressions used in the transformed join expression to take into
- account the tables of the left_op node.
+ If the transformed nested join node node is a natural join node like in
+ the following query
+ SELECT * FROM t1 JOIN t2 LEFT JOIN t3 USING(a) (Q6)
+ the transformation additionally has to take care about setting proper
+ references in the field natural_join for both operands of the natural
+ join operation.
+
+ The queries that combine comma syntax for join operation with
+ JOIN expression require a special care. Consider the query
+ SELECT * FROM t1, t2 JOIN t3 LEFT JOIN t4 ON t3.a=t4.a (Q7)
+ This query is equivalent to the query
+ SELECT * FROM (t1, t2) JOIN t3 LEFT JOIN t4 ON t3.a=t4.a
+ The latter is transformed in the same way as query Q1
+
+ J LJ - ON
+ / \ / \
+ (t1,t2) LJ - ON => J t4
+ / \ / \
+ t3 t4 (t1,t2) t3
+
+ A transformation similar to the transformation for Q3 is done for
+ the following query with RIGHT JOIN
+ SELECT * FROM t1, t2 JOIN t3 RIGHT JOIN t4 ON t3.a=t4.a (Q8)
+
+ J LJ - ON
+ / \ / \
+ t3 LJ - ON => t4 J
+ / \ / \
+ t4 (t1,t2) (t1,t2) t3
+
+ The function also has to change the name resolution context for ON
+ expressions used in the transformed join expression to take into
+ account the tables of the left_op node.
+
+ TODO:
+ A more elegant solution would be to implement the transformation that
+ eliminates nests for cross join operations. For Q7 it would work like this:
+
+ J LJ - ON
+ / \ / \
+ (t1,t2) LJ - ON => (t1,t2,t3) t4
+ / \
+ t3 t4
+
+ For Q8 with RIGHT JOIN the transformation would work similarly:
+
+ J LJ - ON
+ / \ / \
+ t3 LJ - ON => t4 (t1,t2,t3)
+ / \
+ t4 (t1,t2)
+
*/
bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op,
@@ -8523,11 +8566,9 @@ bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op,
}
TABLE_LIST *tbl;
- List<TABLE_LIST> *jl= &right_op->nested_join->join_list;
+ List<TABLE_LIST> *right_op_jl= right_op->join_list;
TABLE_LIST *cj_nest;
- add_joined_table(right_op);
-
/*
Create the node NJ for a new nested join for the future inclusion
of left_op in it. Initially the nest is empty.
@@ -8542,6 +8583,8 @@ bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op,
List<TABLE_LIST> *cjl= &cj_nest->nested_join->join_list;
cjl->empty();
+ List<TABLE_LIST> *jl= &right_op->nested_join->join_list;
+ DBUG_ASSERT(jl->elements == 2);
/* Look for the left most node tbl of the right_op tree */
for ( ; ; )
{
@@ -8614,6 +8657,8 @@ bool st_select_lex::add_cross_joined_table(TABLE_LIST *left_op,
create a new top level nested join node.
*/
right_op->nested_join->nest_type|= REBALANCED_NEST;
+ if (unlikely(right_op_jl->push_front(right_op)))
+ DBUG_RETURN(true);
DBUG_RETURN(false);
}
1
0
[Commits] 52c0d6f1dfb: MDEV-20109: Optimizer ignores distinct key created for materialized...
by psergey 29 Aug '19
by psergey 29 Aug '19
29 Aug '19
revision-id: 52c0d6f1dfb0a53156018e1f601fcaae0d334d33 (mariadb-10.4.7-32-g52c0d6f1dfb)
parent(s): 235cf969d21ba3406a9325d952fda47c589e58d6
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-08-29 14:00:25 +0300
message:
MDEV-20109: Optimizer ignores distinct key created for materialized...
Sj_materialization_picker::check_qep(): fix error in cost/fanout
calculations:
- for each join prefix, add #prefix_rows / TIME_FOR_COMPARE to the cost,
like best_extension_by_limited_search does
- Remove the fanout produced by the subquery tables.
optimize_wo_join_buffering() (used by LooseScan and FirstMatch)
- also add #prefix_rows / TIME_FOR_COMPARE to the cost of each prefix.
---
mysql-test/main/analyze_stmt_privileges2.result | 142 ++++++++--------
mysql-test/main/cte_nonrecursive.result | 24 +--
mysql-test/main/group_by.result | 3 +-
mysql-test/main/index_merge_myisam.result | 5 +-
mysql-test/main/innodb_ext_key.result | 8 +-
mysql-test/main/opt_trace.result | 214 +++++++++++++++---------
mysql-test/main/opt_tvc.result | 72 ++++----
mysql-test/main/subselect.result | 8 +-
mysql-test/main/subselect3.result | 18 +-
mysql-test/main/subselect3_jcl6.result | 20 +--
mysql-test/main/subselect_mat.result | 16 +-
mysql-test/main/subselect_no_mat.result | 10 +-
mysql-test/main/subselect_no_scache.result | 8 +-
mysql-test/main/subselect_sj.result | 60 +++++--
mysql-test/main/subselect_sj.test | 25 +++
mysql-test/main/subselect_sj2.result | 23 +--
mysql-test/main/subselect_sj2_jcl6.result | 22 +--
mysql-test/main/subselect_sj2_mat.result | 51 +++---
mysql-test/main/subselect_sj_jcl6.result | 61 ++++---
mysql-test/main/subselect_sj_mat.result | 26 +--
mysql-test/main/table_value_constr.result | 24 +--
sql/opt_subselect.cc | 7 +-
sql/sql_class.h | 5 +-
sql/sql_select.cc | 15 +-
24 files changed, 507 insertions(+), 360 deletions(-)
diff --git a/mysql-test/main/analyze_stmt_privileges2.result b/mysql-test/main/analyze_stmt_privileges2.result
index cf38810b598..f269aaf540b 100644
--- a/mysql-test/main/analyze_stmt_privileges2.result
+++ b/mysql-test/main/analyze_stmt_privileges2.result
@@ -376,13 +376,13 @@ SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 0.00 100.00 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
#------------------------------------------------------------------------
# I/R/U/D/S on the inner view
@@ -491,14 +491,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -598,14 +598,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 12 12.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 12.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the table
@@ -1591,14 +1591,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything: SELECT access to the column `a`
@@ -1708,14 +1708,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant SELECT, INSERT, UPDATE, DELETE on the table
@@ -1940,14 +1940,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -2048,14 +2048,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#########################################################################
# Inner view permission tests
@@ -2697,14 +2697,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 14 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 14 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 14 14.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 14 14.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -2804,14 +2804,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 18 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 18 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 18 18.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 18 18.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the inner view
@@ -3987,14 +3987,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 35 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 35 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 35 35.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 35 35.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -4094,14 +4094,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#########################################################################
# Outer view permission tests
@@ -4614,14 +4614,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the outer view
@@ -5221,14 +5221,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 44 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 44 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 44 44.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 44 44.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
disconnect con1;
connection default;
DROP USER 'privtest'@localhost;
diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result
index 2556fd4b06b..12a7e2ea789 100644
--- a/mysql-test/main/cte_nonrecursive.result
+++ b/mysql-test/main/cte_nonrecursive.result
@@ -1159,9 +1159,9 @@ with cte as
union
(select a from t1 where a < 2);
a
-7
-5
4
+5
+7
1
prepare stmt from "with cte as
(select a from t1 where a between 4 and 7 group by a)
@@ -1170,15 +1170,15 @@ union
(select a from t1 where a < 2)";
execute stmt;
a
-7
-5
4
+5
+7
1
execute stmt;
a
-7
-5
4
+5
+7
1
deallocate prepare stmt;
with cte as
@@ -1188,9 +1188,9 @@ union
(select a from cte where exists( select a from t1 where cte.a=t1.a ));
a
1
-7
-5
4
+5
+7
prepare stmt from "with cte as
(select a from t1 where a between 4 and 7 group by a)
(select a from t1 where a < 2)
@@ -1199,15 +1199,15 @@ union
execute stmt;
a
1
-7
-5
4
+5
+7
execute stmt;
a
1
-7
-5
4
+5
+7
deallocate prepare stmt;
with cte as
(select a from t1 where a between 4 and 7)
diff --git a/mysql-test/main/group_by.result b/mysql-test/main/group_by.result
index 2eaec8a08b4..44ebce66b22 100644
--- a/mysql-test/main/group_by.result
+++ b/mysql-test/main/group_by.result
@@ -1608,7 +1608,8 @@ EXPLAIN SELECT 1 FROM t2 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index a a 5 NULL 4 Using index
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t2)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t1 ALL NULL NULL NULL NULL 144
SET optimizer_switch=@save_optimizer_switch;
DROP TABLE t1, t2;
CREATE TABLE t1(
diff --git a/mysql-test/main/index_merge_myisam.result b/mysql-test/main/index_merge_myisam.result
index 484ee626b98..7e57c916d04 100644
--- a/mysql-test/main/index_merge_myisam.result
+++ b/mysql-test/main/index_merge_myisam.result
@@ -558,8 +558,9 @@ where exists (select 1 from t2, t3
where t2.a=t1.a and (t3.a=t2.b or t3.b=t2.b or t3.b=t2.b+1));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
-1 PRIMARY t3 ALL a,b NULL NULL NULL 1002 Range checked for each record (index map: 0x3); FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
+2 MATERIALIZED t3 ALL a,b NULL NULL NULL 1002 Range checked for each record (index map: 0x3)
select * from t1
where exists (select 1 from t2, t3
where t2.a=t1.a and (t3.a=t2.b or t3.b=t2.b or t3.b=t2.b+1));
diff --git a/mysql-test/main/innodb_ext_key.result b/mysql-test/main/innodb_ext_key.result
index b4572174fcb..2ec3a9ae951 100644
--- a/mysql-test/main/innodb_ext_key.result
+++ b/mysql-test/main/innodb_ext_key.result
@@ -732,8 +732,8 @@ SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index a,b b 7 NULL 10 Using index
-1 PRIMARY t1 ref b b 3 test.t.b 2 Using index
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t)
+1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; Start temporary
+1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
@@ -745,8 +745,8 @@ SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index a,b b 7 NULL 10 Using index
-1 PRIMARY t1 ref b b 3 test.t.b 2 Using index
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t)
+1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; Start temporary
+1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 518da2888cc..5dfe3241862 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -4308,11 +4308,11 @@ explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_
t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t_outer_1 ALL NULL NULL NULL NULL 3
-1 PRIMARY t_inner_1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY t_inner_2 ALL NULL NULL NULL NULL 9 FirstMatch(t_outer_1); Using join buffer (incremental, BNL join)
+1 PRIMARY t_inner_1 ALL NULL NULL NULL NULL 3 Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY t_inner_2 ALL NULL NULL NULL NULL 9 End temporary; Using join buffer (incremental, BNL join)
+1 PRIMARY t_inner_4 ALL NULL NULL NULL NULL 3 Start temporary; Using join buffer (incremental, BNL join)
1 PRIMARY t_outer_2 ALL NULL NULL NULL NULL 9 Using join buffer (incremental, BNL join)
-1 PRIMARY t_inner_4 ALL NULL NULL NULL NULL 3 Using join buffer (incremental, BNL join)
-1 PRIMARY t_inner_3 ALL NULL NULL NULL NULL 9 Using where; FirstMatch(t_outer_2); Using join buffer (incremental, BNL join)
+1 PRIMARY t_inner_3 ALL NULL NULL NULL NULL 9 Using where; End temporary; Using join buffer (incremental, BNL join)
select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_inner_1.a from t2 t_inner_2, t1 t_inner_1) and
@@ -4580,7 +4580,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 27,
- "cost_for_plan": 34.174,
+ "cost_for_plan": 44.641,
"rest_of_plan": [
{
"plan_prefix": [
@@ -4601,7 +4601,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 81,
- "cost_for_plan": 52.379,
+ "cost_for_plan": 62.846,
"rest_of_plan": [
{
"plan_prefix": [
@@ -4623,7 +4623,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 729,
- "cost_for_plan": 200.19
+ "cost_for_plan": 210.66
}
]
},
@@ -4646,7 +4646,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 243,
- "cost_for_plan": 84.79,
+ "cost_for_plan": 95.256,
"pruned_by_heuristic": true
}
]
@@ -4665,7 +4665,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 9,
- "cost_for_plan": 30.564,
+ "cost_for_plan": 41.031,
"rest_of_plan": [
{
"plan_prefix": [
@@ -4686,7 +4686,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 81,
- "cost_for_plan": 48.779,
+ "cost_for_plan": 59.246,
"rest_of_plan": [
{
"plan_prefix": [
@@ -4708,8 +4708,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 729,
- "cost_for_plan": 196.59,
- "pruned_by_cost": true
+ "cost_for_plan": 207.06
}
]
},
@@ -4732,7 +4731,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 81,
- "cost_for_plan": 48.779,
+ "cost_for_plan": 59.246,
"pruned_by_heuristic": true
}
]
@@ -4751,7 +4750,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 27,
- "cost_for_plan": 34.174,
+ "cost_for_plan": 44.641,
"pruned_by_heuristic": true
}
]
@@ -4787,7 +4786,76 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 172.44,
- "pruned_by_cost": true
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_2"
+ ],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 81,
+ "cost_for_plan": 304.05,
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_2",
+ "t_inner_4"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 729,
+ "cost_for_plan": 451.86,
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_2"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 243,
+ "cost_for_plan": 336.46,
+ "pruned_by_cost": true
+ }
+ ]
},
{
"plan_prefix": ["t_outer_1", "t_inner_1", "t_outer_2"],
@@ -4866,7 +4934,52 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 172.44,
- "pruned_by_heuristic": true
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_3"
+ ],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 2187,
+ "cost_for_plan": 611.85,
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_3"
+ ],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 6561,
+ "cost_for_plan": 1486.7,
+ "pruned_by_cost": true
+ }
+ ]
}
]
},
@@ -5303,70 +5416,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
{
- "fix_semijoin_strategies_for_picked_join_order": [
- {
- "semi_join_strategy": "firstmatch",
- "join_order": [
- {
- "table": "t_inner_4"
- },
- "best_access_path": {
- "considered_access_paths": [
- {
- "access_type": "scan",
- "resulting_rows": 3,
- "cost": 162.42,
- "chosen": true
- }
- ]
- },
- {
- "table": "t_inner_3"
- },
- "best_access_path": {
- "considered_access_paths": [
- {
- "access_type": "scan",
- "resulting_rows": 9,
- "cost": 489.74,
- "chosen": true
- }
- ]
- }
- ]
- },
- {
- "semi_join_strategy": "firstmatch",
- "join_order": [
- {
- "table": "t_inner_1"
- },
- "best_access_path": {
- "considered_access_paths": [
- {
- "access_type": "scan",
- "resulting_rows": 3,
- "cost": 18.046,
- "chosen": true
- }
- ]
- },
- {
- "table": "t_inner_2"
- },
- "best_access_path": {
- "considered_access_paths": [
- {
- "access_type": "scan",
- "resulting_rows": 9,
- "cost": 54.415,
- "chosen": true
- }
- ]
- }
- ]
- }
- ]
+ "fix_semijoin_strategies_for_picked_join_order": []
},
{
"attaching_conditions_to_tables": {
@@ -5386,11 +5436,11 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
"attached": null
},
{
- "table": "t_outer_2",
+ "table": "t_inner_4",
"attached": null
},
{
- "table": "t_inner_4",
+ "table": "t_outer_2",
"attached": null
},
{
diff --git a/mysql-test/main/opt_tvc.result b/mysql-test/main/opt_tvc.result
index d503dab4d99..5329a9f64be 100644
--- a/mysql-test/main/opt_tvc.result
+++ b/mysql-test/main/opt_tvc.result
@@ -46,12 +46,12 @@ a b
2 5
explain extended select * from t1 where a in (1,2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from t1
where a in
(
@@ -59,12 +59,12 @@ select *
from (values (1),(2)) as tvc_0
);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
# AND-condition with IN-predicates in WHERE-part
select * from t1
where a in (1,2) and
@@ -90,15 +90,15 @@ explain extended select * from t1
where a in (1,2) and
b in (1,5);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`_col_1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where 1
explain extended select * from t1
where a in
(
@@ -111,15 +111,15 @@ select *
from (values (1),(5)) as tvc_1
);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where 1
# subquery with IN-predicate
select * from t1
where a in
@@ -206,12 +206,12 @@ from t1
where a in (1,2)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from
(
select *
@@ -224,12 +224,12 @@ as tvc_0
)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
# non-recursive CTE with IN-predicate
with tvc_0 as
(
@@ -265,12 +265,12 @@ where a in (1,2)
)
select * from tvc_0;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
+Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from
(
select *
@@ -283,12 +283,12 @@ as tvc_0
)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
# VIEW with IN-predicate
create view v1 as
select *
@@ -316,20 +316,20 @@ a b
2 5
explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from v2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
drop view v1,v2;
# subselect defined by derived table with IN-predicate
select * from t1
@@ -519,12 +519,12 @@ a b
1 2
explain extended select * from t1 where (a,b) in ((1,2),(3,4));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1` and `test`.`t1`.`b` = `tvc_0`.`_col_2`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where 1
set @@in_predicate_conversion_threshold= 2;
# trasformation works for the one IN predicate and doesn't work for the other
set @@in_predicate_conversion_threshold= 5;
@@ -538,12 +538,12 @@ explain extended select * from t2
where (a,b) in ((1,2),(8,9)) and
(a,c) in ((1,3),(8,0),(5,1));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 3 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`_col_1` and `test`.`t2`.`c` = `tvc_0`.`_col_2` and (`tvc_0`.`_col_1`,`test`.`t2`.`b`) in (<cache>((1,2)),<cache>((8,9)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where (`test`.`t2`.`a`,`test`.`t2`.`b`) in (<cache>((1,2)),<cache>((8,9)))
set @@in_predicate_conversion_threshold= 2;
#
# mdev-14281: conversion of NOT IN predicate into subquery predicate
diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result
index fc0049db997..5e446a171fe 100644
--- a/mysql-test/main/subselect.result
+++ b/mysql-test/main/subselect.result
@@ -5703,8 +5703,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 USE INDEX() WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
@@ -5714,8 +5714,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 index idx idx 5 NULL 3 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect3.result b/mysql-test/main/subselect3.result
index ca151daf146..3c33182b3ef 100644
--- a/mysql-test/main/subselect3.result
+++ b/mysql-test/main/subselect3.result
@@ -1139,8 +1139,8 @@ create table t3 (a int);
insert into t3 select A.a + 10*B.a from t0 A, t0 B;
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
create table t4 (pk int primary key);
insert into t4 select a from t3;
explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
@@ -1276,12 +1276,12 @@ insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
create table t2 as select * from t1;
explain select * from t2 where a in (select b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
drop table t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int, b int);
@@ -1339,9 +1339,9 @@ insert into t2 select * from t2;
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where
-1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where
-1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; FirstMatch(t1)
+1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
drop table t0,t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/main/subselect3_jcl6.result b/mysql-test/main/subselect3_jcl6.result
index adb3ec80394..69f720a95b7 100644
--- a/mysql-test/main/subselect3_jcl6.result
+++ b/mysql-test/main/subselect3_jcl6.result
@@ -1149,8 +1149,8 @@ create table t3 (a int);
insert into t3 select A.a + 10*B.a from t0 A, t0 B;
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
create table t4 (pk int primary key);
insert into t4 select a from t3;
explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
@@ -1286,12 +1286,12 @@ insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
create table t2 as select * from t1;
explain select * from t2 where a in (select b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
drop table t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int, b int);
@@ -1348,10 +1348,10 @@ create table t2 as select a as a, a as b from t0 where a < 3;
insert into t2 select * from t2;
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where; Using join buffer (incremental, BNL join)
-1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; FirstMatch(t1); Using join buffer (incremental, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY X hash_ALL NULL #hash#$hj 5 test.t1.a 6 Using where; Start temporary; Using join buffer (flat, BNLH join)
+1 PRIMARY Y hash_ALL NULL #hash#$hj 5 test.t1.b 6 Using where; Using join buffer (incremental, BNLH join)
+1 PRIMARY Z hash_ALL NULL #hash#$hj 5 test.t1.c 6 Using where; End temporary; Using join buffer (incremental, BNLH join)
drop table t0,t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result
index 4e03d9663ef..ee680d40b75 100644
--- a/mysql-test/main/subselect_mat.result
+++ b/mysql-test/main/subselect_mat.result
@@ -1510,8 +1510,8 @@ set @@optimizer_switch=@optimizer_switch_local_default;
SET @@optimizer_switch='semijoin=on,materialization=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 7 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
COUNT(*)
@@ -2437,8 +2437,8 @@ INSERT INTO t2 VALUES (11,11),(12,12),(13,13);
explain
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t2.i1 9 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 9
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
1
@@ -2450,8 +2450,8 @@ alter table t1 add key(id);
explain
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index
+1 PRIMARY t1 index id id 4 NULL 9 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
1
@@ -2507,8 +2507,8 @@ INSERT INTO t2 VALUES (11,11),(12,12),(13,13);
CREATE VIEW v1 AS SELECT t2.i1 FROM t2 where t2.i1 = t2.i2;
explain SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index
+1 PRIMARY t1 index id id 4 NULL 9 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1);
1
diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result
index 4ebf04b1f55..ecd973da09d 100644
--- a/mysql-test/main/subselect_no_mat.result
+++ b/mysql-test/main/subselect_no_mat.result
@@ -5683,9 +5683,9 @@ WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot1 ALL NULL NULL NULL NULL 2
-1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using join buffer (flat, BNL join)
-1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where
-1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using where; FirstMatch(ot4)
+1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
+1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
#
# Bug#729039: NULL keys used to evaluate subquery
@@ -5712,8 +5712,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index idx idx 5 NULL 3 Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 2 Using index; FirstMatch(t1)
DROP TABLE t1,t2;
#
# BUG#752992: Wrong results for a subquery with 'semijoin=on'
diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result
index 71d61e797f3..318ad02d473 100644
--- a/mysql-test/main/subselect_no_scache.result
+++ b/mysql-test/main/subselect_no_scache.result
@@ -5709,8 +5709,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 USE INDEX() WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
@@ -5720,8 +5720,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 index idx idx 5 NULL 3 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect_sj.result b/mysql-test/main/subselect_sj.result
index 98143246673..3bd08e303b8 100644
--- a/mysql-test/main/subselect_sj.result
+++ b/mysql-test/main/subselect_sj.result
@@ -729,8 +729,8 @@ SELECT int_key FROM ot1
WHERE int_nokey IN (SELECT it2.int_key
FROM it1 LEFT JOIN it2 ON it2.datetime_key);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 20
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it1 index NULL int_key 4 NULL 2 Using index
2 MATERIALIZED it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where
DROP TABLE ot1, it1, it2;
@@ -972,11 +972,11 @@ SELECT `varchar_key` , `varchar_nokey`
FROM t1
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 15 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and `test`.`t2`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
+Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
SELECT varchar_nokey
FROM t2
WHERE ( `varchar_nokey` , `varchar_nokey` ) IN (
@@ -1246,8 +1246,8 @@ INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1);
EXPLAIN
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; Start temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; End temporary; Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
i
1
@@ -1757,8 +1757,8 @@ insert into t3 values('three'),( 'four');
insert into t3 values('three'),( 'four');
explain select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func 1
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
@@ -1991,12 +1991,13 @@ CREATE VIEW v4 AS SELECT DISTINCT f2 FROM t4 ;
explain extended
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3) WHERE t2.f3 IN (SELECT * FROM t4);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
-1 PRIMARY t4 ref f2 f2 5 test.t2.f3 2 100.00 Using index; FirstMatch(t2)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
+2 MATERIALIZED t4 index f2 f2 5 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3`,`test`.`t3`.`f3` AS `f3` from `test`.`t1` semi join (`test`.`t4`) join `test`.`t2` join `test`.`t3` where `test`.`t4`.`f2` = `test`.`t2`.`f3` and `test`.`t3`.`f1` = `test`.`t1`.`f1` and `test`.`t1`.`f2` = `test`.`t2`.`f2`
+Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3`,`test`.`t3`.`f3` AS `f3` from `test`.`t1` semi join (`test`.`t4`) join `test`.`t2` join `test`.`t3` where `test`.`t3`.`f1` = `test`.`t1`.`f1` and `test`.`t1`.`f2` = `test`.`t2`.`f2`
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3) WHERE t2.f3 IN (SELECT * FROM t4);
f1 f2 f3 f3
2 0 0 0
@@ -2495,8 +2496,8 @@ WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 1
-1 PRIMARY t1 ref a a 5 const 1 Using index
-1 PRIMARY t2 ref a a 5 func 1 Using index
+1 PRIMARY t2 ref a a 5 const 1 Using index
+1 PRIMARY t1 ref a a 5 func 1 Using index
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 0
SELECT * FROM t1, t2
WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
@@ -2706,8 +2707,8 @@ a
19
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
drop table t0,t1,t3;
set optimizer_switch= @tmp_923246;
#
@@ -2923,8 +2924,8 @@ WHERE alias1.pk = 58 OR alias1.col_varchar_key = 'o'
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
-1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where
-1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); FirstMatch(t2)
+1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where; Start temporary
+1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); End temporary
SELECT *
FROM t2
WHERE (field1) IN (SELECT alias1.col_varchar_nokey AS field1
@@ -3264,4 +3265,27 @@ create table t2 (a2 varchar(25)) ;
insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2);
drop table t1,t2;
# End of 5.5 test
+#
+# MDEV-20109: Optimizer ignores distinct key created for materialized
+# semi-join subquery when searching for best execution plan
+#
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+# The following must not use this query plan that does a cross join:
+# | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+# | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+#
+# Instead, it should use eq_ref on the materialized table.
+explain select * from t3 where a in (select a from t4 group by a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 10000
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 500
+drop table t1, t2, t3, t4;
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/main/subselect_sj.test b/mysql-test/main/subselect_sj.test
index b693f7b5b93..a2d6c7e427c 100644
--- a/mysql-test/main/subselect_sj.test
+++ b/mysql-test/main/subselect_sj.test
@@ -2940,5 +2940,30 @@ drop table t1,t2;
--echo # End of 5.5 test
+--echo #
+--echo # MDEV-20109: Optimizer ignores distinct key created for materialized
+--echo # semi-join subquery when searching for best execution plan
+--echo #
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+
+--echo # The following must not use this query plan that does a cross join:
+--echo # | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+--echo # | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+--echo #
+--echo # Instead, it should use eq_ref on the materialized table.
+
+explain select * from t3 where a in (select a from t4 group by a);
+
+drop table t1, t2, t3, t4;
+
# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/main/subselect_sj2.result b/mysql-test/main/subselect_sj2.result
index a127c18280e..31453801220 100644
--- a/mysql-test/main/subselect_sj2.result
+++ b/mysql-test/main/subselect_sj2.result
@@ -131,8 +131,9 @@ set join_buffer_size= @save_join_buffer_size;
set max_heap_table_size= @save_max_heap_table_size;
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY t2 ref b b 5 test.t1.a 1 Using index; FirstMatch(t1)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index b b 5 NULL 20 Using index
select * from t1;
a b
1 1
@@ -159,8 +160,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -227,8 +228,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -730,8 +731,9 @@ alter table t3 add primary key(id), add key(a);
The following must use loose index scan over t3, key a:
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index a a 5 NULL 1000 Using where; Using index
-1 PRIMARY t3 ref a a 5 test.t2.a 30 Using index; FirstMatch(t2)
+1 PRIMARY t2 index a a 5 NULL 1000 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t3 index a a 5 NULL 30000 Using index
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
1000
@@ -757,9 +759,10 @@ c2 in (select 1 from t3, t2) and
c1 in (select convert(c6,char(1)) from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch((sj-nest))
+3 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
drop table t2, t3;
#
# BUG#761598: InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock() in maria-5.3
diff --git a/mysql-test/main/subselect_sj2_jcl6.result b/mysql-test/main/subselect_sj2_jcl6.result
index 56c11e8c9af..3321ba221f3 100644
--- a/mysql-test/main/subselect_sj2_jcl6.result
+++ b/mysql-test/main/subselect_sj2_jcl6.result
@@ -171,9 +171,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 32 Using where; Using join buffer (flat, BNLH join)
-2 MATERIALIZED it ALL NULL NULL NULL NULL 22 Using where
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -239,9 +239,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 52 Using where; Using join buffer (flat, BNLH join)
-2 MATERIALIZED it ALL NULL NULL NULL NULL 22 Using where
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -1410,9 +1410,10 @@ SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b
WHERE c IN (SELECT t4.b FROM t4 JOIN t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
-1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t3); Using join buffer (incremental, BNL join)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
1 PRIMARY t1 ref b b 4 test.t3.b 1 Using index
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b
WHERE c IN (SELECT t4.b FROM t4 JOIN t2);
b c
@@ -1438,9 +1439,10 @@ EXPLAIN
SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 1 Using where
+2 MATERIALIZED t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1
SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk);
pk a b
1 6 8
diff --git a/mysql-test/main/subselect_sj2_mat.result b/mysql-test/main/subselect_sj2_mat.result
index 73f682755da..7245e74b242 100644
--- a/mysql-test/main/subselect_sj2_mat.result
+++ b/mysql-test/main/subselect_sj2_mat.result
@@ -133,8 +133,9 @@ set join_buffer_size= @save_join_buffer_size;
set max_heap_table_size= @save_max_heap_table_size;
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY t2 ref b b 5 test.t1.a 1 Using index; FirstMatch(t1)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index b b 5 NULL 20 Using index
select * from t1;
a b
1 1
@@ -161,8 +162,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -229,8 +230,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -732,8 +733,9 @@ alter table t3 add primary key(id), add key(a);
The following must use loose index scan over t3, key a:
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index a a 5 NULL 1000 Using where; Using index
-1 PRIMARY t3 ref a a 5 test.t2.a 30 Using index; FirstMatch(t2)
+1 PRIMARY t2 index a a 5 NULL 1000 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t3 index a a 5 NULL 30000 Using index
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
1000
@@ -759,9 +761,10 @@ c2 in (select 1 from t3, t2) and
c1 in (select convert(c6,char(1)) from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch((sj-nest))
+3 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
drop table t2, t3;
#
# BUG#761598: InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock() in maria-5.3
@@ -1638,12 +1641,12 @@ set optimizer_switch='materialization=on,semijoin=on';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 = i2 OR 1=2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 5 test.t2.i2 5 100.00 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 MATERIALIZED t3 hash_ALL NULL #hash#$hj 5 test.t2.i2 3 100.00 Using where; Using join buffer (flat, BNLH join)
Warnings:
-Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`i1` = `test`.`t2`.`i2`
+Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2`
SELECT * FROM t1 WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 = i2 OR 1=2);
i1
7
@@ -1651,12 +1654,12 @@ EXPLAIN EXTENDED
SELECT * FROM t1
WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 > 0 AND i3 = i2 OR 1=2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 5 test.t2.i2 5 100.00 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 MATERIALIZED t3 hash_ALL NULL #hash#$hj 5 test.t2.i2 3 100.00 Using where; Using join buffer (flat, BNLH join)
Warnings:
-Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`i1` = `test`.`t2`.`i2` and `test`.`t3`.`i3` > 0
+Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t3`.`i3` > 0
SELECT * FROM t1
WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 > 0 AND i3 = i2 OR 1=2);
i1
@@ -1748,8 +1751,8 @@ OR
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index PRIMARY PRIMARY 4 NULL 13 Using where; Using index
-2 MATERIALIZED <subquery3> ALL distinct_key NULL NULL NULL 8
-2 MATERIALIZED A ALL PRIMARY NULL NULL NULL 13 Using where; Using join buffer (flat, BNL join)
+2 MATERIALIZED A ALL PRIMARY NULL NULL NULL 13
+2 MATERIALIZED <subquery3> eq_ref distinct_key distinct_key 67 func 1
3 MATERIALIZED B range PRIMARY PRIMARY 4 NULL 8 Using where
SELECT SQL_NO_CACHE t.id
FROM t1 t
@@ -1914,18 +1917,16 @@ AND t3.id_product IN (SELECT id_product FROM t2 t2_5 WHERE t2_5.id_t2 = 29 OR t2
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 12
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t2_2.id_product 1 Using where; Using index
-1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 4 func 1 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 Using where
+1 PRIMARY t2_3 ref id_t2,id_product id_product 5 test.t3.id_product 44 Using index condition; Using where; Start temporary; End temporary
+1 PRIMARY t2_5 ref id_t2,id_product id_product 5 test.t3.id_product 44 Using index condition; Using where; Start temporary; End temporary
1 PRIMARY t5 ALL NULL NULL NULL NULL 18 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY <subquery6> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t4 eq_ref PRIMARY PRIMARY 8 test.t3.id_product,const 1 Using where; Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 Using where
-1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 Using where
+1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t1 index NULL PRIMARY 8 NULL 73 Using where; Using index; Using join buffer (flat, BNL join)
3 MATERIALIZED t2_2 ref id_t2,id_product id_t2 5 const 12 Using where
-5 MATERIALIZED t2_4 range id_t2,id_product id_t2 5 NULL 18 Using index condition; Using where
-6 MATERIALIZED t2_5 range id_t2,id_product id_t2 5 NULL 31 Using index condition; Using where
2 MATERIALIZED t2_1 ref id_t2,id_product id_t2 5 const 51
-4 MATERIALIZED t2_3 range id_t2,id_product id_t2 5 NULL 33 Using index condition; Using where
+5 MATERIALIZED t2_4 range id_t2,id_product id_t2 5 NULL 18 Using index condition; Using where
set optimizer_switch='rowid_filter=default';
drop table t1,t2,t3,t4,t5;
set global innodb_stats_persistent= @innodb_stats_persistent_save;
diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result
index acfafde6d7e..711ae32a931 100644
--- a/mysql-test/main/subselect_sj_jcl6.result
+++ b/mysql-test/main/subselect_sj_jcl6.result
@@ -742,8 +742,8 @@ SELECT int_key FROM ot1
WHERE int_nokey IN (SELECT it2.int_key
FROM it1 LEFT JOIN it2 ON it2.datetime_key);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 20
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it1 index NULL int_key 4 NULL 2 Using index
2 MATERIALIZED it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
DROP TABLE ot1, it1, it2;
@@ -985,11 +985,11 @@ SELECT `varchar_key` , `varchar_nokey`
FROM t1
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 15 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and `test`.`t2`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
+Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
SELECT varchar_nokey
FROM t2
WHERE ( `varchar_nokey` , `varchar_nokey` ) IN (
@@ -1259,8 +1259,8 @@ INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1);
EXPLAIN
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; Start temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; End temporary; Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
i
1
@@ -1770,8 +1770,8 @@ insert into t3 values('three'),( 'four');
insert into t3 values('three'),( 'four');
explain select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func 1
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
@@ -2509,8 +2509,8 @@ WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 1
-1 PRIMARY t1 ref a a 5 const 1 Using index
-1 PRIMARY t2 ref a a 5 func 1 Using index
+1 PRIMARY t2 ref a a 5 const 1 Using index
+1 PRIMARY t1 ref a a 5 func 1 Using index
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 0
SELECT * FROM t1, t2
WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
@@ -2720,8 +2720,8 @@ a
19
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
drop table t0,t1,t3;
set optimizer_switch= @tmp_923246;
#
@@ -2937,8 +2937,8 @@ WHERE alias1.pk = 58 OR alias1.col_varchar_key = 'o'
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
-1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where
-1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); FirstMatch(t2)
+1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); End temporary
SELECT *
FROM t2
WHERE (field1) IN (SELECT alias1.col_varchar_nokey AS field1
@@ -3278,6 +3278,29 @@ create table t2 (a2 varchar(25)) ;
insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2);
drop table t1,t2;
# End of 5.5 test
+#
+# MDEV-20109: Optimizer ignores distinct key created for materialized
+# semi-join subquery when searching for best execution plan
+#
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+# The following must not use this query plan that does a cross join:
+# | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+# | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+#
+# Instead, it should use eq_ref on the materialized table.
+explain select * from t3 where a in (select a from t4 group by a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 10000
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 500
+drop table t1, t2, t3, t4;
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
@@ -3485,8 +3508,8 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 Using temporary; Using filesort
+1 PRIMARY t ref idx_a idx_a 4 test.t2.b 2 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
@@ -3499,8 +3522,8 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 Using temporary; Using filesort
+1 PRIMARY t ref idx_a idx_a 4 test.t2.b 2 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result
index 203dbee6374..432f6c648fc 100644
--- a/mysql-test/main/subselect_sj_mat.result
+++ b/mysql-test/main/subselect_sj_mat.result
@@ -491,15 +491,15 @@ where (c1, c2) in (select b1, b2 from t2i where b2 > '0')) and
a1 = c1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 4 100.00 Using where
1 PRIMARY t3 ALL NULL NULL NULL NULL 4 99.22 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 16 func,func 1 100.00
4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 99.22 Using where
4 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 1 100.00 Using index
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 99.22 Using where
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 99.22 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and `test`.`t3`.`c2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0'
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0'
select * from t1, t3
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(c1, c2) in (select c1, c2 from t3
@@ -1132,11 +1132,11 @@ insert into t3 values (30);
explain extended
select a from t1 where a in (select c from t2 where d >= 20);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 6 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t1`.`a` = `test`.`t2`.`c` and `test`.`t2`.`d` >= 20
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`d` >= 20
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1543,8 +1543,8 @@ set @@optimizer_switch=@optimizer_switch_local_default;
SET @@optimizer_switch='semijoin=on,materialization=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 7 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
COUNT(*)
@@ -2473,8 +2473,8 @@ INSERT INTO t2 VALUES (11,11),(12,12),(13,13);
explain
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t2.i1 9 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 9
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
1
@@ -2486,8 +2486,8 @@ alter table t1 add key(id);
explain
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index
+1 PRIMARY t1 index id id 4 NULL 9 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
1
@@ -2543,8 +2543,8 @@ INSERT INTO t2 VALUES (11,11),(12,12),(13,13);
CREATE VIEW v1 AS SELECT t2.i1 FROM t2 where t2.i1 = t2.i2;
explain SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index
+1 PRIMARY t1 index id id 4 NULL 9 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1);
1
diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result
index 51198ea47d6..a9b085fe31e 100644
--- a/mysql-test/main/table_value_constr.result
+++ b/mysql-test/main/table_value_constr.result
@@ -743,21 +743,21 @@ a b
explain extended select * from t1
where a in (values (1));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where 1
explain extended select * from t1
where a in (select * from (values (1)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where 1
# IN-subquery with VALUES structure(s) : UNION with VALUES on the first place
select * from t1
where a in (values (1) union select 2);
@@ -978,21 +978,21 @@ a b
explain extended select * from t1
where a = any (values (1),(2));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from t1
where a = any (select * from (values (1),(2)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
# ANY-subquery with VALUES structure(s) : UNION with VALUES on the first place
select * from t1
where a = any (values (1) union select 2);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 599642b3a26..fd3ac1e9155 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -2456,7 +2456,7 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
&subjoin_out_rows);
sjm->materialization_cost.convert_from_cost(subjoin_read_time);
- sjm->rows= subjoin_out_rows;
+ sjm->rows_with_duplicates= sjm->rows= subjoin_out_rows;
// Don't use the following list because it has "stale" items. use
// ref_pointer_array instead:
@@ -3082,11 +3082,14 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
disable_jbuf, prefix_rec_count, &curpos, &dummy);
prefix_rec_count= COST_MULT(prefix_rec_count, curpos.records_read);
prefix_cost= COST_ADD(prefix_cost, curpos.read_time);
+ prefix_cost= COST_ADD(prefix_cost,
+ prefix_rec_count / (double) TIME_FOR_COMPARE);
+ //TODO: take into account join condition selectivity here
}
*strategy= SJ_OPT_MATERIALIZE_SCAN;
*read_time= prefix_cost;
- *record_count= prefix_rec_count;
+ *record_count= prefix_rec_count / mat_info->rows_with_duplicates;
*handled_fanout= mat_nest->sj_inner_tables;
return TRUE;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2b46fc69365..5ffc8bde269 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5995,7 +5995,10 @@ class SJ_MATERIALIZATION_INFO : public Sql_alloc
uint tables; /* Number of tables in the sj-nest */
- /* Expected #rows in the materialized table */
+ /* Number of rows in the materialized table, before the de-duplication */
+ double rows_with_duplicates;
+
+ /* Expected #rows in the materialized table, after de-duplication */
double rows;
/*
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e79e96bf210..fd34842d37a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8816,6 +8816,7 @@ void JOIN::get_prefix_cost_and_fanout(uint n_tables,
record_count= COST_MULT(record_count, best_positions[i].records_read);
read_time= COST_ADD(read_time, best_positions[i].read_time);
}
+ /* TODO: Take into account condition selectivities here */
}
*read_time_arg= read_time;// + record_count / TIME_FOR_COMPARE;
*record_count_arg= record_count;
@@ -16703,10 +16704,20 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
reopt_remaining_tables &= ~rs->table->map;
rec_count= COST_MULT(rec_count, pos.records_read);
cost= COST_ADD(cost, pos.read_time);
-
-
+ cost= COST_ADD(cost, rec_count / (double) TIME_FOR_COMPARE);
+ //TODO: take into account join condition selectivity here
+ double pushdown_cond_selectivity= 1.0;
+ table_map real_table_bit= rs->table->map;
+ if (join->thd->variables.optimizer_use_condition_selectivity > 1)
+ {
+ pushdown_cond_selectivity= table_cond_selectivity(join, i, rs,
+ reopt_remaining_tables &
+ ~real_table_bit);
+ }
+ (*outer_rec_count) *= pushdown_cond_selectivity;
if (!rs->emb_sj_nest)
*outer_rec_count= COST_MULT(*outer_rec_count, pos.records_read);
+
}
join->cur_sj_inner_tables= save_cur_sj_inner_tables;
1
0
[Commits] b729f8c536b: MDEV-18094: Query with order by limit picking index scan over filesort
by Varun 26 Aug '19
by Varun 26 Aug '19
26 Aug '19
revision-id: b729f8c536bc2307ee3008167d009f440ab6b725 (mariadb-10.1.39-155-gb729f8c536b)
parent(s): de0f93fb0d7b03aaf293cc89b611aeff3ce3244e
author: Varun Gupta
committer: Varun Gupta
timestamp: 2019-08-26 20:54:17 +0530
message:
MDEV-18094: Query with order by limit picking index scan over filesort
In the function test_if_cheaper_ordering we make a decision if using an index is better than using filesort
for ordering. If we chose to do range access then in test_quick_select we should make sure that cost
for table scan is set to DBL_MAX so that it is not picked
---
mysql-test/r/group_min_max.result | 4 ++--
mysql-test/r/order_by_innodb.result | 31 +++++++++++++++++++++++++++++++
mysql-test/t/order_by_innodb.test | 24 ++++++++++++++++++++++++
sql/opt_range.cc | 14 +++++++++-----
4 files changed, 66 insertions(+), 7 deletions(-)
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index 777780f8400..c535550d5f9 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -2119,12 +2119,12 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using index
explain extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 128 75.00 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 102 94.12 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,count(`test`.`t1`.`a2`) AS `count(a2)` from `test`.`t1` where (`test`.`t1`.`a1` > 'a') group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 128 75.00 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 102 94.12 Using where; Using index
Warnings:
Note 1003 select sum(ord(`test`.`t1`.`a1`)) AS `sum(ord(a1))` from `test`.`t1` where (`test`.`t1`.`a1` > 'a') group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
create table t4 as select distinct a1, a2, b, c from t1;
diff --git a/mysql-test/r/order_by_innodb.result b/mysql-test/r/order_by_innodb.result
index 4f59a2f8c20..4c997769b65 100644
--- a/mysql-test/r/order_by_innodb.result
+++ b/mysql-test/r/order_by_innodb.result
@@ -48,3 +48,34 @@ where key1<3 or key2<3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using sort_union(key1,key2); Using where
drop table t0, t1;
+#
+# MDEV-18094: Query with order by limit picking index scan over filesort
+#
+create table t0 (a int);
+INSERT INTO t0 VALUES (0),(0),(0),(0),(2),(0),(0),(1),(1),(0);
+CREATE TABLE t1 (
+a int(11) DEFAULT NULL,
+b int(11) DEFAULT NULL,
+c int(11) DEFAULT NULL,
+KEY a_c (a,c),
+KEY a_b (a,b)
+) ENGINE=InnoDB;
+insert into t1 select A.a , B.a, C.a from t0 A, t0 B, t0 C;
+# should use ref access
+explain extended select a,b,c from t1 where a=1 and c=2 order by b;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 ref a_c,a_b a_c 10 const,const 20 100.00 Using where; Using filesort
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where ((`test`.`t1`.`a` = 1) and (`test`.`t1`.`c` = 2)) order by `test`.`t1`.`b`
+# both should use range access
+explain extended select a,b,c from t1 where a=1 and c=2 order by b limit 1000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range a_c,a_b a_b 5 NULL 200 10.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where ((`test`.`t1`.`a` = 1) and (`test`.`t1`.`c` = 2)) order by `test`.`t1`.`b` limit 1000
+explain extended select a,b,c from t1 where a=1 and c=2 order by b limit 2000;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 range a_c,a_b a_b 5 NULL 200 10.00 Using where
+Warnings:
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where ((`test`.`t1`.`a` = 1) and (`test`.`t1`.`c` = 2)) order by `test`.`t1`.`b` limit 2000
+drop table t1,t0;
diff --git a/mysql-test/t/order_by_innodb.test b/mysql-test/t/order_by_innodb.test
index 097eddd24f1..7d8b5c2ca65 100644
--- a/mysql-test/t/order_by_innodb.test
+++ b/mysql-test/t/order_by_innodb.test
@@ -61,3 +61,27 @@ from t1
where key1<3 or key2<3;
drop table t0, t1;
+
+--echo #
+--echo # MDEV-18094: Query with order by limit picking index scan over filesort
+--echo #
+
+create table t0 (a int);
+INSERT INTO t0 VALUES (0),(0),(0),(0),(2),(0),(0),(1),(1),(0);
+
+CREATE TABLE t1 (
+a int(11) DEFAULT NULL,
+b int(11) DEFAULT NULL,
+c int(11) DEFAULT NULL,
+KEY a_c (a,c),
+KEY a_b (a,b)
+) ENGINE=InnoDB;
+insert into t1 select A.a , B.a, C.a from t0 A, t0 B, t0 C;
+
+--echo # should use ref access
+explain extended select a,b,c from t1 where a=1 and c=2 order by b;
+
+--echo # both should use range access
+explain extended select a,b,c from t1 where a=1 and c=2 order by b limit 1000;
+explain extended select a,b,c from t1 where a=1 and c=2 order by b limit 2000;
+drop table t1,t0;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index e8421ad052a..5a67770c831 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2420,12 +2420,16 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
records= head->stat_records();
if (!records)
records++; /* purecov: inspected */
- scan_time= (double) records / TIME_FOR_COMPARE + 1;
- read_time= (double) head->file->scan_time() + scan_time + 1.1;
- if (head->force_index)
+
+ if (head->force_index || force_quick_range)
scan_time= read_time= DBL_MAX;
- if (limit < records)
- read_time= (double) records + scan_time + 1; // Force to use index
+ else
+ {
+ scan_time= (double) records / TIME_FOR_COMPARE + 1;
+ read_time= (double) head->file->scan_time() + scan_time + 1.1;
+ if (limit < records)
+ read_time= (double) records + scan_time + 1; // Force to use index
+ }
possible_keys.clear_all();
1
0
[Commits] 31815d37666: MDEV-6111: Optimizer Trace: add tracing for semi-join optimizations
by Sergei Petrunia 25 Aug '19
by Sergei Petrunia 25 Aug '19
25 Aug '19
revision-id: 31815d37666d3ca9fae2df45b99138e1c4507bab (mariadb-10.4.7-33-g31815d37666)
parent(s): efb8485d85b19a2a729310adc6779ca649198f29
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-08-25 11:03:19 +0300
message:
MDEV-6111: Optimizer Trace: add tracing for semi-join optimizations
Added:
- "semijoin_strategy_choice" element (actions in advance_sj_state(), name
matches the name in MySQL)
- semijoin_table_pullout element.
---
mysql-test/main/opt_trace.result | 273 +++++++++++++++++++++++++++++++++++++--
mysql-test/main/opt_trace.test | 18 +++
sql/opt_subselect.cc | 101 ++++++++++++---
3 files changed, 365 insertions(+), 27 deletions(-)
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 518da2888cc..ab07db38d05 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -2662,6 +2662,11 @@ explain extended select * from t1 where a in (select pk from t10) {
}
]
},
+ {
+ "semijoin_table_pullout": {
+ "pulled_out_tables": []
+ }
+ },
{
"execution_plan_for_potential_materialization": {
"steps": [
@@ -2705,6 +2710,7 @@ explain extended select * from t1 where a in (select pk from t10) {
},
"rows_for_plan": 3,
"cost_for_plan": 2.6066,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t1"],
@@ -2720,7 +2726,27 @@ explain extended select * from t1 where a in (select pk from t10) {
]
},
"rows_for_plan": 30,
- "cost_for_plan": 10.629
+ "cost_for_plan": 10.629,
+ "semijoin_strategy_choice": [
+ {
+ "strategy": "FirstMatch",
+ "records": 3,
+ "read_time": 10.629
+ },
+ {
+ "strategy": "SJ-Materialization",
+ "records": 3,
+ "read_time": 5.2786
+ },
+ {
+ "strategy": "DuplicateWeedout",
+ "records": 3,
+ "read_time": 27.129
+ },
+ {
+ "chosen_strategy": "SJ-Materialize"
+ }
+ ]
}
]
},
@@ -2739,6 +2765,7 @@ explain extended select * from t1 where a in (select pk from t10) {
},
"rows_for_plan": 10,
"cost_for_plan": 4.022,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -2746,7 +2773,7 @@ explain extended select * from t1 where a in (select pk from t10) {
{
"fix_semijoin_strategies_for_picked_join_order": [
{
- "semi_join_strategy": "sj_materialize",
+ "semi_join_strategy": "SJ-Materialization",
"join_order": [
{
"table": "t10"
@@ -4081,6 +4108,11 @@ explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_
}
]
},
+ {
+ "semijoin_table_pullout": {
+ "pulled_out_tables": []
+ }
+ },
{
"execution_plan_for_potential_materialization": {
"steps": [
@@ -4159,6 +4191,7 @@ explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t1"],
@@ -4175,6 +4208,7 @@ explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_
},
"rows_for_plan": 9,
"cost_for_plan": 6.4103,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t1", "t_inner_1"],
@@ -4190,7 +4224,27 @@ explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_
]
},
"rows_for_plan": 27,
- "cost_for_plan": 13.815
+ "cost_for_plan": 13.815,
+ "semijoin_strategy_choice": [
+ {
+ "strategy": "FirstMatch",
+ "records": 3,
+ "read_time": 26.667
+ },
+ {
+ "strategy": "SJ-Materialization",
+ "records": 3,
+ "read_time": 7.2154
+ },
+ {
+ "strategy": "DuplicateWeedout",
+ "records": 3,
+ "read_time": 18.315
+ },
+ {
+ "chosen_strategy": "SJ-Materialize"
+ }
+ ]
}
]
},
@@ -4209,6 +4263,7 @@ explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_
},
"rows_for_plan": 9,
"cost_for_plan": 6.4103,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -4228,6 +4283,7 @@ explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -4245,6 +4301,7 @@ explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -4252,7 +4309,7 @@ explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_
{
"fix_semijoin_strategies_for_picked_join_order": [
{
- "semi_join_strategy": "sj_materialize",
+ "semi_join_strategy": "SJ-Materialization",
"join_order": [
{
"table": "t_inner_1"
@@ -4511,6 +4568,16 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
}
]
},
+ {
+ "semijoin_table_pullout": {
+ "pulled_out_tables": []
+ }
+ },
+ {
+ "semijoin_table_pullout": {
+ "pulled_out_tables": []
+ }
+ },
{
"execution_plan_for_potential_materialization": {
"steps": []
@@ -4533,6 +4600,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1"],
@@ -4549,6 +4617,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 6.4103,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1", "t_inner_1"],
@@ -4565,6 +4634,21 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 24.626,
+ "semijoin_strategy_choice": [
+ {
+ "strategy": "FirstMatch",
+ "records": 3,
+ "read_time": 26.759
+ },
+ {
+ "strategy": "DuplicateWeedout",
+ "records": 3,
+ "read_time": 37.226
+ },
+ {
+ "chosen_strategy": "FirstMatch"
+ }
+ ],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_2"],
@@ -4581,6 +4665,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 34.174,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -4602,6 +4687,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 52.379,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -4623,7 +4709,22 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 729,
- "cost_for_plan": 200.19
+ "cost_for_plan": 200.19,
+ "semijoin_strategy_choice": [
+ {
+ "strategy": "FirstMatch",
+ "records": 27,
+ "read_time": 251.56
+ },
+ {
+ "strategy": "DuplicateWeedout",
+ "records": 27,
+ "read_time": 313.59
+ },
+ {
+ "chosen_strategy": "FirstMatch"
+ }
+ ]
}
]
},
@@ -4647,6 +4748,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 243,
"cost_for_plan": 84.79,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -4666,6 +4768,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 30.564,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -4687,6 +4790,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 48.779,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -4709,6 +4813,16 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 196.59,
+ "semijoin_strategy_choice": [
+ {
+ "strategy": "DuplicateWeedout",
+ "records": 27,
+ "read_time": 309.99
+ },
+ {
+ "chosen_strategy": "DuplicateWeedout"
+ }
+ ],
"pruned_by_cost": true
}
]
@@ -4733,6 +4847,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 48.779,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -4752,6 +4867,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 34.174,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -4771,6 +4887,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 24.626,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1", "t_inner_1", "t_outer_2"],
@@ -4787,6 +4904,16 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 172.44,
+ "semijoin_strategy_choice": [
+ {
+ "strategy": "DuplicateWeedout",
+ "records": 27,
+ "read_time": 285.84
+ },
+ {
+ "chosen_strategy": "DuplicateWeedout"
+ }
+ ],
"pruned_by_cost": true
},
{
@@ -4804,6 +4931,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 243,
"cost_for_plan": 75.231,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -4825,6 +4953,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 2187,
"cost_for_plan": 514.65,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
},
{
@@ -4847,6 +4976,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 2187,
"cost_for_plan": 514.65,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
}
]
@@ -4866,6 +4996,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 172.44,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -4885,6 +5016,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 13.815,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_4"],
@@ -4901,6 +5033,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 243,
"cost_for_plan": 64.431,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -4922,6 +5055,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 2187,
"cost_for_plan": 503.85,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
},
{
@@ -4944,6 +5078,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 2187,
"cost_for_plan": 503.85,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
}
]
@@ -4963,6 +5098,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 243,
"cost_for_plan": 64.431,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -4980,6 +5116,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 243,
"cost_for_plan": 64.431,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -4999,6 +5136,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 24.626,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_3"],
@@ -5015,6 +5153,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 172.44,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -5036,6 +5175,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 2187,
"cost_for_plan": 611.85,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
},
{
@@ -5058,6 +5198,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 6561,
"cost_for_plan": 1486.7,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
}
]
@@ -5077,6 +5218,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 243,
"cost_for_plan": 75.231,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -5098,6 +5240,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 2187,
"cost_for_plan": 514.65,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
},
{
@@ -5120,6 +5263,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 2187,
"cost_for_plan": 514.65,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
}
]
@@ -5139,6 +5283,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 172.44,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -5160,6 +5305,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 10.021,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -5177,6 +5323,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 10.021,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -5194,6 +5341,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 6.4103,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -5211,6 +5359,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 10.021,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -5230,6 +5379,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -5247,6 +5397,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 3.8154,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -5264,6 +5415,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 3.8154,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -5281,6 +5433,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -5298,6 +5451,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 3.8154,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -5305,7 +5459,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
{
"fix_semijoin_strategies_for_picked_join_order": [
{
- "semi_join_strategy": "firstmatch",
+ "semi_join_strategy": "FirstMatch",
"join_order": [
{
"table": "t_inner_4"
@@ -5336,7 +5490,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
{
- "semi_join_strategy": "firstmatch",
+ "semi_join_strategy": "FirstMatch",
"join_order": [
{
"table": "t_inner_1"
@@ -5621,6 +5775,16 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
}
]
},
+ {
+ "semijoin_table_pullout": {
+ "pulled_out_tables": []
+ }
+ },
+ {
+ "semijoin_table_pullout": {
+ "pulled_out_tables": []
+ }
+ },
{
"execution_plan_for_potential_materialization": {
"steps": [
@@ -5754,6 +5918,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1"],
@@ -5770,6 +5935,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 6.4103,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1", "t_inner_1"],
@@ -5786,6 +5952,26 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 24.626,
+ "semijoin_strategy_choice": [
+ {
+ "strategy": "FirstMatch",
+ "records": 3,
+ "read_time": 26.759
+ },
+ {
+ "strategy": "SJ-Materialization",
+ "records": 3,
+ "read_time": 8.1256
+ },
+ {
+ "strategy": "DuplicateWeedout",
+ "records": 3,
+ "read_time": 37.226
+ },
+ {
+ "chosen_strategy": "SJ-Materialize"
+ }
+ ],
"rest_of_plan": [
{
"plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_2"],
@@ -5802,6 +5988,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 15.541,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -5823,6 +6010,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 33.746,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -5844,7 +6032,27 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 729,
- "cost_for_plan": 181.56
+ "cost_for_plan": 181.56,
+ "semijoin_strategy_choice": [
+ {
+ "strategy": "FirstMatch",
+ "records": 27,
+ "read_time": 232.93
+ },
+ {
+ "strategy": "SJ-Materialization",
+ "records": 27,
+ "read_time": 22.262
+ },
+ {
+ "strategy": "DuplicateWeedout",
+ "records": 27,
+ "read_time": 294.96
+ },
+ {
+ "chosen_strategy": "SJ-Materialize"
+ }
+ ]
}
]
},
@@ -5868,6 +6076,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 243,
"cost_for_plan": 66.156,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
}
]
@@ -5887,6 +6096,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 11.931,
+ "semijoin_strategy_choice": [],
"rest_of_plan": [
{
"plan_prefix": [
@@ -5908,6 +6118,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 30.146,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
},
{
@@ -5930,6 +6141,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 30.146,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
}
]
@@ -5949,6 +6161,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 15.541,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -5968,6 +6181,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 24.626,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
},
{
@@ -5985,6 +6199,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 13.815,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -6002,6 +6217,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 81,
"cost_for_plan": 24.626,
+ "semijoin_strategy_choice": [],
"pruned_by_cost": true
}
]
@@ -6021,6 +6237,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 10.021,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -6038,6 +6255,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 10.021,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -6055,6 +6273,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 6.4103,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -6072,6 +6291,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 27,
"cost_for_plan": 10.021,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -6091,6 +6311,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -6108,6 +6329,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 3.8154,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -6125,6 +6347,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 3.8154,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -6142,6 +6365,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 3,
"cost_for_plan": 2.6051,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
},
{
@@ -6159,6 +6383,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 9,
"cost_for_plan": 3.8154,
+ "semijoin_strategy_choice": [],
"pruned_by_heuristic": true
}
]
@@ -6166,7 +6391,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
{
"fix_semijoin_strategies_for_picked_join_order": [
{
- "semi_join_strategy": "sj_materialize",
+ "semi_join_strategy": "SJ-Materialization",
"join_order": [
{
"table": "t_inner_4"
@@ -6177,7 +6402,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
{
- "semi_join_strategy": "sj_materialize",
+ "semi_join_strategy": "SJ-Materialization",
"join_order": [
{
"table": "t_inner_1"
@@ -7026,4 +7251,32 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
}
]
DROP TABLE t1;
+#
+# Test for Semi-Join table pullout element
+#
+create table t1 (a int primary key, b int);
+insert into t1 (a) values (1),(2),(3),(4),(5);
+create table t2 (a int primary key, b int);
+insert into t2 (a) values (1),(2),(3),(4),(5);
+create table t3 (a int);
+insert into t3 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+explain
+select * from t3 where (a,a) in (select t1.a, t2.a from t1, t2 where t1.b=t2.b);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL PRIMARY NULL NULL NULL 5
+1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where
+1 PRIMARY t3 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.semijoin_table_pullout')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.semijoin_table_pullout'))
+[
+
+ {
+ "pulled_out_tables":
+ [
+ "t2",
+ "t1"
+ ]
+ }
+]
+drop table t1,t2,t3;
set optimizer_trace='enabled=off';
diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test
index 085b7e0aea8..51950f00781 100644
--- a/mysql-test/main/opt_trace.test
+++ b/mysql-test/main/opt_trace.test
@@ -549,4 +549,22 @@ select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) fr
DROP TABLE t1;
+--echo #
+--echo # Test for Semi-Join table pullout element
+--echo #
+create table t1 (a int primary key, b int);
+insert into t1 (a) values (1),(2),(3),(4),(5);
+
+create table t2 (a int primary key, b int);
+insert into t2 (a) values (1),(2),(3),(4),(5);
+
+create table t3 (a int);
+insert into t3 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
+
+explain
+select * from t3 where (a,a) in (select t1.a, t2.a from t1, t2 where t1.b=t2.b);
+
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.semijoin_table_pullout')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+drop table t1,t2,t3;
set optimizer_trace='enabled=off';
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 599642b3a26..9205380bd19 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -2192,12 +2192,15 @@ int pull_out_semijoin_tables(JOIN *join)
TABLE_LIST *sj_nest;
DBUG_ENTER("pull_out_semijoin_tables");
List_iterator<TABLE_LIST> sj_list_it(join->select_lex->sj_nests);
-
+
/* Try pulling out of the each of the semi-joins */
while ((sj_nest= sj_list_it++))
{
List_iterator<TABLE_LIST> child_li(sj_nest->nested_join->join_list);
TABLE_LIST *tbl;
+ Json_writer_object trace_wrapper(join->thd);
+ Json_writer_object trace(join->thd, "semijoin_table_pullout");
+ Json_writer_array trace_arr(join->thd, "pulled_out_tables");
/*
Don't do table pull-out for nested joins (if we get nested joins here, it
@@ -2296,7 +2299,8 @@ int pull_out_semijoin_tables(JOIN *join)
pulled_a_table= TRUE;
pulled_tables |= tbl->table->map;
DBUG_PRINT("info", ("Table %s pulled out (reason: func dep)",
- tbl->table->alias.c_ptr()));
+ tbl->table->alias.c_ptr_safe()));
+ trace_arr.add(tbl->table->alias.c_ptr_safe());
/*
Pulling a table out of uncorrelated subquery in general makes
makes it correlated. See the NOTE to this funtion.
@@ -2778,27 +2782,30 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
{
POSITION *pos= join->positions + idx;
const JOIN_TAB *new_join_tab= pos->table;
- Semi_join_strategy_picker *pickers[]=
- {
- &pos->firstmatch_picker,
- &pos->loosescan_picker,
- &pos->sjmat_picker,
- &pos->dups_weedout_picker,
- NULL,
- };
-
- if (join->emb_sjm_nest)
+ if (join->emb_sjm_nest || //(1)
+ !join->select_lex->have_merged_subqueries) //(2)
{
/*
- We're performing optimization inside SJ-Materialization nest:
+ (1): We're performing optimization inside SJ-Materialization nest:
- there are no other semi-joins inside semi-join nests
- attempts to build semi-join strategies here will confuse
the optimizer, so bail out.
+ (2): Don't waste time on semi-join optimizations if we don't have any
+ semi-joins
*/
pos->sj_strategy= SJ_OPT_NONE;
return;
}
+ Semi_join_strategy_picker *pickers[]=
+ {
+ &pos->firstmatch_picker,
+ &pos->loosescan_picker,
+ &pos->sjmat_picker,
+ &pos->dups_weedout_picker,
+ NULL,
+ };
+ Json_writer_array trace_steps(join->thd, "semijoin_strategy_choice");
/*
Update join->cur_sj_inner_tables (Used by FirstMatch in this function and
LooseScan detector in best_access_path)
@@ -2897,6 +2904,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
*current_read_time= read_time;
*current_record_count= rec_count;
dups_producing_tables &= ~handled_fanout;
+
//TODO: update bitmap of semi-joins that were handled together with
// others.
if (is_multiple_semi_joins(join, join->positions, idx,
@@ -2924,6 +2932,30 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
}
}
}
+
+ if (unlikely(join->thd->trace_started() && pos->sj_strategy != SJ_OPT_NONE))
+ {
+ Json_writer_object tr(join->thd);
+ const char *sname;
+ switch (pos->sj_strategy) {
+ case SJ_OPT_MATERIALIZE:
+ sname= "SJ-Materialize";
+ break;
+ case SJ_OPT_MATERIALIZE_SCAN:
+ sname= "SJ-Materialize-Scan";
+ break;
+ case SJ_OPT_FIRST_MATCH:
+ sname= "FirstMatch";
+ break;
+ case SJ_OPT_DUPS_WEEDOUT:
+ sname= "DuplicateWeedout";
+ break;
+ default:
+ DBUG_ASSERT(0);
+ sname="Invalid";
+ }
+ tr.add("chosen_strategy", sname);
+ }
}
if ((emb_sj_nest= new_join_tab->emb_sj_nest))
@@ -3000,6 +3032,8 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
}
else
{
+ Json_writer_object trace(join->thd);
+ trace.add("strategy", "SJ-Materialization");
/* This is SJ-Materialization with lookups */
Cost_estimate prefix_cost;
signed int first_tab= (int)idx - mat_info->tables;
@@ -3032,6 +3066,11 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
*record_count= prefix_rec_count;
*handled_fanout= new_join_tab->emb_sj_nest->sj_inner_tables;
*strategy= SJ_OPT_MATERIALIZE;
+ if (unlikely(join->thd->trace_started()))
+ {
+ trace.add("records", *record_count);
+ trace.add("read_time", *read_time);
+ }
return TRUE;
}
}
@@ -3040,6 +3079,8 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
if (sjm_scan_need_tables && /* Have SJM-Scan prefix */
!(sjm_scan_need_tables & remaining_tables))
{
+ Json_writer_object trace(join->thd);
+ trace.add("strategy", "SJ-Materialization-Scan");
TABLE_LIST *mat_nest=
join->positions[sjm_scan_last_inner].table->emb_sj_nest;
SJ_MATERIALIZATION_INFO *mat_info= mat_nest->sj_mat_info;
@@ -3088,6 +3129,11 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
*read_time= prefix_cost;
*record_count= prefix_rec_count;
*handled_fanout= mat_nest->sj_inner_tables;
+ if (unlikely(join->thd->trace_started()))
+ {
+ trace.add("records", *record_count);
+ trace.add("read_time", *read_time);
+ }
return TRUE;
}
return FALSE;
@@ -3151,6 +3197,8 @@ bool LooseScan_picker::check_qep(JOIN *join,
!(remaining_tables & loosescan_need_tables) &&
(new_join_tab->table->map & loosescan_need_tables))
{
+ Json_writer_object trace(join->thd);
+ trace.add("strategy", "SJ-Materialization-Scan");
/*
Ok we have LooseScan plan and also have all LooseScan sj-nest's
inner tables and outer correlated tables into the prefix.
@@ -3181,6 +3229,11 @@ bool LooseScan_picker::check_qep(JOIN *join,
*/
*strategy= SJ_OPT_LOOSE_SCAN;
*handled_fanout= first->table->emb_sj_nest->sj_inner_tables;
+ if (unlikely(join->thd->trace_started()))
+ {
+ trace.add("records", *record_count);
+ trace.add("read_time", *read_time);
+ }
return TRUE;
}
return FALSE;
@@ -3260,6 +3313,8 @@ bool Firstmatch_picker::check_qep(JOIN *join,
if (in_firstmatch_prefix() &&
!(firstmatch_need_tables & remaining_tables))
{
+ Json_writer_object trace(join->thd);
+ trace.add("strategy", "FirstMatch");
/*
Got a complete FirstMatch range. Calculate correct costs and fanout
*/
@@ -3292,6 +3347,11 @@ bool Firstmatch_picker::check_qep(JOIN *join,
*handled_fanout= firstmatch_need_tables;
/* *record_count and *read_time were set by the above call */
*strategy= SJ_OPT_FIRST_MATCH;
+ if (unlikely(join->thd->trace_started()))
+ {
+ trace.add("records", *record_count);
+ trace.add("read_time", *read_time);
+ }
return TRUE;
}
}
@@ -3370,6 +3430,8 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
double sj_inner_fanout= 1.0;
double sj_outer_fanout= 1.0;
uint temptable_rec_size;
+ Json_writer_object trace(join->thd);
+ trace.add("strategy", "DuplicateWeedout");
if (first_tab == join->const_tables)
{
prefix_rec_count= 1.0;
@@ -3430,6 +3492,11 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
*record_count= prefix_rec_count * sj_outer_fanout;
*handled_fanout= dups_removed_fanout;
*strategy= SJ_OPT_DUPS_WEEDOUT;
+ if (unlikely(join->thd->trace_started()))
+ {
+ trace.add("records", *record_count);
+ trace.add("read_time", *read_time);
+ }
return TRUE;
}
return FALSE;
@@ -3660,7 +3727,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
join->best_positions[first].n_sj_tables= sjm->tables;
join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE;
Json_writer_object semijoin_strategy(thd);
- semijoin_strategy.add("semi_join_strategy","sj_materialize");
+ semijoin_strategy.add("semi_join_strategy","SJ-Materialization");
Json_writer_array semijoin_plan(thd, "join_order");
for (uint i= first; i < first+ sjm->tables; i++)
{
@@ -3709,7 +3776,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
POSITION dummy;
join->cur_sj_inner_tables= 0;
Json_writer_object semijoin_strategy(thd);
- semijoin_strategy.add("semi_join_strategy","sj_materialize_scan");
+ semijoin_strategy.add("semi_join_strategy","SJ-Materialization-Scan");
Json_writer_array semijoin_plan(thd, "join_order");
for (i= first + sjm->tables; i <= tablenr; i++)
{
@@ -3747,7 +3814,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
*/
join->cur_sj_inner_tables= 0;
Json_writer_object semijoin_strategy(thd);
- semijoin_strategy.add("semi_join_strategy","firstmatch");
+ semijoin_strategy.add("semi_join_strategy","FirstMatch");
Json_writer_array semijoin_plan(thd, "join_order");
for (idx= first; idx <= tablenr; idx++)
{
@@ -3785,7 +3852,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
*/
join->cur_sj_inner_tables= 0;
Json_writer_object semijoin_strategy(thd);
- semijoin_strategy.add("semi_join_strategy","sj_materialize");
+ semijoin_strategy.add("semi_join_strategy","LooseScan");
Json_writer_array semijoin_plan(thd, "join_order");
for (idx= first; idx <= tablenr; idx++)
{
1
0
[Commits] de2db8acf74: MDEV-20109: Optimizer ignores distinct key created for materialized...
by psergey 22 Aug '19
by psergey 22 Aug '19
22 Aug '19
revision-id: de2db8acf746eec785f40ff778251fd0aa3949ae (mariadb-10.4.7-32-gde2db8acf74)
parent(s): 235cf969d21ba3406a9325d952fda47c589e58d6
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-08-23 00:59:50 +0300
message:
MDEV-20109: Optimizer ignores distinct key created for materialized...
Sj_materialization_picker::check_qep(): fix error in cost/fanout
calculations:
- for each join prefix, add #prefix_rows / TIME_FOR_COMPARE to the cost,
like best_extension_by_limited_search does
- Remove the fanout produced by the subquery tables.
optimize_wo_join_buffering() (used by LooseScan and FirstMatch)
- also add #prefix_rows / TIME_FOR_COMPARE to the cost of each prefix.
---
mysql-test/main/analyze_stmt_privileges2.result | 142 ++++++++--------
mysql-test/main/cte_nonrecursive.result | 24 +--
mysql-test/main/group_by.result | 3 +-
mysql-test/main/index_merge_myisam.result | 5 +-
mysql-test/main/innodb_ext_key.result | 8 +-
mysql-test/main/opt_trace.result | 214 +++++++++++++++---------
mysql-test/main/opt_tvc.result | 72 ++++----
mysql-test/main/subselect.result | 8 +-
mysql-test/main/subselect3.result | 18 +-
mysql-test/main/subselect3_jcl6.result | 20 +--
mysql-test/main/subselect_mat.result | 16 +-
mysql-test/main/subselect_no_mat.result | 10 +-
mysql-test/main/subselect_no_scache.result | 8 +-
mysql-test/main/subselect_sj.result | 60 +++++--
mysql-test/main/subselect_sj.test | 25 +++
mysql-test/main/subselect_sj2.result | 23 +--
mysql-test/main/subselect_sj2_jcl6.result | 22 +--
mysql-test/main/subselect_sj2_mat.result | 51 +++---
mysql-test/main/subselect_sj_jcl6.result | 61 ++++---
mysql-test/main/subselect_sj_mat.result | 26 +--
mysql-test/main/table_value_constr.result | 24 +--
sql/opt_subselect.cc | 5 +-
sql/sql_select.cc | 3 +-
23 files changed, 491 insertions(+), 357 deletions(-)
diff --git a/mysql-test/main/analyze_stmt_privileges2.result b/mysql-test/main/analyze_stmt_privileges2.result
index cf38810b598..f269aaf540b 100644
--- a/mysql-test/main/analyze_stmt_privileges2.result
+++ b/mysql-test/main/analyze_stmt_privileges2.result
@@ -376,13 +376,13 @@ SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM t1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 0.00 100.00 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
#------------------------------------------------------------------------
# I/R/U/D/S on the inner view
@@ -491,14 +491,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -598,14 +598,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 12 12.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 12.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the table
@@ -1591,14 +1591,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything: SELECT access to the column `a`
@@ -1708,14 +1708,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant SELECT, INSERT, UPDATE, DELETE on the table
@@ -1940,14 +1940,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 4.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -2048,14 +2048,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 8 8.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#########################################################################
# Inner view permission tests
@@ -2697,14 +2697,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 14 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 14 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 14 14.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 14 14.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -2804,14 +2804,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 18 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 18 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 18 18.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 18 18.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the inner view
@@ -3987,14 +3987,14 @@ SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 35 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 35 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v1 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 35 35.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00
+1 PRIMARY t1 ALL NULL NULL NULL NULL 35 35.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#------------------------------------------------------------------------
# I/R/U/D/S on the outer view
# Expectation: Can run everything
@@ -4094,14 +4094,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#########################################################################
# Outer view permission tests
@@ -4614,14 +4614,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 39 39.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
#========================================================================
# Test: Grant INSERT on the outer view
@@ -5221,14 +5221,14 @@ SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
a b
EXPLAIN SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 44 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 44 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
ANALYZE SELECT * FROM v2 WHERE a IN ( SELECT a FROM t2 );
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 3.00 100.00 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 44 44.00 100.00 0.00 Using where; Using join buffer (flat, BNL join)
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 3.00 100.00 100.00 Using where
+1 PRIMARY t1 ALL NULL NULL NULL NULL 44 44.00 100.00 0.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 NULL 100.00 NULL
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 NULL 100.00 NULL
disconnect con1;
connection default;
DROP USER 'privtest'@localhost;
diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result
index 2556fd4b06b..12a7e2ea789 100644
--- a/mysql-test/main/cte_nonrecursive.result
+++ b/mysql-test/main/cte_nonrecursive.result
@@ -1159,9 +1159,9 @@ with cte as
union
(select a from t1 where a < 2);
a
-7
-5
4
+5
+7
1
prepare stmt from "with cte as
(select a from t1 where a between 4 and 7 group by a)
@@ -1170,15 +1170,15 @@ union
(select a from t1 where a < 2)";
execute stmt;
a
-7
-5
4
+5
+7
1
execute stmt;
a
-7
-5
4
+5
+7
1
deallocate prepare stmt;
with cte as
@@ -1188,9 +1188,9 @@ union
(select a from cte where exists( select a from t1 where cte.a=t1.a ));
a
1
-7
-5
4
+5
+7
prepare stmt from "with cte as
(select a from t1 where a between 4 and 7 group by a)
(select a from t1 where a < 2)
@@ -1199,15 +1199,15 @@ union
execute stmt;
a
1
-7
-5
4
+5
+7
execute stmt;
a
1
-7
-5
4
+5
+7
deallocate prepare stmt;
with cte as
(select a from t1 where a between 4 and 7)
diff --git a/mysql-test/main/group_by.result b/mysql-test/main/group_by.result
index 2eaec8a08b4..44ebce66b22 100644
--- a/mysql-test/main/group_by.result
+++ b/mysql-test/main/group_by.result
@@ -1608,7 +1608,8 @@ EXPLAIN SELECT 1 FROM t2 WHERE a IN
(SELECT a FROM t1 USE INDEX (i2) IGNORE INDEX (i2));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index a a 5 NULL 4 Using index
-1 PRIMARY t1 ALL NULL NULL NULL NULL 144 Using where; FirstMatch(t2)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t1 ALL NULL NULL NULL NULL 144
SET optimizer_switch=@save_optimizer_switch;
DROP TABLE t1, t2;
CREATE TABLE t1(
diff --git a/mysql-test/main/index_merge_myisam.result b/mysql-test/main/index_merge_myisam.result
index 484ee626b98..7e57c916d04 100644
--- a/mysql-test/main/index_merge_myisam.result
+++ b/mysql-test/main/index_merge_myisam.result
@@ -558,8 +558,9 @@ where exists (select 1 from t2, t3
where t2.a=t1.a and (t3.a=t2.b or t3.b=t2.b or t3.b=t2.b+1));
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
-1 PRIMARY t3 ALL a,b NULL NULL NULL 1002 Range checked for each record (index map: 0x3); FirstMatch(t1)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
+2 MATERIALIZED t3 ALL a,b NULL NULL NULL 1002 Range checked for each record (index map: 0x3)
select * from t1
where exists (select 1 from t2, t3
where t2.a=t1.a and (t3.a=t2.b or t3.b=t2.b or t3.b=t2.b+1));
diff --git a/mysql-test/main/innodb_ext_key.result b/mysql-test/main/innodb_ext_key.result
index b4572174fcb..2ec3a9ae951 100644
--- a/mysql-test/main/innodb_ext_key.result
+++ b/mysql-test/main/innodb_ext_key.result
@@ -732,8 +732,8 @@ SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index a,b b 7 NULL 10 Using index
-1 PRIMARY t1 ref b b 3 test.t.b 2 Using index
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t)
+1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; Start temporary
+1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
@@ -745,8 +745,8 @@ SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index a,b b 7 NULL 10 Using index
-1 PRIMARY t1 ref b b 3 test.t.b 2 Using index
-1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; FirstMatch(t)
+1 PRIMARY t1 ref b b 3 test.t.b 2 Using index; Start temporary
+1 PRIMARY t2 index NULL PRIMARY 4 NULL 11 Using index; End temporary; Using join buffer (flat, BNL join)
1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 test.t.a 1 Using index
SELECT a FROM t1 AS t, t2
WHERE c = a AND b IN (SELECT b FROM t1, t2 WHERE b = t.b);
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 518da2888cc..5dfe3241862 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -4308,11 +4308,11 @@ explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_
t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t_outer_1 ALL NULL NULL NULL NULL 3
-1 PRIMARY t_inner_1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY t_inner_2 ALL NULL NULL NULL NULL 9 FirstMatch(t_outer_1); Using join buffer (incremental, BNL join)
+1 PRIMARY t_inner_1 ALL NULL NULL NULL NULL 3 Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY t_inner_2 ALL NULL NULL NULL NULL 9 End temporary; Using join buffer (incremental, BNL join)
+1 PRIMARY t_inner_4 ALL NULL NULL NULL NULL 3 Start temporary; Using join buffer (incremental, BNL join)
1 PRIMARY t_outer_2 ALL NULL NULL NULL NULL 9 Using join buffer (incremental, BNL join)
-1 PRIMARY t_inner_4 ALL NULL NULL NULL NULL 3 Using join buffer (incremental, BNL join)
-1 PRIMARY t_inner_3 ALL NULL NULL NULL NULL 9 Using where; FirstMatch(t_outer_2); Using join buffer (incremental, BNL join)
+1 PRIMARY t_inner_3 ALL NULL NULL NULL NULL 9 Using where; End temporary; Using join buffer (incremental, BNL join)
select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_inner_1.a from t2 t_inner_2, t1 t_inner_1) and
@@ -4580,7 +4580,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 27,
- "cost_for_plan": 34.174,
+ "cost_for_plan": 44.641,
"rest_of_plan": [
{
"plan_prefix": [
@@ -4601,7 +4601,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 81,
- "cost_for_plan": 52.379,
+ "cost_for_plan": 62.846,
"rest_of_plan": [
{
"plan_prefix": [
@@ -4623,7 +4623,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 729,
- "cost_for_plan": 200.19
+ "cost_for_plan": 210.66
}
]
},
@@ -4646,7 +4646,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 243,
- "cost_for_plan": 84.79,
+ "cost_for_plan": 95.256,
"pruned_by_heuristic": true
}
]
@@ -4665,7 +4665,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 9,
- "cost_for_plan": 30.564,
+ "cost_for_plan": 41.031,
"rest_of_plan": [
{
"plan_prefix": [
@@ -4686,7 +4686,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 81,
- "cost_for_plan": 48.779,
+ "cost_for_plan": 59.246,
"rest_of_plan": [
{
"plan_prefix": [
@@ -4708,8 +4708,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 729,
- "cost_for_plan": 196.59,
- "pruned_by_cost": true
+ "cost_for_plan": 207.06
}
]
},
@@ -4732,7 +4731,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 81,
- "cost_for_plan": 48.779,
+ "cost_for_plan": 59.246,
"pruned_by_heuristic": true
}
]
@@ -4751,7 +4750,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
"rows_for_plan": 27,
- "cost_for_plan": 34.174,
+ "cost_for_plan": 44.641,
"pruned_by_heuristic": true
}
]
@@ -4787,7 +4786,76 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 172.44,
- "pruned_by_cost": true
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_2"
+ ],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 81,
+ "cost_for_plan": 304.05,
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_2",
+ "t_inner_4"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 729,
+ "cost_for_plan": 451.86,
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_2"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 243,
+ "cost_for_plan": 336.46,
+ "pruned_by_cost": true
+ }
+ ]
},
{
"plan_prefix": ["t_outer_1", "t_inner_1", "t_outer_2"],
@@ -4866,7 +4934,52 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
},
"rows_for_plan": 729,
"cost_for_plan": 172.44,
- "pruned_by_heuristic": true
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_3"
+ ],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 2187,
+ "cost_for_plan": 611.85,
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_3"
+ ],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rows_for_plan": 6561,
+ "cost_for_plan": 1486.7,
+ "pruned_by_cost": true
+ }
+ ]
}
]
},
@@ -5303,70 +5416,7 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
]
},
{
- "fix_semijoin_strategies_for_picked_join_order": [
- {
- "semi_join_strategy": "firstmatch",
- "join_order": [
- {
- "table": "t_inner_4"
- },
- "best_access_path": {
- "considered_access_paths": [
- {
- "access_type": "scan",
- "resulting_rows": 3,
- "cost": 162.42,
- "chosen": true
- }
- ]
- },
- {
- "table": "t_inner_3"
- },
- "best_access_path": {
- "considered_access_paths": [
- {
- "access_type": "scan",
- "resulting_rows": 9,
- "cost": 489.74,
- "chosen": true
- }
- ]
- }
- ]
- },
- {
- "semi_join_strategy": "firstmatch",
- "join_order": [
- {
- "table": "t_inner_1"
- },
- "best_access_path": {
- "considered_access_paths": [
- {
- "access_type": "scan",
- "resulting_rows": 3,
- "cost": 18.046,
- "chosen": true
- }
- ]
- },
- {
- "table": "t_inner_2"
- },
- "best_access_path": {
- "considered_access_paths": [
- {
- "access_type": "scan",
- "resulting_rows": 9,
- "cost": 54.415,
- "chosen": true
- }
- ]
- }
- ]
- }
- ]
+ "fix_semijoin_strategies_for_picked_join_order": []
},
{
"attaching_conditions_to_tables": {
@@ -5386,11 +5436,11 @@ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
"attached": null
},
{
- "table": "t_outer_2",
+ "table": "t_inner_4",
"attached": null
},
{
- "table": "t_inner_4",
+ "table": "t_outer_2",
"attached": null
},
{
diff --git a/mysql-test/main/opt_tvc.result b/mysql-test/main/opt_tvc.result
index d503dab4d99..5329a9f64be 100644
--- a/mysql-test/main/opt_tvc.result
+++ b/mysql-test/main/opt_tvc.result
@@ -46,12 +46,12 @@ a b
2 5
explain extended select * from t1 where a in (1,2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from t1
where a in
(
@@ -59,12 +59,12 @@ select *
from (values (1),(2)) as tvc_0
);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
# AND-condition with IN-predicates in WHERE-part
select * from t1
where a in (1,2) and
@@ -90,15 +90,15 @@ explain extended select * from t1
where a in (1,2) and
b in (1,5);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`_col_1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where 1
explain extended select * from t1
where a in
(
@@ -111,15 +111,15 @@ select *
from (values (1),(5)) as tvc_1
);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
4 MATERIALIZED <derived5> ALL NULL NULL NULL NULL 2 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
5 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where `test`.`t1`.`b` = `tvc_1`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) semi join ((values (1),(5)) `tvc_1`) where 1
# subquery with IN-predicate
select * from t1
where a in
@@ -206,12 +206,12 @@ from t1
where a in (1,2)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from
(
select *
@@ -224,12 +224,12 @@ as tvc_0
)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
# non-recursive CTE with IN-predicate
with tvc_0 as
(
@@ -265,12 +265,12 @@ where a in (1,2)
)
select * from tvc_0;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
+Note 1003 with tvc_0 as (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` in (1,2))/* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from
(
select *
@@ -283,12 +283,12 @@ as tvc_0
)
) as dr_table;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
# VIEW with IN-predicate
create view v1 as
select *
@@ -316,20 +316,20 @@ a b
2 5
explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from v2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived4> ALL NULL NULL NULL NULL 2 100.00
4 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
drop view v1,v2;
# subselect defined by derived table with IN-predicate
select * from t1
@@ -519,12 +519,12 @@ a b
1 2
explain extended select * from t1 where (a,b) in ((1,2),(3,4));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`_col_1` and `test`.`t1`.`b` = `tvc_0`.`_col_2`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1,2),(3,4)) `tvc_0`) where 1
set @@in_predicate_conversion_threshold= 2;
# trasformation works for the one IN predicate and doesn't work for the other
set @@in_predicate_conversion_threshold= 5;
@@ -538,12 +538,12 @@ explain extended select * from t2
where (a,b) in ((1,2),(8,9)) and
(a,c) in ((1,3),(8,0),(5,1));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 6 100.00 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 3 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where `test`.`t2`.`a` = `tvc_0`.`_col_1` and `test`.`t2`.`c` = `tvc_0`.`_col_2` and (`tvc_0`.`_col_1`,`test`.`t2`.`b`) in (<cache>((1,2)),<cache>((8,9)))
+Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` semi join ((values (1,3),(8,0),(5,1)) `tvc_0`) where (`test`.`t2`.`a`,`test`.`t2`.`b`) in (<cache>((1,2)),<cache>((8,9)))
set @@in_predicate_conversion_threshold= 2;
#
# mdev-14281: conversion of NOT IN predicate into subquery predicate
diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result
index fc0049db997..5e446a171fe 100644
--- a/mysql-test/main/subselect.result
+++ b/mysql-test/main/subselect.result
@@ -5703,8 +5703,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 USE INDEX() WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
@@ -5714,8 +5714,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 index idx idx 5 NULL 3 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect3.result b/mysql-test/main/subselect3.result
index ca151daf146..3c33182b3ef 100644
--- a/mysql-test/main/subselect3.result
+++ b/mysql-test/main/subselect3.result
@@ -1139,8 +1139,8 @@ create table t3 (a int);
insert into t3 select A.a + 10*B.a from t0 A, t0 B;
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
create table t4 (pk int primary key);
insert into t4 select a from t3;
explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
@@ -1276,12 +1276,12 @@ insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
create table t2 as select * from t1;
explain select * from t2 where a in (select b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
drop table t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int, b int);
@@ -1339,9 +1339,9 @@ insert into t2 select * from t2;
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where
-1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where
-1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; FirstMatch(t1)
+1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; End temporary; Using join buffer (flat, BNL join)
drop table t0,t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/main/subselect3_jcl6.result b/mysql-test/main/subselect3_jcl6.result
index adb3ec80394..69f720a95b7 100644
--- a/mysql-test/main/subselect3_jcl6.result
+++ b/mysql-test/main/subselect3_jcl6.result
@@ -1149,8 +1149,8 @@ create table t3 (a int);
insert into t3 select A.a + 10*B.a from t0 A, t0 B;
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
create table t4 (pk int primary key);
insert into t4 select a from t3;
explain select * from t3 where a in (select t1.kp1 from t1,t4 where kp1<20
@@ -1286,12 +1286,12 @@ insert into t1 select A.a, B.a, 'filler' from t0 A, t0 B;
create table t2 as select * from t1;
explain select * from t2 where a in (select b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
explain select * from t2 where (b,a) in (select a,b from t1 where a=3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ref a a 5 const 8 Using index; LooseScan
-1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref a a 10 const,test.t2.a 1 Using index; FirstMatch(t2)
drop table t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
create table t1 (a int, b int);
@@ -1348,10 +1348,10 @@ create table t2 as select a as a, a as b from t0 where a < 3;
insert into t2 select * from t2;
explain select * from t1 where (a,b,c) in (select X.a, Y.a, Z.a from t2 X, t2 Y, t2 Z where X.b=33);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3
-1 PRIMARY X ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY Y ALL NULL NULL NULL NULL 6 Using where; Using join buffer (incremental, BNL join)
-1 PRIMARY Z ALL NULL NULL NULL NULL 6 Using where; FirstMatch(t1); Using join buffer (incremental, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
+1 PRIMARY X hash_ALL NULL #hash#$hj 5 test.t1.a 6 Using where; Start temporary; Using join buffer (flat, BNLH join)
+1 PRIMARY Y hash_ALL NULL #hash#$hj 5 test.t1.b 6 Using where; Using join buffer (incremental, BNLH join)
+1 PRIMARY Z hash_ALL NULL #hash#$hj 5 test.t1.c 6 Using where; End temporary; Using join buffer (incremental, BNLH join)
drop table t0,t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result
index 4e03d9663ef..ee680d40b75 100644
--- a/mysql-test/main/subselect_mat.result
+++ b/mysql-test/main/subselect_mat.result
@@ -1510,8 +1510,8 @@ set @@optimizer_switch=@optimizer_switch_local_default;
SET @@optimizer_switch='semijoin=on,materialization=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 7 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
COUNT(*)
@@ -2437,8 +2437,8 @@ INSERT INTO t2 VALUES (11,11),(12,12),(13,13);
explain
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t2.i1 9 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 9
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
1
@@ -2450,8 +2450,8 @@ alter table t1 add key(id);
explain
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index
+1 PRIMARY t1 index id id 4 NULL 9 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
1
@@ -2507,8 +2507,8 @@ INSERT INTO t2 VALUES (11,11),(12,12),(13,13);
CREATE VIEW v1 AS SELECT t2.i1 FROM t2 where t2.i1 = t2.i2;
explain SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index
+1 PRIMARY t1 index id id 4 NULL 9 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1);
1
diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result
index 4ebf04b1f55..ecd973da09d 100644
--- a/mysql-test/main/subselect_no_mat.result
+++ b/mysql-test/main/subselect_no_mat.result
@@ -5683,9 +5683,9 @@ WHERE (ot1.a,ot4.a) IN (SELECT it2.a,it3.a
FROM it2,it3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY ot1 ALL NULL NULL NULL NULL 2
-1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using join buffer (flat, BNL join)
-1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where
-1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using where; FirstMatch(ot4)
+1 PRIMARY it2 ALL NULL NULL NULL NULL 4 Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY it3 ALL NULL NULL NULL NULL 6 Using join buffer (flat, BNL join)
+1 PRIMARY ot4 ALL NULL NULL NULL NULL 8 Using where; End temporary; Using join buffer (flat, BNL join)
DROP TABLE IF EXISTS ot1, ot4, it2, it3;
#
# Bug#729039: NULL keys used to evaluate subquery
@@ -5712,8 +5712,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index idx idx 5 NULL 3 Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where
+1 PRIMARY t2 ref idx idx 5 test.t1.a 2 Using index; FirstMatch(t1)
DROP TABLE t1,t2;
#
# BUG#752992: Wrong results for a subquery with 'semijoin=on'
diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result
index 71d61e797f3..318ad02d473 100644
--- a/mysql-test/main/subselect_no_scache.result
+++ b/mysql-test/main/subselect_no_scache.result
@@ -5709,8 +5709,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 USE INDEX() WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
@@ -5720,8 +5720,8 @@ EXPLAIN
SELECT * FROM t1
WHERE EXISTS (SELECT a FROM t2 WHERE t2.a = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 4
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 index idx idx 5 NULL 3 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect_sj.result b/mysql-test/main/subselect_sj.result
index 98143246673..3bd08e303b8 100644
--- a/mysql-test/main/subselect_sj.result
+++ b/mysql-test/main/subselect_sj.result
@@ -729,8 +729,8 @@ SELECT int_key FROM ot1
WHERE int_nokey IN (SELECT it2.int_key
FROM it1 LEFT JOIN it2 ON it2.datetime_key);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 20
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it1 index NULL int_key 4 NULL 2 Using index
2 MATERIALIZED it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where
DROP TABLE ot1, it1, it2;
@@ -972,11 +972,11 @@ SELECT `varchar_key` , `varchar_nokey`
FROM t1
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 15 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and `test`.`t2`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
+Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
SELECT varchar_nokey
FROM t2
WHERE ( `varchar_nokey` , `varchar_nokey` ) IN (
@@ -1246,8 +1246,8 @@ INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1);
EXPLAIN
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; Start temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; End temporary; Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
i
1
@@ -1757,8 +1757,8 @@ insert into t3 values('three'),( 'four');
insert into t3 values('three'),( 'four');
explain select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func 1
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
@@ -1991,12 +1991,13 @@ CREATE VIEW v4 AS SELECT DISTINCT f2 FROM t4 ;
explain extended
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3) WHERE t2.f3 IN (SELECT * FROM t4);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
-1 PRIMARY t4 ref f2 f2 5 test.t2.f3 2 100.00 Using index; FirstMatch(t2)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t3 ALL NULL NULL NULL NULL 5 100.00 Using where; Using join buffer (flat, BNL join)
+2 MATERIALIZED t4 index f2 f2 5 NULL 2 100.00 Using index
Warnings:
-Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3`,`test`.`t3`.`f3` AS `f3` from `test`.`t1` semi join (`test`.`t4`) join `test`.`t2` join `test`.`t3` where `test`.`t4`.`f2` = `test`.`t2`.`f3` and `test`.`t3`.`f1` = `test`.`t1`.`f1` and `test`.`t1`.`f2` = `test`.`t2`.`f2`
+Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2`,`test`.`t2`.`f3` AS `f3`,`test`.`t3`.`f3` AS `f3` from `test`.`t1` semi join (`test`.`t4`) join `test`.`t2` join `test`.`t3` where `test`.`t3`.`f1` = `test`.`t1`.`f1` and `test`.`t1`.`f2` = `test`.`t2`.`f2`
SELECT * FROM t1 NATURAL LEFT JOIN (t2, t3) WHERE t2.f3 IN (SELECT * FROM t4);
f1 f2 f3 f3
2 0 0 0
@@ -2495,8 +2496,8 @@ WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 1
-1 PRIMARY t1 ref a a 5 const 1 Using index
-1 PRIMARY t2 ref a a 5 func 1 Using index
+1 PRIMARY t2 ref a a 5 const 1 Using index
+1 PRIMARY t1 ref a a 5 func 1 Using index
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 0
SELECT * FROM t1, t2
WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
@@ -2706,8 +2707,8 @@ a
19
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
drop table t0,t1,t3;
set optimizer_switch= @tmp_923246;
#
@@ -2923,8 +2924,8 @@ WHERE alias1.pk = 58 OR alias1.col_varchar_key = 'o'
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
-1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where
-1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); FirstMatch(t2)
+1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where; Start temporary
+1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); End temporary
SELECT *
FROM t2
WHERE (field1) IN (SELECT alias1.col_varchar_nokey AS field1
@@ -3264,4 +3265,27 @@ create table t2 (a2 varchar(25)) ;
insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2);
drop table t1,t2;
# End of 5.5 test
+#
+# MDEV-20109: Optimizer ignores distinct key created for materialized
+# semi-join subquery when searching for best execution plan
+#
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+# The following must not use this query plan that does a cross join:
+# | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+# | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+#
+# Instead, it should use eq_ref on the materialized table.
+explain select * from t3 where a in (select a from t4 group by a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 10000
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 500
+drop table t1, t2, t3, t4;
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/main/subselect_sj.test b/mysql-test/main/subselect_sj.test
index b693f7b5b93..a2d6c7e427c 100644
--- a/mysql-test/main/subselect_sj.test
+++ b/mysql-test/main/subselect_sj.test
@@ -2940,5 +2940,30 @@ drop table t1,t2;
--echo # End of 5.5 test
+--echo #
+--echo # MDEV-20109: Optimizer ignores distinct key created for materialized
+--echo # semi-join subquery when searching for best execution plan
+--echo #
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+
+--echo # The following must not use this query plan that does a cross join:
+--echo # | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+--echo # | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+--echo #
+--echo # Instead, it should use eq_ref on the materialized table.
+
+explain select * from t3 where a in (select a from t4 group by a);
+
+drop table t1, t2, t3, t4;
+
# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/main/subselect_sj2.result b/mysql-test/main/subselect_sj2.result
index a127c18280e..31453801220 100644
--- a/mysql-test/main/subselect_sj2.result
+++ b/mysql-test/main/subselect_sj2.result
@@ -131,8 +131,9 @@ set join_buffer_size= @save_join_buffer_size;
set max_heap_table_size= @save_max_heap_table_size;
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY t2 ref b b 5 test.t1.a 1 Using index; FirstMatch(t1)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index b b 5 NULL 20 Using index
select * from t1;
a b
1 1
@@ -159,8 +160,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -227,8 +228,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -730,8 +731,9 @@ alter table t3 add primary key(id), add key(a);
The following must use loose index scan over t3, key a:
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index a a 5 NULL 1000 Using where; Using index
-1 PRIMARY t3 ref a a 5 test.t2.a 30 Using index; FirstMatch(t2)
+1 PRIMARY t2 index a a 5 NULL 1000 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t3 index a a 5 NULL 30000 Using index
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
1000
@@ -757,9 +759,10 @@ c2 in (select 1 from t3, t2) and
c1 in (select convert(c6,char(1)) from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch((sj-nest))
+3 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
drop table t2, t3;
#
# BUG#761598: InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock() in maria-5.3
diff --git a/mysql-test/main/subselect_sj2_jcl6.result b/mysql-test/main/subselect_sj2_jcl6.result
index 56c11e8c9af..3321ba221f3 100644
--- a/mysql-test/main/subselect_sj2_jcl6.result
+++ b/mysql-test/main/subselect_sj2_jcl6.result
@@ -171,9 +171,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 32 Using where; Using join buffer (flat, BNLH join)
-2 MATERIALIZED it ALL NULL NULL NULL NULL 22 Using where
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -239,9 +239,9 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot hash_ALL NULL #hash#$hj 5 test.it.a 52 Using where; Using join buffer (flat, BNLH join)
-2 MATERIALIZED it ALL NULL NULL NULL NULL 22 Using where
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
@@ -1410,9 +1410,10 @@ SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b
WHERE c IN (SELECT t4.b FROM t4 JOIN t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
-1 PRIMARY t4 ALL NULL NULL NULL NULL 2 Using where; FirstMatch(t3); Using join buffer (incremental, BNL join)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
1 PRIMARY t1 ref b b 4 test.t3.b 1 Using index
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
SELECT t3.* FROM t1 JOIN t3 ON t3.b = t1.b
WHERE c IN (SELECT t4.b FROM t4 JOIN t2);
b c
@@ -1438,9 +1439,10 @@ EXPLAIN
SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t4 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 1 Using where
+2 MATERIALIZED t3 eq_ref PRIMARY PRIMARY 4 test.t4.b 1
SELECT * FROM t1, t2 WHERE b IN (SELECT a FROM t3, t4 WHERE b = pk);
pk a b
1 6 8
diff --git a/mysql-test/main/subselect_sj2_mat.result b/mysql-test/main/subselect_sj2_mat.result
index 73f682755da..7245e74b242 100644
--- a/mysql-test/main/subselect_sj2_mat.result
+++ b/mysql-test/main/subselect_sj2_mat.result
@@ -133,8 +133,9 @@ set join_buffer_size= @save_join_buffer_size;
set max_heap_table_size= @save_max_heap_table_size;
explain select * from t1 where a in (select b from t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
-1 PRIMARY t2 ref b b 5 test.t1.a 1 Using index; FirstMatch(t1)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t2 index b b 5 NULL 20 Using index
select * from t1;
a b
1 1
@@ -161,8 +162,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 32 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 32
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -229,8 +230,8 @@ explain select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
from t1 ot where a in (select a from t2 it);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 22
-1 PRIMARY ot ALL NULL NULL NULL NULL 52 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot ALL NULL NULL NULL NULL 52
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it ALL NULL NULL NULL NULL 22
select
a, mid(filler1, 1,10), length(filler1)=length(filler2) as Z
@@ -732,8 +733,9 @@ alter table t3 add primary key(id), add key(a);
The following must use loose index scan over t3, key a:
explain select count(a) from t2 where a in ( SELECT a FROM t3);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index a a 5 NULL 1000 Using where; Using index
-1 PRIMARY t3 ref a a 5 test.t2.a 30 Using index; FirstMatch(t2)
+1 PRIMARY t2 index a a 5 NULL 1000 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t3 index a a 5 NULL 30000 Using index
select count(a) from t2 where a in ( SELECT a FROM t3);
count(a)
1000
@@ -759,9 +761,10 @@ c2 in (select 1 from t3, t2) and
c1 in (select convert(c6,char(1)) from t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where
-1 PRIMARY t2 ALL NULL NULL NULL NULL 1 Using where; FirstMatch(t2)
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 1
-1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch(t2)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 FirstMatch((sj-nest))
+3 MATERIALIZED t2 ALL NULL NULL NULL NULL 1
drop table t2, t3;
#
# BUG#761598: InnoDB: Error: row_search_for_mysql() is called without ha_innobase::external_lock() in maria-5.3
@@ -1638,12 +1641,12 @@ set optimizer_switch='materialization=on,semijoin=on';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 = i2 OR 1=2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 5 test.t2.i2 5 100.00 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 MATERIALIZED t3 hash_ALL NULL #hash#$hj 5 test.t2.i2 3 100.00 Using where; Using join buffer (flat, BNLH join)
Warnings:
-Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`i1` = `test`.`t2`.`i2`
+Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2`
SELECT * FROM t1 WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 = i2 OR 1=2);
i1
7
@@ -1651,12 +1654,12 @@ EXPLAIN EXTENDED
SELECT * FROM t1
WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 > 0 AND i3 = i2 OR 1=2);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3 100.00
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 5 test.t2.i2 5 100.00 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 MATERIALIZED t3 hash_ALL NULL #hash#$hj 5 test.t2.i2 3 100.00 Using where; Using join buffer (flat, BNLH join)
Warnings:
-Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t1`.`i1` = `test`.`t2`.`i2` and `test`.`t3`.`i3` > 0
+Note 1003 select `test`.`t1`.`i1` AS `i1` from `test`.`t1` semi join (`test`.`t2` join `test`.`t3`) where `test`.`t3`.`i3` = `test`.`t2`.`i2` and `test`.`t3`.`i3` > 0
SELECT * FROM t1
WHERE i1 IN (SELECT i3 FROM t2, t3 WHERE i3 > 0 AND i3 = i2 OR 1=2);
i1
@@ -1748,8 +1751,8 @@ OR
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index PRIMARY PRIMARY 4 NULL 13 Using where; Using index
-2 MATERIALIZED <subquery3> ALL distinct_key NULL NULL NULL 8
-2 MATERIALIZED A ALL PRIMARY NULL NULL NULL 13 Using where; Using join buffer (flat, BNL join)
+2 MATERIALIZED A ALL PRIMARY NULL NULL NULL 13
+2 MATERIALIZED <subquery3> eq_ref distinct_key distinct_key 67 func 1
3 MATERIALIZED B range PRIMARY PRIMARY 4 NULL 8 Using where
SELECT SQL_NO_CACHE t.id
FROM t1 t
@@ -1914,18 +1917,16 @@ AND t3.id_product IN (SELECT id_product FROM t2 t2_5 WHERE t2_5.id_t2 = 29 OR t2
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 12
1 PRIMARY t3 eq_ref PRIMARY PRIMARY 4 test.t2_2.id_product 1 Using where; Using index
-1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 4 func 1 Using where
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 Using where
+1 PRIMARY t2_3 ref id_t2,id_product id_product 5 test.t3.id_product 44 Using index condition; Using where; Start temporary; End temporary
+1 PRIMARY t2_5 ref id_t2,id_product id_product 5 test.t3.id_product 44 Using index condition; Using where; Start temporary; End temporary
1 PRIMARY t5 ALL NULL NULL NULL NULL 18 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY <subquery6> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t4 eq_ref PRIMARY PRIMARY 8 test.t3.id_product,const 1 Using where; Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 Using where
-1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 func 1 Using where
+1 PRIMARY <subquery5> eq_ref distinct_key distinct_key 4 func 1 Using where
1 PRIMARY t1 index NULL PRIMARY 8 NULL 73 Using where; Using index; Using join buffer (flat, BNL join)
3 MATERIALIZED t2_2 ref id_t2,id_product id_t2 5 const 12 Using where
-5 MATERIALIZED t2_4 range id_t2,id_product id_t2 5 NULL 18 Using index condition; Using where
-6 MATERIALIZED t2_5 range id_t2,id_product id_t2 5 NULL 31 Using index condition; Using where
2 MATERIALIZED t2_1 ref id_t2,id_product id_t2 5 const 51
-4 MATERIALIZED t2_3 range id_t2,id_product id_t2 5 NULL 33 Using index condition; Using where
+5 MATERIALIZED t2_4 range id_t2,id_product id_t2 5 NULL 18 Using index condition; Using where
set optimizer_switch='rowid_filter=default';
drop table t1,t2,t3,t4,t5;
set global innodb_stats_persistent= @innodb_stats_persistent_save;
diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result
index acfafde6d7e..711ae32a931 100644
--- a/mysql-test/main/subselect_sj_jcl6.result
+++ b/mysql-test/main/subselect_sj_jcl6.result
@@ -742,8 +742,8 @@ SELECT int_key FROM ot1
WHERE int_nokey IN (SELECT it2.int_key
FROM it1 LEFT JOIN it2 ON it2.datetime_key);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 10
-1 PRIMARY ot1 ALL NULL NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY ot1 ALL NULL NULL NULL NULL 20
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED it1 index NULL int_key 4 NULL 2 Using index
2 MATERIALIZED it2 ALL int_key,datetime_key NULL NULL NULL 20 Using where; Using join buffer (flat, BNL join)
DROP TABLE ot1, it1, it2;
@@ -985,11 +985,11 @@ SELECT `varchar_key` , `varchar_nokey`
FROM t1
WHERE `varchar_nokey` < 'n' XOR `pk` ) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 15 100.00
-1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 ALL NULL NULL NULL NULL 18 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 func,func 1 100.00
2 MATERIALIZED t1 ALL varchar_key NULL NULL NULL 15 100.00 Using where
Warnings:
-Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and `test`.`t2`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
+Note 1003 select `test`.`t2`.`varchar_nokey` AS `varchar_nokey` from `test`.`t2` semi join (`test`.`t1`) where `test`.`t1`.`varchar_nokey` = `test`.`t1`.`varchar_key` and (`test`.`t1`.`varchar_key` < 'n' xor `test`.`t1`.`pk`)
SELECT varchar_nokey
FROM t2
WHERE ( `varchar_nokey` , `varchar_nokey` ) IN (
@@ -1259,8 +1259,8 @@ INSERT INTO t2 VALUES (1, 0), (1, 1), (2, 0), (2, 1);
EXPLAIN
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; LooseScan
-1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t2 index k k 10 NULL 4 Using where; Using index; Start temporary
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; End temporary; Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE (i) IN (SELECT i FROM t2 where j > 0);
i
1
@@ -1770,8 +1770,8 @@ insert into t3 values('three'),( 'four');
insert into t3 values('three'),( 'four');
explain select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t3 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 8
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 10 func 1
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 2
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
select * from t3 where t3.b in (select t2.b from t1 left join t2 on t1.a=t2.a);
@@ -2509,8 +2509,8 @@ WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 1
-1 PRIMARY t1 ref a a 5 const 1 Using index
-1 PRIMARY t2 ref a a 5 func 1 Using index
+1 PRIMARY t2 ref a a 5 const 1 Using index
+1 PRIMARY t1 ref a a 5 func 1 Using index
2 MATERIALIZED t4 ALL NULL NULL NULL NULL 0
SELECT * FROM t1, t2
WHERE t1.a = t2.a AND t2.a IN (SELECT b FROM t3 STRAIGHT_JOIN t4);
@@ -2720,8 +2720,8 @@ a
19
explain select * from t3 where a in (select kp1 from t1 where kp1<20);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range kp1 kp1 5 NULL 48 Using where; Using index; LooseScan
-1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t3 ALL NULL NULL NULL NULL 100 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 1 Using index; FirstMatch(t3)
drop table t0,t1,t3;
set optimizer_switch= @tmp_923246;
#
@@ -2937,8 +2937,8 @@ WHERE alias1.pk = 58 OR alias1.col_varchar_key = 'o'
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
-1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where
-1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); FirstMatch(t2)
+1 PRIMARY alias1 index_merge PRIMARY,col_int_key,col_varchar_key PRIMARY,col_varchar_key 4,4 NULL 2 Using sort_union(PRIMARY,col_varchar_key); Using where; Start temporary; Using join buffer (flat, BNL join)
+1 PRIMARY alias2 ALL col_int_key NULL NULL NULL 12 Range checked for each record (index map: 0x2); End temporary
SELECT *
FROM t2
WHERE (field1) IN (SELECT alias1.col_varchar_nokey AS field1
@@ -3278,6 +3278,29 @@ create table t2 (a2 varchar(25)) ;
insert into t1 select 'xxx' from dual where 'xxx' in (select a2 from t2);
drop table t1,t2;
# End of 5.5 test
+#
+# MDEV-20109: Optimizer ignores distinct key created for materialized
+# semi-join subquery when searching for best execution plan
+#
+create table t1(a int);
+insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t2(a int);
+insert into t2 select A.a + B.a* 10 + C.a * 100 from t1 A, t1 B, t1 C;
+create table t3 (a int);
+create table t4 (a int);
+insert into t3 select A.a +1000*B.a from t2 A, t1 B;
+insert into t4 select floor(rand()*1000) from t2 limit 500;
+# The following must not use this query plan that does a cross join:
+# | 1 | PRIMARY | <subquery2> | ALL | distinct_key | ... | 500 | |
+# | 1 | PRIMARY | t3 | ALL | NULL | ... | 10000 | Using where; Using join buffer (flat, BNL join) |
+#
+# Instead, it should use eq_ref on the materialized table.
+explain select * from t3 where a in (select a from t4 group by a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 10000
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t4 ALL NULL NULL NULL NULL 500
+drop table t1, t2, t3, t4;
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
@@ -3485,8 +3508,8 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 Using temporary; Using filesort
+1 PRIMARY t ref idx_a idx_a 4 test.t2.b 2 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
@@ -3499,8 +3522,8 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 Using temporary; Using filesort
+1 PRIMARY t ref idx_a idx_a 4 test.t2.b 2 Using index
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result
index 203dbee6374..432f6c648fc 100644
--- a/mysql-test/main/subselect_sj_mat.result
+++ b/mysql-test/main/subselect_sj_mat.result
@@ -491,15 +491,15 @@ where (c1, c2) in (select b1, b2 from t2i where b2 > '0')) and
a1 = c1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where
-1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 4 100.00 Using where
1 PRIMARY t3 ALL NULL NULL NULL NULL 4 99.22 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 16 func,func 1 100.00
4 MATERIALIZED t3 ALL NULL NULL NULL NULL 4 99.22 Using where
4 MATERIALIZED t2i ref it2i1,it2i2,it2i3 it2i3 18 test.t3.c1,test.t3.c2 1 100.00 Using index
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 3 99.22 Using where
3 DEPENDENT UNION t2 ALL NULL NULL NULL NULL 5 99.22 Using where
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and `test`.`t3`.`c2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0'
+Note 1003 /* select#1 */ select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t3`.`c1` AS `c1`,`test`.`t3`.`c2` AS `c2` from `test`.`t1` semi join (`test`.`t2i` join `test`.`t3`) join `test`.`t3` where `test`.`t3`.`c1` = `test`.`t1`.`a1` and `test`.`t2i`.`b1` = `test`.`t3`.`c1` and `test`.`t2i`.`b2` = `test`.`t3`.`c2` and <expr_cache><`test`.`t1`.`a1`,`test`.`t1`.`a2`>(<in_optimizer>((`test`.`t1`.`a1`,`test`.`t1`.`a2`),<exists>(/* select#2 */ select `test`.`t1`.`a1`,`test`.`t1`.`a2` from `test`.`t1` where `test`.`t1`.`a1` > '0' and <cache>(`test`.`t1`.`a1`) = `test`.`t1`.`a1` and <cache>(`test`.`t1`.`a2`) = `test`.`t1`.`a2` union /* select#3 */ select `test`.`t2`.`b1`,`test`.`t2`.`b2` from `test`.`t2` where `test`.`t2`.`b1` < '9' and <cache>(`test`.`t1`.`a1`) = `test`.`t2`.`b1` and <cache>(`test`.`t1`.`a2`) = `test`.`t2`.`b2`))) and `test`.`t3`.`c2` > '0'
select * from t1, t3
where (a1, a2) in (select * from t1 where a1 > '0' UNION select * from t2 where b1 < '9') and
(c1, c2) in (select c1, c2 from t3
@@ -1132,11 +1132,11 @@ insert into t3 values (30);
explain extended
select a from t1 where a in (select c from t2 where d >= 20);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 6 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 7 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 6 100.00 Using where
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t1`.`a` = `test`.`t2`.`c` and `test`.`t2`.`d` >= 20
+Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where `test`.`t2`.`d` >= 20
select a from t1 where a in (select c from t2 where d >= 20);
a
2
@@ -1543,8 +1543,8 @@ set @@optimizer_switch=@optimizer_switch_local_default;
SET @@optimizer_switch='semijoin=on,materialization=on';
EXPLAIN SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
-1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 7 func,func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2
SELECT COUNT(*) FROM t1 WHERE (f1,f2) IN (SELECT f1,f2 FROM t2);
COUNT(*)
@@ -2473,8 +2473,8 @@ INSERT INTO t2 VALUES (11,11),(12,12),(13,13);
explain
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 hash_ALL NULL #hash#$hj 4 test.t2.i1 9 Using where; Using join buffer (flat, BNLH join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 9
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
1
@@ -2486,8 +2486,8 @@ alter table t1 add key(id);
explain
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index
+1 PRIMARY t1 index id id 4 NULL 9 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT t2.i1 FROM t2 WHERE t2.i1 = t2.i2);
1
@@ -2543,8 +2543,8 @@ INSERT INTO t2 VALUES (11,11),(12,12),(13,13);
CREATE VIEW v1 AS SELECT t2.i1 FROM t2 where t2.i1 = t2.i2;
explain SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
-1 PRIMARY t1 ref id id 4 test.t2.i1 2 Using index
+1 PRIMARY t1 index id id 4 NULL 9 Using index
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
SELECT 1 FROM t1 where t1.id IN (SELECT v1.i1 from v1);
1
diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result
index 51198ea47d6..a9b085fe31e 100644
--- a/mysql-test/main/table_value_constr.result
+++ b/mysql-test/main/table_value_constr.result
@@ -743,21 +743,21 @@ a b
explain extended select * from t1
where a in (values (1));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where 1
explain extended select * from t1
where a in (select * from (values (1)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1)) `tvc_0`) where 1
# IN-subquery with VALUES structure(s) : UNION with VALUES on the first place
select * from t1
where a in (values (1) union select 2);
@@ -978,21 +978,21 @@ a b
explain extended select * from t1
where a = any (values (1),(2));
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1 100.00
3 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 2 100.00
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
explain extended select * from t1
where a = any (select * from (values (1),(2)) as tvc_0);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2 100.00
-1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t1 ALL NULL NULL NULL NULL 6 100.00
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED <derived3> ALL NULL NULL NULL NULL 2 100.00
3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
-Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where `test`.`t1`.`a` = `tvc_0`.`1`
+Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join ((values (1),(2)) `tvc_0`) where 1
# ANY-subquery with VALUES structure(s) : UNION with VALUES on the first place
select * from t1
where a = any (values (1) union select 2);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 599642b3a26..5daf4a4b04c 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -3082,11 +3082,14 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
disable_jbuf, prefix_rec_count, &curpos, &dummy);
prefix_rec_count= COST_MULT(prefix_rec_count, curpos.records_read);
prefix_cost= COST_ADD(prefix_cost, curpos.read_time);
+ prefix_cost= COST_ADD(prefix_cost,
+ prefix_rec_count / (double) TIME_FOR_COMPARE);
+ //TODO: take into account join condition selectivity here
}
*strategy= SJ_OPT_MATERIALIZE_SCAN;
*read_time= prefix_cost;
- *record_count= prefix_rec_count;
+ *record_count= prefix_rec_count / mat_info->rows;
*handled_fanout= mat_nest->sj_inner_tables;
return TRUE;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e79e96bf210..546f1c420d5 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -16703,7 +16703,8 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
reopt_remaining_tables &= ~rs->table->map;
rec_count= COST_MULT(rec_count, pos.records_read);
cost= COST_ADD(cost, pos.read_time);
-
+ cost= COST_ADD(cost, rec_count / (double) TIME_FOR_COMPARE);
+ //TODO: take into account join condition selectivity here
if (!rs->emb_sj_nest)
*outer_rec_count= COST_MULT(*outer_rec_count, pos.records_read);
1
0
[Commits] 9bcb6cc1df7: MDEV-20188: binlog.binlog_stm_drop_tmp_tbl fails in buildbot with Unknown table on exec
by sujatha 21 Aug '19
by sujatha 21 Aug '19
21 Aug '19
revision-id: 9bcb6cc1df79535d5923435cfd4f64efe94bcf2a (mariadb-10.1.41-22-g9bcb6cc1df7)
parent(s): 91fdb931fa2f734d54acadeb3e9c860a26543f04
author: Sujatha
committer: Sujatha
timestamp: 2019-08-21 21:23:11 +0530
message:
MDEV-20188: binlog.binlog_stm_drop_tmp_tbl fails in buildbot with Unknown table on exec
Analysis:
========
As part of BUG#28642318 fix, two new test cases were added. The first test
case tests a scenario where two sessions are present, in which the first
session has a regular table named 't1' and another session has a temporary
table named 't1'. Test executes a DELETE statement on regular table. These
statements are captured from binary log and replayed back on new client
connection to prove that DELETE statement is applied successfully. Note that
the binlog contains only CREATE TEMPORARY TABLE part hence a temporary table
gets created in new connection. This replaying logic is implemented by using
'--exec $MYSQL' command. If the new connection gets disconnected within the
scope of first test case the test passes, i.e the temporary table gets dropped
as part thread cleanup. But on slow platforms the connection gets closed at
the time of execution of test case 2. When the temporary table is dropped as
part thread cleanup a "DROP TEMPORARY TABLE t1" is written into the binary
log. In test case two the same sessions continue to exist and and table names
are reused to test a new bug scenario. The additional "DROP TEMPORARY TABLE"
command drops second test specific tables which results in "Unknown table"
error.
Fix:
====
Rename the second case specific table to 't2'. Even if the close connection
from test case one happens later the drop command with has
'DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t1`' will not result in an error.
---
mysql-test/extra/binlog_tests/drop_temp_table.test | 8 ++++----
mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result | 8 ++++----
mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result | 8 ++++----
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/mysql-test/extra/binlog_tests/drop_temp_table.test b/mysql-test/extra/binlog_tests/drop_temp_table.test
index 9139ac76017..7c95195eadc 100644
--- a/mysql-test/extra/binlog_tests/drop_temp_table.test
+++ b/mysql-test/extra/binlog_tests/drop_temp_table.test
@@ -150,16 +150,16 @@ RESET MASTER;
--echo # Test case for DROP query.
--connection default
-CREATE TABLE t1 (a INT) ENGINE=INNODB;
+CREATE TABLE t2 (a INT) ENGINE=INNODB;
--connection con1
-CREATE TEMPORARY TABLE t1 (b BLOB) ENGINE=INNODB;
+CREATE TEMPORARY TABLE t2 (b BLOB) ENGINE=INNODB;
--connection default
-DROP TABLE t1;
+DROP TABLE t2;
--connection con1
-DROP TABLE t1;
+DROP TABLE t2;
--connection default
--exec $MYSQL_BINLOG --force-if-open $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/bug28642318.sql
diff --git a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
index 3d97817161e..1a18aac3997 100644
--- a/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
+++ b/mysql-test/suite/binlog/r/binlog_row_drop_tmp_tbl.result
@@ -71,10 +71,10 @@ DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t1;
RESET MASTER;
# Test case for DROP query.
-CREATE TABLE t1 (a INT) ENGINE=INNODB;
-CREATE TEMPORARY TABLE t1 (b BLOB) ENGINE=INNODB;
-DROP TABLE t1;
-DROP TABLE t1;
+CREATE TABLE t2 (a INT) ENGINE=INNODB;
+CREATE TEMPORARY TABLE t2 (b BLOB) ENGINE=INNODB;
+DROP TABLE t2;
+DROP TABLE t2;
# DROP table query fails with unknown table error without patch.
# Clean up
SET @@session.binlog_format= @save_binlog_format;
diff --git a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
index b13ffea86db..dc4b3bf10c3 100644
--- a/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
+++ b/mysql-test/suite/binlog/r/binlog_stm_drop_tmp_tbl.result
@@ -99,10 +99,10 @@ DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t1;
RESET MASTER;
# Test case for DROP query.
-CREATE TABLE t1 (a INT) ENGINE=INNODB;
-CREATE TEMPORARY TABLE t1 (b BLOB) ENGINE=INNODB;
-DROP TABLE t1;
-DROP TABLE t1;
+CREATE TABLE t2 (a INT) ENGINE=INNODB;
+CREATE TEMPORARY TABLE t2 (b BLOB) ENGINE=INNODB;
+DROP TABLE t2;
+DROP TABLE t2;
# DROP table query fails with unknown table error without patch.
# Clean up
SET @@session.binlog_format= @save_binlog_format;
1
0
[Commits] 18420037773: MDEV-19925: Column ... cannot be converted from type 'varchar(20)' to type 'varchar(20)'
by sujatha 21 Aug '19
by sujatha 21 Aug '19
21 Aug '19
revision-id: 18420037773d42cc72bebd1397c5a1eedecb80d6 (mariadb-10.2.26-47-g18420037773)
parent(s): 1a3c77e524e87e8f4151d31cd9c3112df6de218f
author: Sujatha
committer: Sujatha
timestamp: 2019-08-21 14:01:18 +0530
message:
MDEV-19925: Column ... cannot be converted from type 'varchar(20)' to type 'varchar(20)'
Cherry picking:
Bug#25135304: RBR: WRONG FIELD LENGTH IN ERROR MESSAGE
commit 47bd3f7cf3c8518f62b1580ec65af2ba7ac13b95
Description:
============
In row based replication, when replicating from a table with a field with
character set set to UTF8mb3 to the same table with the same field set to
character set UTF8mb4 I get a confusing error message:
For VARCHAR: VARCHAR(1) 'utf8mb3' to VARCHAR(1) 'utf8mb4'
"Column 0 of table 'test.t1' cannot be converted from type 'varchar(3)' to
type 'varchar(1)'"
Similar issue with CHAR type as well.
Issue with respect to BLOB types:
For BLOB: LONGBLOB to TINYBLOB - Error message displays incorrect blob type.
"Column 0 of table 'test.t1' cannot be converted from type 'tinyblob' to type
'tinyblob'"
Analysis:
=========
In Row based replication charset information is not sent as part of metadata
from master to slave.
For VARCHAR field its character length is converted into equivalent
octets/bytes and stored internally. At the time of displaying the data to user
it is converted back to original character length.
For example:
VARCHAR(2)- utf8mb3 is stored as:2*3 = VARCHAR(6)
At the time of displaying it to user
VARCHAR(6)- charset utf8mb3:6/3= VARCHAR(2).
At present the internally converted octect length is sent from master to slave
with out providing the charset information. On slave side if the type
conversion fails 'show_sql_type' function is used to get the type specific
information from metadata. Since there is no charset information is available
the filed type is displayed as VARCHAR(6).
This results in confused error message.
For CHAR fields
CHAR(1)- utf8mb3 - CHAR(3)
CHAR(1)- utf8mb4 - CHAR(4)
'show_sql_type' function which retrieves type information from metadata uses
(bytes/local charset length) to get actual character length. If slave's chaset
is 'utf8mb4' then
CHAR(3/4)-->CHAR(0)
CHAR(4/4)-->CHAR(1).
This results in confused error message.
Analysis for BLOB type issue:
BLOB's length is represented in two forms.
1. Actual length
i.e
(length < 256) type= MYSQL_TYPE_TINY_BLOB;
(length < 65536) type= MYSQL_TYPE_BLOB; ...
2. packlength - The number of bytes used to represent the length of the blob
1- tinyblob
2- blob ...
In row based replication only the packlength is written in the binary log. On
the slave side this packlength is interpreted as actual length of the blob.
Hence the length is always < 256 and the type is displayed as tiny blob.
Fix:
===
For CHAR and VARCHAR fields display their length in octets for both source and
target fields. For target field display the charset information if it is
relevant.
For blob type changed the code to use the packlength and display appropriate
blob type in error message.
---
.../suite/rpl/r/rpl_extra_col_master_innodb.result | 4 +-
.../suite/rpl/r/rpl_extra_col_master_myisam.result | 4 +-
.../suite/rpl/r/rpl_extra_col_slave_innodb.result | 12 +-
.../suite/rpl/r/rpl_extra_col_slave_myisam.result | 12 +-
.../suite/rpl/r/rpl_row_basic_2myisam.result | 4 +-
.../suite/rpl/r/rpl_row_basic_3innodb.result | 4 +-
mysql-test/suite/rpl/r/rpl_row_colSize.result | 10 +-
.../suite/rpl/r/rpl_type_conv_utf8_utf8mb4.result | 62 +++++++++
.../suite/rpl/t/rpl_type_conv_utf8_utf8mb4.test | 144 +++++++++++++++++++++
sql/field.h | 31 +++++
sql/rpl_utility.cc | 26 ++--
sql/share/errmsg-utf8.txt | 2 +-
.../rpl/r/rpl_extra_col_master_tokudb.result | 4 +-
.../rpl/r/rpl_extra_col_slave_tokudb.result | 12 +-
.../mysql-test/rpl/r/rpl_row_basic_3tokudb.result | 4 +-
15 files changed, 287 insertions(+), 48 deletions(-)
diff --git a/mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result b/mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result
index 3aa7c07a845..5865b75550f 100644
--- a/mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result
+++ b/mysql-test/suite/rpl/r/rpl_extra_col_master_innodb.result
@@ -468,7 +468,7 @@ INSERT INTO t10 () VALUES(1,@b1,DEFAULT,'Kyle',DEFAULT),
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)''
+Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5 octets) character set latin1''
*** Drop t10 ***
connection master;
@@ -510,7 +510,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT),
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)''
+Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'blob' to type 'varchar(254 octets) character set latin1''
*** Drop t11 ***
connection master;
diff --git a/mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result b/mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result
index 0918364b28e..f47d79b5b86 100644
--- a/mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result
+++ b/mysql-test/suite/rpl/r/rpl_extra_col_master_myisam.result
@@ -468,7 +468,7 @@ INSERT INTO t10 () VALUES(1,@b1,DEFAULT,'Kyle',DEFAULT),
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)''
+Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5 octets) character set latin1''
*** Drop t10 ***
connection master;
@@ -510,7 +510,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT),
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)''
+Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'blob' to type 'varchar(254 octets) character set latin1''
*** Drop t11 ***
connection master;
diff --git a/mysql-test/suite/rpl/r/rpl_extra_col_slave_innodb.result b/mysql-test/suite/rpl/r/rpl_extra_col_slave_innodb.result
index 456c1c24f8f..a9cbbd9fafe 100644
--- a/mysql-test/suite/rpl/r/rpl_extra_col_slave_innodb.result
+++ b/mysql-test/suite/rpl/r/rpl_extra_col_slave_innodb.result
@@ -64,7 +64,7 @@ a b c
connection slave;
START SLAVE;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t2' cannot be converted from type 'char(10)' to type 'char(5)''
+Last_SQL_Error = 'Column 2 of table 'test.t2' cannot be converted from type 'char(10 octets)' to type 'char(5 octets) character set latin1''
STOP SLAVE;
RESET SLAVE;
SELECT * FROM t2 ORDER BY a;
@@ -102,7 +102,7 @@ INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TEST
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)''
+Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'blob' to type 'int(11)''
*** Drop t3 ***
connection master;
DROP TABLE t3;
@@ -160,7 +160,7 @@ INSERT INTO t5 () VALUES(1,'Kyle',200.23,1,'b1b1',23.00098),
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'varchar(6)' to type 'char(5)''
+Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'varchar(6 octets)' to type 'char(5 octets) character set latin1''
*** Drop t5 ***
connection master;
DROP TABLE t5;
@@ -188,7 +188,7 @@ INSERT INTO t6 () VALUES(1,'Kyle',200.23,1),
********************************************
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'varchar(6)' to type 'char(5)''
+Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'varchar(6 octets)' to type 'char(5 octets) character set latin1''
*** Drop t6 ***
include/rpl_reset.inc
connection master;
@@ -310,7 +310,7 @@ INSERT INTO t10 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'char(5)' to type 'double''
+Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'char(5 octets)' to type 'double''
*** Drop t10 ***
connection master;
DROP TABLE t10;
@@ -338,7 +338,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'varchar(254)' to type 'int(11)''
+Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'varchar(254 octets)' to type 'int(11)''
*** Drop t11 ***
connection master;
DROP TABLE t11;
diff --git a/mysql-test/suite/rpl/r/rpl_extra_col_slave_myisam.result b/mysql-test/suite/rpl/r/rpl_extra_col_slave_myisam.result
index 7178a2a78b8..11a716f22b6 100644
--- a/mysql-test/suite/rpl/r/rpl_extra_col_slave_myisam.result
+++ b/mysql-test/suite/rpl/r/rpl_extra_col_slave_myisam.result
@@ -64,7 +64,7 @@ a b c
connection slave;
START SLAVE;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t2' cannot be converted from type 'char(10)' to type 'char(5)''
+Last_SQL_Error = 'Column 2 of table 'test.t2' cannot be converted from type 'char(10 octets)' to type 'char(5 octets) character set latin1''
STOP SLAVE;
RESET SLAVE;
SELECT * FROM t2 ORDER BY a;
@@ -102,7 +102,7 @@ INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TEST
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)''
+Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'blob' to type 'int(11)''
*** Drop t3 ***
connection master;
DROP TABLE t3;
@@ -160,7 +160,7 @@ INSERT INTO t5 () VALUES(1,'Kyle',200.23,1,'b1b1',23.00098),
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'varchar(6)' to type 'char(5)''
+Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'varchar(6 octets)' to type 'char(5 octets) character set latin1''
*** Drop t5 ***
connection master;
DROP TABLE t5;
@@ -188,7 +188,7 @@ INSERT INTO t6 () VALUES(1,'Kyle',200.23,1),
********************************************
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'varchar(6)' to type 'char(5)''
+Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'varchar(6 octets)' to type 'char(5 octets) character set latin1''
*** Drop t6 ***
include/rpl_reset.inc
connection master;
@@ -310,7 +310,7 @@ INSERT INTO t10 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'char(5)' to type 'double''
+Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'char(5 octets)' to type 'double''
*** Drop t10 ***
connection master;
DROP TABLE t10;
@@ -338,7 +338,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'varchar(254)' to type 'int(11)''
+Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'varchar(254 octets)' to type 'int(11)''
*** Drop t11 ***
connection master;
DROP TABLE t11;
diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
index 1d4b31a4a87..98e95e8cc77 100644
--- a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
+++ b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result
@@ -560,7 +560,7 @@ INSERT INTO t5 VALUES (1, "", 1);
INSERT INTO t5 VALUES (2, repeat(_utf8'a', 255), 2);
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'char(255)' to type 'char(16)''
+Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'char(765 octets)' to type 'char(48 octets) character set utf8''
include/rpl_reset.inc
[expecting slave to stop]
connection master;
@@ -568,7 +568,7 @@ INSERT INTO t6 VALUES (1, "", 1);
INSERT INTO t6 VALUES (2, repeat(_utf8'a', 255), 2);
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'char(255)' to type 'char(128)''
+Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'char(765 octets)' to type 'char(384 octets) character set utf8''
include/rpl_reset.inc
[expecting slave to replicate correctly]
connection master;
diff --git a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
index 1e3ddd4f289..3203d5394df 100644
--- a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
+++ b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result
@@ -565,7 +565,7 @@ INSERT INTO t5 VALUES (1, "", 1);
INSERT INTO t5 VALUES (2, repeat(_utf8'a', 255), 2);
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'char(255)' to type 'char(16)''
+Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'char(765 octets)' to type 'char(48 octets) character set utf8''
include/rpl_reset.inc
[expecting slave to stop]
connection master;
@@ -573,7 +573,7 @@ INSERT INTO t6 VALUES (1, "", 1);
INSERT INTO t6 VALUES (2, repeat(_utf8'a', 255), 2);
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'char(255)' to type 'char(128)''
+Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'char(765 octets)' to type 'char(384 octets) character set utf8''
include/rpl_reset.inc
[expecting slave to replicate correctly]
connection master;
diff --git a/mysql-test/suite/rpl/r/rpl_row_colSize.result b/mysql-test/suite/rpl/r/rpl_row_colSize.result
index dd324ef7807..748d83a7f8e 100644
--- a/mysql-test/suite/rpl/r/rpl_row_colSize.result
+++ b/mysql-test/suite/rpl/r/rpl_row_colSize.result
@@ -185,7 +185,7 @@ INSERT INTO t1 VALUES ('This is a test.');
connection slave;
START SLAVE;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'char(20)' to type 'char(10)''
+Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'char(20 octets)' to type 'char(10 octets) character set latin1''
SELECT COUNT(*) FROM t1;
COUNT(*)
0
@@ -264,7 +264,7 @@ INSERT INTO t1 VALUES ('This is a test.');
connection slave;
START SLAVE;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'varchar(2000)' to type 'varchar(100)''
+Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'varchar(2000 octets)' to type 'varchar(100 octets) character set latin1''
SELECT COUNT(*) FROM t1;
COUNT(*)
0
@@ -287,7 +287,7 @@ INSERT INTO t1 VALUES ('This is a test.');
connection slave;
START SLAVE;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'varchar(200)' to type 'varchar(10)''
+Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'varchar(200 octets)' to type 'varchar(10 octets) character set latin1''
SELECT COUNT(*) FROM t1;
COUNT(*)
0
@@ -310,7 +310,7 @@ INSERT INTO t1 VALUES ('This is a test.');
connection slave;
START SLAVE;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'varchar(2000)' to type 'varchar(1000)''
+Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'varchar(2000 octets)' to type 'varchar(1000 octets) character set latin1''
SELECT COUNT(*) FROM t1;
COUNT(*)
0
@@ -334,7 +334,7 @@ INSERT INTO t1 VALUES ('This is a test.');
connection slave;
START SLAVE;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'tinyblob' to type 'tinyblob''
+Last_SQL_Error = 'Column 0 of table 'test.t1' cannot be converted from type 'longblob' to type 'tinyblob''
SELECT COUNT(*) FROM t1;
COUNT(*)
0
diff --git a/mysql-test/suite/rpl/r/rpl_type_conv_utf8_utf8mb4.result b/mysql-test/suite/rpl/r/rpl_type_conv_utf8_utf8mb4.result
new file mode 100644
index 00000000000..4780d65b787
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_type_conv_utf8_utf8mb4.result
@@ -0,0 +1,62 @@
+include/master-slave.inc
+[connection master]
+####################################################################
+# Test Case1: Improved error message with charset information
+####################################################################
+connection master;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 VARCHAR(1) CHARACTER SET 'utf8mb3');
+SET SQL_LOG_BIN=1;
+connection slave;
+CREATE TABLE t1 (c1 VARCHAR(1) CHARACTER SET 'utf8mb4');
+connection master;
+INSERT INTO t1 VALUES ('a');
+connection slave;
+include/wait_for_slave_sql_error.inc [errno=1677]
+FOUND 1 /\'varchar\(3 octets\)\' to type \'varchar\(4 octets\) character set utf8mb4\'/ in mysqld.2.err
+connection master;
+DROP TABLE t1;
+connection slave;
+DROP TABLE t1;
+include/rpl_reset.inc
+####################################################################
+# Test Case2: Improved error message with charset information for CHAR
+# type
+####################################################################
+connection master;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET 'utf8mb3');
+SET SQL_LOG_BIN=1;
+connection slave;
+CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET 'utf8mb4');
+connection master;
+INSERT INTO t1 VALUES ('a');
+connection slave;
+include/wait_for_slave_sql_error.inc [errno=1677]
+FOUND 1 /\'char\(3 octets\)\' to type \'char\(4 octets\) character set utf8mb4\'/ in mysqld.2.err
+connection master;
+DROP TABLE t1;
+connection slave;
+DROP TABLE t1;
+include/rpl_reset.inc
+####################################################################
+# Test Case3: For BLOB type fileds, when type conversion failed on
+# slave, the errormessage had incorrect type names.
+####################################################################
+connection master;
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 LONGBLOB);
+SET SQL_LOG_BIN=1;
+connection slave;
+CREATE TABLE t1 (c1 TINYBLOB);
+connection master;
+INSERT INTO t1 VALUES ('a');
+connection slave;
+include/wait_for_slave_sql_error.inc [errno=1677]
+FOUND 1 /\'longblob\' to type \'tinyblob\'/ in mysqld.2.err
+connection master;
+DROP TABLE t1;
+connection slave;
+DROP TABLE t1;
+include/rpl_reset.inc
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_type_conv_utf8_utf8mb4.test b/mysql-test/suite/rpl/t/rpl_type_conv_utf8_utf8mb4.test
new file mode 100644
index 00000000000..6954614a4d6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_type_conv_utf8_utf8mb4.test
@@ -0,0 +1,144 @@
+# ==== Purpose ====
+#
+# Test verifies that when slave side type conversion fails in row based
+# replication, more informative error message is displayed. It also verifies
+# that in the case of blob fields appropriate type name is displayed in error
+# message.
+#
+# ==== Implementation ====
+#
+# Steps:
+# Test case1:
+# 1. Create a table on master with VARCHAR filed and charset
+# 'utf8mb3'.
+# 2. Create a table on slave with VARCHAR field and charset
+# 'utf8mb4'.
+# 3. Insert a tuple on master.
+# 4. Verify that slave provides more informative error message with
+# respect to difference in charsets.
+# Test case2: Repeat same steps as above for CHAR field
+# Test case3:
+# 1. Create a table on master with LONGBLOB field.
+# 2. Create a table on slave with TINYBLOB field.
+# 3. Insert a tuple on master.
+# 4. Verify that error message displayed on slave clearly states type
+# conversion failure from 'longblob' to 'tinyblob'.
+# 5. Also verify that error message doesn't show additional details
+# of charset when not required.
+#
+# ==== References ====
+#
+# MDEV-19925: Column ... cannot be converted from type 'varchar(20)' to type
+# 'varchar(20)'
+#
+
+--source include/have_binlog_format_row.inc
+# Inorder to grep a specific error pattern in error log a fresh error log
+# needs to be generated.
+--source include/force_restart.inc
+--source include/master-slave.inc
+
+--echo ####################################################################
+--echo # Test Case1: Improved error message with charset information
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 VARCHAR(1) CHARACTER SET 'utf8mb3');
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 VARCHAR(1) CHARACTER SET 'utf8mb4');
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.inc
+
+# Check error log for correct messages.
+let $log_error_= `SELECT @@GLOBAL.log_error`;
+if(!$log_error_)
+{
+ # MySQL Server on windows is started with --console and thus
+ # does not know the location of its .err log, use default location
+ let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.2.err;
+}
+
+# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'varchar(3)' to type 'varchar(1)'
+# Error msg after : Column 0 of table 'test.t1' cannot be converted from type # # 'varchar(3 octets)' to type 'varchar(4 octets) character set utf8mb4'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'varchar\(3 octets\)\' to type \'varchar\(4 octets\) character set utf8mb4\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case2: Improved error message with charset information for CHAR
+--echo # type
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET 'utf8mb3');
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET 'utf8mb4');
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.inc
+
+# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'char(0)' to type 'char(1)'
+# Error msg after : Column 0 of table 'test.t1' cannot be converted from type # 'char(3 octets)' to type 'char(4 octets) character set utf8mb4)'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'char\(3 octets\)\' to type \'char\(4 octets\) character set utf8mb4\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+
+--echo ####################################################################
+--echo # Test Case3: For BLOB type fileds, when type conversion failed on
+--echo # slave, the errormessage had incorrect type names.
+--echo ####################################################################
+--connection master
+SET SQL_LOG_BIN=0;
+CREATE TABLE t1 (c1 LONGBLOB);
+SET SQL_LOG_BIN=1;
+
+--connection slave
+CREATE TABLE t1 (c1 TINYBLOB);
+
+--connection master
+INSERT INTO t1 VALUES ('a');
+
+--connection slave
+--let $slave_sql_errno= 1677
+--source include/wait_for_slave_sql_error.inc
+
+# Error msg before: Column 0 of table 'test.t1' cannot be converted from type 'tinyblob' to type 'tinyblob'
+# Error msg after : Column 0 of table 'test.t1' cannot be converted from type 'longblob' to type 'tinyblob'
+--let SEARCH_FILE=$log_error_
+--let SEARCH_PATTERN=\'longblob\' to type \'tinyblob\'
+--source include/search_pattern_in_file.inc
+
+--connection master
+DROP TABLE t1;
+--connection slave
+DROP TABLE t1;
+--let $rpl_only_running_threads= 1
+--source include/rpl_reset.inc
+--source include/rpl_end.inc
diff --git a/sql/field.h b/sql/field.h
index 083f3d01bb8..25c9860cd65 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1106,6 +1106,7 @@ class Field: public Value_source
in str and restore it with set() if needed
*/
virtual void sql_type(String &str) const =0;
+ virtual void sql_rpl_type(String *str) const { sql_type(*str); }
virtual uint size_of() const =0; // For new field
inline bool is_null(my_ptrdiff_t row_offset= 0) const
{
@@ -3162,6 +3163,21 @@ class Field_string :public Field_longstr {
int cmp(const uchar *,const uchar *);
void sort_string(uchar *buff,uint length);
void sql_type(String &str) const;
+ void sql_rpl_type(String *res) const
+ {
+ CHARSET_INFO *cs=charset();
+ if (has_charset() &&
+ (real_type() != MYSQL_TYPE_ENUM && real_type() != MYSQL_TYPE_SET) &&
+ type() == MYSQL_TYPE_STRING)
+ {
+ size_t length= cs->cset->snprintf(cs, (char*) res->ptr(),
+ res->alloced_length(),
+ "%s(%u octets) character set %s",
+ "char", field_length,
+ charset()->csname);
+ res->length(length);
+ }
+ }
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length);
virtual const uchar *unpack(uchar* to, const uchar *from,
@@ -3264,6 +3280,21 @@ class Field_varstring :public Field_longstr {
uint get_key_image(uchar *buff,uint length, imagetype type);
void set_key_image(const uchar *buff,uint length);
void sql_type(String &str) const;
+ void sql_rpl_type(String *res) const
+ {
+ CHARSET_INFO *cs=charset();
+ if (has_charset() &&
+ (real_type() != MYSQL_TYPE_ENUM && real_type() != MYSQL_TYPE_SET) &&
+ type() == MYSQL_TYPE_VARCHAR)
+ {
+ size_t length= cs->cset->snprintf(cs, (char*) res->ptr(),
+ res->alloced_length(),
+ "%s(%u octets) character set %s",
+ "varchar", field_length,
+ charset()->csname);
+ res->length(length);
+ }
+ }
virtual uchar *pack(uchar *to, const uchar *from, uint max_length);
virtual const uchar *unpack(uchar* to, const uchar *from,
const uchar *from_end, uint param_data);
diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc
index 4277e68a8b5..ead30657bf8 100644
--- a/sql/rpl_utility.cc
+++ b/sql/rpl_utility.cc
@@ -410,7 +410,7 @@ void show_sql_type(enum_field_types type, uint16 metadata, String *str, CHARSET_
CHARSET_INFO *cs= str->charset();
uint32 length=
cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(),
- "varchar(%u)", metadata);
+ "varchar(%u octets)", metadata);
str->length(length);
}
break;
@@ -460,22 +460,22 @@ void show_sql_type(enum_field_types type, uint16 metadata, String *str, CHARSET_
it is necessary to check the pack length to figure out what kind
of blob it really is.
*/
- switch (get_blob_type_from_length(metadata))
+ switch (metadata)
{
- case MYSQL_TYPE_TINY_BLOB:
+ case 1:
str->set_ascii(STRING_WITH_LEN("tinyblob"));
break;
- case MYSQL_TYPE_MEDIUM_BLOB:
- str->set_ascii(STRING_WITH_LEN("mediumblob"));
+ case 2:
+ str->set_ascii(STRING_WITH_LEN("blob"));
break;
- case MYSQL_TYPE_LONG_BLOB:
- str->set_ascii(STRING_WITH_LEN("longblob"));
+ case 3:
+ str->set_ascii(STRING_WITH_LEN("mediumblob"));
break;
- case MYSQL_TYPE_BLOB:
- str->set_ascii(STRING_WITH_LEN("blob"));
+ case 4:
+ str->set_ascii(STRING_WITH_LEN("longblob"));
break;
default:
@@ -493,7 +493,7 @@ void show_sql_type(enum_field_types type, uint16 metadata, String *str, CHARSET_
uint bytes= (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff);
uint32 length=
cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(),
- "char(%d)", bytes / field_cs->mbmaxlen);
+ "char(%d octets)", bytes);
str->length(length);
}
break;
@@ -897,8 +897,10 @@ table_def::compatible_with(THD *thd, rpl_group_info *rgi,
String target_type(target_buf, sizeof(target_buf), &my_charset_latin1);
THD *thd= table->in_use;
- show_sql_type(type(col), field_metadata(col), &source_type, field->charset());
- field->sql_type(target_type);
+ show_sql_type(type(col), field_metadata(col), &source_type,
+ field->charset());
+ field->sql_rpl_type(&target_type);
+
rli->report(ERROR_LEVEL, ER_SLAVE_CONVERSION_FAILED, rgi->gtid_info(),
ER_THD(thd, ER_SLAVE_CONVERSION_FAILED),
col, db_name, tbl_name,
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 1c828db65a8..325858ed05c 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6461,7 +6461,7 @@ ER_MESSAGE_AND_STATEMENT
eng "%s Statement: %s"
ER_SLAVE_CONVERSION_FAILED
- eng "Column %d of table '%-.192s.%-.192s' cannot be converted from type '%-.32s' to type '%-.32s'"
+ eng "Column %d of table '%-.192s.%-.192s' cannot be converted from type '%-.50s' to type '%-.50s'"
ER_SLAVE_CANT_CREATE_CONVERSION
eng "Can't create conversion table for table '%-.192s.%-.192s'"
ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result
index cca18c7c1ab..6982078d2b8 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_master_tokudb.result
@@ -468,7 +468,7 @@ INSERT INTO t10 () VALUES(1,@b1,DEFAULT,'Kyle',DEFAULT),
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5)''
+Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'double' to type 'char(5 octets) character set latin1''
*** Drop t10 ***
connection master;
@@ -510,7 +510,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Testing is fun','Kyle',DEFAULT),
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'tinyblob' to type 'varchar(254)''
+Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'blob' to type 'varchar(254 octets) character set latin1''
*** Drop t11 ***
connection master;
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result
index 8906cf31d74..318d5496255 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_extra_col_slave_tokudb.result
@@ -64,7 +64,7 @@ a b c
connection slave;
START SLAVE;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t2' cannot be converted from type 'char(10)' to type 'char(5)''
+Last_SQL_Error = 'Column 2 of table 'test.t2' cannot be converted from type 'char(10 octets)' to type 'char(5 octets) character set latin1''
STOP SLAVE;
RESET SLAVE;
SELECT * FROM t2 ORDER BY a;
@@ -102,7 +102,7 @@ INSERT INTO t3 () VALUES(@b1,2,'Kyle, TEX'),(@b1,1,'JOE AUSTIN'),(@b1,4,'QA TEST
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'tinyblob' to type 'int(11)''
+Last_SQL_Error = 'Column 0 of table 'test.t3' cannot be converted from type 'blob' to type 'int(11)''
*** Drop t3 ***
connection master;
DROP TABLE t3;
@@ -160,7 +160,7 @@ INSERT INTO t5 () VALUES(1,'Kyle',200.23,1,'b1b1',23.00098),
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'varchar(6)' to type 'char(5)''
+Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'varchar(6 octets)' to type 'char(5 octets) character set latin1''
*** Drop t5 ***
connection master;
DROP TABLE t5;
@@ -188,7 +188,7 @@ INSERT INTO t6 () VALUES(1,'Kyle',200.23,1),
********************************************
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'varchar(6)' to type 'char(5)''
+Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'varchar(6 octets)' to type 'char(5 octets) character set latin1''
*** Drop t6 ***
include/rpl_reset.inc
connection master;
@@ -310,7 +310,7 @@ INSERT INTO t10 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'char(5)' to type 'double''
+Last_SQL_Error = 'Column 2 of table 'test.t10' cannot be converted from type 'char(5 octets)' to type 'double''
*** Drop t10 ***
connection master;
DROP TABLE t10;
@@ -338,7 +338,7 @@ INSERT INTO t11 () VALUES(1,@b1,'Kyle'),(2,@b1,'JOE'),(3,@b1,'QA');
********************************************
connection slave;
include/wait_for_slave_sql_error_and_skip.inc [errno=1677]
-Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'varchar(254)' to type 'int(11)''
+Last_SQL_Error = 'Column 2 of table 'test.t11' cannot be converted from type 'varchar(254 octets)' to type 'int(11)''
*** Drop t11 ***
connection master;
DROP TABLE t11;
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result b/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result
index 32a42143180..e638a1aab12 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_row_basic_3tokudb.result
@@ -565,7 +565,7 @@ INSERT INTO t5 VALUES (1, "", 1);
INSERT INTO t5 VALUES (2, repeat(_utf8'a', 255), 2);
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'char(255)' to type 'char(16)''
+Last_SQL_Error = 'Column 1 of table 'test.t5' cannot be converted from type 'char(765 octets)' to type 'char(48 octets) character set utf8''
include/rpl_reset.inc
[expecting slave to stop]
connection master;
@@ -573,7 +573,7 @@ INSERT INTO t6 VALUES (1, "", 1);
INSERT INTO t6 VALUES (2, repeat(_utf8'a', 255), 2);
connection slave;
include/wait_for_slave_sql_error.inc [errno=1677]
-Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'char(255)' to type 'char(128)''
+Last_SQL_Error = 'Column 1 of table 'test.t6' cannot be converted from type 'char(765 octets)' to type 'char(384 octets) character set utf8''
include/rpl_reset.inc
[expecting slave to replicate correctly]
connection master;
1
0