Merged the code of mwl 106 into the latest 5.3 with mwl 90 pushed.

Resolved all conflicts and failures.
This commit is contained in:
Igor Babaev 2011-06-04 19:56:06 -07:00
commit f03a3ee54f
99 changed files with 4331 additions and 1089 deletions

View file

@ -57,9 +57,8 @@ a b a b
3 c 3 c
explain select * from t1 as x1, (select * from t1) as x2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY x1 ALL NULL NULL NULL NULL 4
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 4
1 SIMPLE x1 ALL NULL NULL NULL NULL 4
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
drop table if exists t2,t3;
select * from (select 1) as a;
1
@ -91,7 +90,7 @@ a b
2 b
explain select * from (select * from t1 union select * from t1) a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
2 DERIVED t1 ALL NULL NULL NULL NULL 4
3 UNION t1 ALL NULL NULL NULL NULL 4
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
@ -113,9 +112,8 @@ a b
3 c
explain select * from (select t1.*, t2.a as t2a from t1,t2 where t1.a=t2.a) t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t2 system NULL NULL NULL NULL 1
2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using where
1 SIMPLE t2 system NULL NULL NULL NULL 1
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
drop table t1, t2;
create table t1(a int not null, t char(8), index(a));
SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
@ -142,8 +140,7 @@ a t
20 20
explain select count(*) from t1 as tt1, (select * from t1) as tt2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 DERIVED t1 ALL NULL NULL NULL NULL 10000
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
drop table t1;
SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
(SELECT * FROM (SELECT 1 as a) as a )
@ -172,30 +169,30 @@ insert into t1 values (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd'
insert into t2 values (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), (3, 101), (3, 102), (3, 105);
SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
pla_id mat_id
100 1
101 1
102 1
103 2
101 1
100 1
104 2
103 2
105 3
SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
pla_id test
100 1
101 1
102 1
103 2
101 1
100 1
104 2
103 2
105 3
explain SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY <derived2> ref key0 key0 7 test.m2.matintnum 2
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
2 DERIVED m1 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1
explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY <derived2> ref key0 key0 7 test.m2.matintnum 2
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
2 DERIVED m1 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1
drop table t1,t2;
@ -230,9 +227,8 @@ count(*)
2
explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 THEMAX.E2 1 Using where
2 DERIVED A ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE A ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.A.E2 1 Using where
3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where
drop table t1;
create table t1 (a int);
@ -245,8 +241,8 @@ a a
2 2
explain select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
4 DERIVED t1 ALL NULL NULL NULL NULL 2
5 UNION t1 ALL NULL NULL NULL NULL 2
NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL
@ -311,7 +307,7 @@ a 7.0000
b 3.5000
explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 Using temporary; Using filesort
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 289 Using temporary; Using filesort
2 DERIVED x ALL NULL NULL NULL NULL 17 Using temporary; Using filesort
2 DERIVED y ALL NULL NULL NULL NULL 17 Using where; Using join buffer (flat, BNL join)
drop table t1;
@ -322,8 +318,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index
explain select a from (select a from t2 where a>1) tt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index
1 SIMPLE t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index
drop table t2;
CREATE TABLE `t1` ( `itemid` int(11) NOT NULL default '0', `grpid` varchar(15) NOT NULL default '', `vendor` int(11) NOT NULL default '0', `date_` date NOT NULL default '0000-00-00', `price` decimal(12,2) NOT NULL default '0.00', PRIMARY KEY (`itemid`,`grpid`,`vendor`,`date_`), KEY `itemid` (`itemid`,`vendor`), KEY `itemid_2` (`itemid`,`date_`));
insert into t1 values (128, 'rozn', 2, curdate(), 10),

View file

@ -0,0 +1,570 @@
drop table if exists t1,t2;
drop view if exists v1,v2,v3,v4;
create table t1(f1 int, f11 int);
create table t2(f2 int, f22 int);
insert into t1 values(1,1),(2,2),(3,3),(5,5),(9,9),(7,7);
insert into t1 values(17,17),(13,13),(11,11),(15,15),(19,19);
insert into t2 values(1,1),(3,3),(2,2),(4,4),(8,8),(6,6);
insert into t2 values(12,12),(14,14),(10,10),(18,18),(16,16);
Tests:
for merged derived tables
explain for simple derived
explain select * from (select * from t1) tt;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11
select * from (select * from t1) tt;
f1 f11
1 1
2 2
3 3
5 5
9 9
7 7
17 17
13 13
11 11
15 15
19 19
explain for multitable derived
explain extended select * from (select * from t1 join t2 on f1=f2) tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`f2` = `test`.`t1`.`f1`)
select * from (select * from t1 join t2 on f1=f2) tt;
f1 f11 f2 f22
1 1 1 1
3 3 3 3
2 2 2 2
explain for derived with where
explain extended
select * from (select * from t1 where f1 in (2,3)) tt where f11=2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where ((`test`.`t1`.`f11` = 2) and (`test`.`t1`.`f1` in (2,3)))
select * from (select * from t1 where f1 in (2,3)) tt where f11=2;
f1 f11
2 2
join of derived
explain extended
select * from (select * from t1 where f1 in (2,3)) tt join
(select * from t1 where f1 in (1,2)) aa on tt.f1=aa.f1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` join `test`.`t1` where ((`test`.`t1`.`f1` = `test`.`t1`.`f1`) and (`test`.`t1`.`f1` in (1,2)) and (`test`.`t1`.`f1` in (2,3)))
select * from (select * from t1 where f1 in (2,3)) tt join
(select * from t1 where f1 in (1,2)) aa on tt.f1=aa.f1;
f1 f11 f1 f11
2 2 2 2
flush status;
explain extended
select * from (select * from t1 where f1 in (2,3)) tt where f11=2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where ((`test`.`t1`.`f11` = 2) and (`test`.`t1`.`f1` in (2,3)))
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 0
flush status;
select * from (select * from t1 where f1 in (2,3)) tt where f11=2;
f1 f11
2 2
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 12
for merged views
create view v1 as select * from t1;
create view v2 as select * from t1 join t2 on f1=f2;
create view v3 as select * from t1 where f1 in (2,3);
create view v4 as select * from t2 where f2 in (2,3);
explain for simple views
explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1`
select * from v1;
f1 f11
1 1
2 2
3 3
5 5
9 9
7 7
17 17
13 13
11 11
15 15
19 19
explain for multitable views
explain extended select * from v2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t1` join `test`.`t2` where (`test`.`t2`.`f2` = `test`.`t1`.`f1`)
select * from v2;
f1 f11 f2 f22
1 1 1 1
3 3 3 3
2 2 2 2
explain for views with where
explain extended select * from v3 where f11 in (1,3);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where ((`test`.`t1`.`f11` in (1,3)) and (`test`.`t1`.`f1` in (2,3)))
select * from v3 where f11 in (1,3);
f1 f11
3 3
explain for joined views
explain extended
select * from v3 join v4 on f1=f2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`f2` = `test`.`t1`.`f1`) and (`test`.`t1`.`f1` in (2,3)) and (`test`.`t1`.`f1` in (2,3)))
select * from v3 join v4 on f1=f2;
f1 f11 f2 f22
3 3 3 3
2 2 2 2
flush status;
explain extended select * from v4 where f2 in (1,3);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 100.00 Using where
Warnings:
Note 1003 select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t2` where ((`test`.`t2`.`f2` in (1,3)) and (`test`.`t2`.`f2` in (2,3)))
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 0
flush status;
select * from v4 where f2 in (1,3);
f2 f22
3 3
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 12
for materialized derived tables
explain for simple derived
explain extended select * from (select * from t1 group by f1) tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
Note 1003 select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` group by `test`.`t1`.`f1`) `tt`
select * from (select * from t1 having f1=f1) tt;
f1 f11
1 1
2 2
3 3
5 5
9 9
7 7
17 17
13 13
11 11
15 15
19 19
explain showing created indexes
explain extended
select * from t1 join (select * from t2 group by f2) tt on f1=f2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 11 100.00 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t1.f1 2 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`tt`.`f2` AS `f2`,`tt`.`f22` AS `f22` from `test`.`t1` join (select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t2` group by `test`.`t2`.`f2`) `tt` where (`tt`.`f2` = `test`.`t1`.`f1`)
select * from t1 join (select * from t2 group by f2) tt on f1=f2;
f1 f11 f2 f22
1 1 1 1
2 2 2 2
3 3 3 3
explain showing late materialization
flush status;
explain select * from t1 join (select * from t2 group by f2) tt on f1=f2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 11 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t1.f1 2
2 DERIVED t2 ALL NULL NULL NULL NULL 11 Using temporary; Using filesort
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 0
flush status;
select * from t1 join (select * from t2 group by f2) tt on f1=f2;
f1 f11 f2 f22
1 1 1 1
2 2 2 2
3 3 3 3
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 11
Handler_read_next 3
Handler_read_prev 0
Handler_read_rnd 11
Handler_read_rnd_next 36
for materialized views
drop view v1,v2,v3;
create view v1 as select * from t1 group by f1;
create view v2 as select * from t2 group by f2;
create view v3 as select t1.f1,t1.f11 from t1 join t1 as t11 where t1.f1=t11.f1
having t1.f1<100;
explain for simple derived
explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
Note 1003 select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1`
select * from v1;
f1 f11
1 1
2 2
3 3
5 5
7 7
9 9
11 11
13 13
15 15
17 17
19 19
explain showing created indexes
explain extended select * from t1 join v2 on f1=f2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 11 100.00 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t1.f1 2 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`v2`.`f2` AS `f2`,`v2`.`f22` AS `f22` from `test`.`t1` join `test`.`v2` where (`v2`.`f2` = `test`.`t1`.`f1`)
select * from t1 join v2 on f1=f2;
f1 f11 f2 f22
1 1 1 1
2 2 2 2
3 3 3 3
explain extended
select * from t1,v3 as v31,v3 where t1.f1=v31.f1 and t1.f1=v3.f1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 11 100.00 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t1.f1 10 100.00
1 PRIMARY <derived3> ref key0 key0 5 test.t1.f1 10 100.00
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00
3 DERIVED t11 ALL NULL NULL NULL NULL 11 100.00 Using where; Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t11 ALL NULL NULL NULL NULL 11 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`v31`.`f1` AS `f1`,`v31`.`f11` AS `f11`,`v3`.`f1` AS `f1`,`v3`.`f11` AS `f11` from `test`.`t1` join `test`.`v3` `v31` join `test`.`v3` where ((`v31`.`f1` = `test`.`t1`.`f1`) and (`v3`.`f1` = `test`.`t1`.`f1`))
flush status;
select * from t1,v3 as v31,v3 where t1.f1=v31.f1 and t1.f1=v3.f1;
f1 f11 f1 f11 f1 f11
1 1 1 1 1 1
2 2 2 2 2 2
3 3 3 3 3 3
5 5 5 5 5 5
9 9 9 9 9 9
7 7 7 7 7 7
17 17 17 17 17 17
13 13 13 13 13 13
11 11 11 11 11 11
15 15 15 15 15 15
19 19 19 19 19 19
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 22
Handler_read_next 22
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 60
explain showing late materialization
flush status;
explain select * from t1 join v2 on f1=f2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 11 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t1.f1 2
2 DERIVED t2 ALL NULL NULL NULL NULL 11 Using temporary; Using filesort
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 0
Handler_read_next 0
Handler_read_prev 0
Handler_read_rnd 0
Handler_read_rnd_next 0
flush status;
select * from t1 join v2 on f1=f2;
f1 f11 f2 f22
1 1 1 1
2 2 2 2
3 3 3 3
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 11
Handler_read_next 3
Handler_read_prev 0
Handler_read_rnd 11
Handler_read_rnd_next 36
explain extended select * from v1 join v4 on f1=f2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 11 100.00 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t2.f2 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
Note 1003 select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11`,`test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`v1` join `test`.`t2` where ((`v1`.`f1` = `test`.`t2`.`f2`) and (`test`.`t2`.`f2` in (2,3)))
select * from v1 join v4 on f1=f2;
f1 f11 f2 f22
3 3 3 3
2 2 2 2
merged derived in merged derived
explain extended select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2) zz;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where ((`test`.`t1`.`f1` > 2) and (`test`.`t1`.`f1` < 7))
select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2) zz;
f1 f11
3 3
5 5
materialized derived in merged derived
explain extended select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2) zz;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE <derived3> ALL NULL NULL NULL NULL 11 100.00 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
Note 1003 select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where (`test`.`t1`.`f1` < 7) group by `test`.`t1`.`f1`) `tt` where (`tt`.`f1` > 2)
select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2) zz;
f1 f11
3 3
5 5
merged derived in materialized derived
explain extended select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2 group by f1) zz;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
Note 1003 select `zz`.`f1` AS `f1`,`zz`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where ((`test`.`t1`.`f1` > 2) and (`test`.`t1`.`f1` < 7)) group by `test`.`t1`.`f1`) `zz`
select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2 group by f1) zz;
f1 f11
3 3
5 5
materialized derived in materialized derived
explain extended select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) zz;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED <derived3> ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
Note 1003 select `zz`.`f1` AS `f1`,`zz`.`f11` AS `f11` from (select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where (`test`.`t1`.`f1` < 7) group by `test`.`t1`.`f1`) `tt` where (`tt`.`f1` > 2) group by `tt`.`f1`) `zz`
select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) zz;
f1 f11
3 3
5 5
mat in merged derived join mat in merged derived
explain extended select * from
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) x
join
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) z
on x.f1 = z.f1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE <derived3> ALL key0 NULL NULL NULL 11 100.00 Using where
1 SIMPLE <derived5> ref key0 key0 5 tt.f1 2 100.00
5 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
Note 1003 select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11`,`tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where (`test`.`t1`.`f1` < 7) group by `test`.`t1`.`f1`) `tt` join (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where (`test`.`t1`.`f1` < 7) group by `test`.`t1`.`f1`) `tt` where ((`tt`.`f1` = `tt`.`f1`) and (`tt`.`f1` > 2) and (`tt`.`f1` > 2))
flush status;
select * from
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) x
join
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) z
on x.f1 = z.f1;
f1 f11 f1 f11
3 3 3 3
5 5 5 5
show status like 'Handler_read%';
Variable_name Value
Handler_read_first 0
Handler_read_key 2
Handler_read_next 2
Handler_read_prev 0
Handler_read_rnd 8
Handler_read_rnd_next 39
flush status;
merged in merged derived join merged in merged derived
explain extended select * from
(select * from
(select * from t1 where f1 < 7 ) tt where f1 > 2 ) x
join
(select * from
(select * from t1 where f1 < 7 ) tt where f1 > 2 ) z
on x.f1 = z.f1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where
1 SIMPLE t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11`,`test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` join `test`.`t1` where ((`test`.`t1`.`f1` = `test`.`t1`.`f1`) and (`test`.`t1`.`f1` > 2) and (`test`.`t1`.`f1` < 7) and (`test`.`t1`.`f1` > 2) and (`test`.`t1`.`f1` < 7))
select * from
(select * from
(select * from t1 where f1 < 7 ) tt where f1 > 2 ) x
join
(select * from
(select * from t1 where f1 < 7 ) tt where f1 > 2 ) z
on x.f1 = z.f1;
f1 f11 f1 f11
3 3 3 3
5 5 5 5
materialized in materialized derived join
materialized in materialized derived
explain extended select * from
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) x
join
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) z
on x.f1 = z.f1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL key0 NULL NULL NULL 11 100.00 Using where
1 PRIMARY <derived4> ref key0 key0 5 x.f1 2 100.00
4 DERIVED <derived5> ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
5 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
2 DERIVED <derived3> ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
Note 1003 select `x`.`f1` AS `f1`,`x`.`f11` AS `f11`,`z`.`f1` AS `f1`,`z`.`f11` AS `f11` from (select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where (`test`.`t1`.`f1` < 7) group by `test`.`t1`.`f1`) `tt` where (`tt`.`f1` > 2) group by `tt`.`f1`) `x` join (select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f11` AS `f11` from `test`.`t1` where (`test`.`t1`.`f1` < 7) group by `test`.`t1`.`f1`) `tt` where (`tt`.`f1` > 2) group by `tt`.`f1`) `z` where (`z`.`f1` = `x`.`f1`)
select * from
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) x
join
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) z
on x.f1 = z.f1;
f1 f11 f1 f11
3 3 3 3
5 5 5 5
merged view in materialized derived
explain extended
select * from (select * from v4 group by 1) tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 11 100.00 Using where; Using temporary; Using filesort
Warnings:
Note 1003 select `tt`.`f2` AS `f2`,`tt`.`f22` AS `f22` from (select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t2` where (`test`.`t2`.`f2` in (2,3)) group by 1) `tt`
select * from (select * from v4 group by 1) tt;
f2 f22
2 2
3 3
materialized view in merged derived
explain extended
select * from ( select * from v1 where f1 < 7) tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE <derived3> ALL NULL NULL NULL NULL 11 100.00 Using where
3 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
Note 1003 select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1` where (`v1`.`f1` < 7)
select * from ( select * from v1 where f1 < 7) tt;
f1 f11
1 1
2 2
3 3
5 5
merged view in a merged view in a merged derived
create view v6 as select * from v4 where f2 < 7;
explain extended select * from (select * from v6) tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 100.00 Using where
Warnings:
Note 1003 select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22` from `test`.`t2` where ((`test`.`t2`.`f2` < 7) and (`test`.`t2`.`f2` in (2,3)))
select * from (select * from v6) tt;
f2 f22
3 3
2 2
materialized view in a merged view in a materialized derived
create view v7 as select * from v1;
explain extended select * from (select * from v7 group by 1) tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11 100.00
2 DERIVED <derived4> ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
4 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
Note 1003 select `tt`.`f1` AS `f1`,`tt`.`f11` AS `f11` from (select `v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`v1` group by 1) `tt`
select * from (select * from v7 group by 1) tt;
f1 f11
1 1
2 2
3 3
5 5
7 7
9 9
11 11
13 13
15 15
17 17
19 19
join of above two
explain extended select * from v6 join v7 on f2=f1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 11 100.00 Using where
1 SIMPLE <derived5> ref key0 key0 5 test.t2.f2 2 100.00
5 DERIVED t1 ALL NULL NULL NULL NULL 11 100.00 Using temporary; Using filesort
Warnings:
Note 1003 select `test`.`t2`.`f2` AS `f2`,`test`.`t2`.`f22` AS `f22`,`v1`.`f1` AS `f1`,`v1`.`f11` AS `f11` from `test`.`t2` join `test`.`v1` where ((`v1`.`f1` = `test`.`t2`.`f2`) and (`test`.`t2`.`f2` < 7) and (`test`.`t2`.`f2` in (2,3)))
select * from v6 join v7 on f2=f1;
f2 f22 f1 f11
3 3 3 3
2 2 2 2
test two keys
explain select * from t1 join (select * from t2 group by f2) tt on t1.f1=tt.f2 join t1 xx on tt.f22=xx.f1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 11 Using where
1 PRIMARY <derived2> ref key0 key0 5 test.t1.f1 2
1 PRIMARY xx ALL NULL NULL NULL NULL 11 Using where; Using join buffer (flat, BNL join)
2 DERIVED t2 ALL NULL NULL NULL NULL 11 Using temporary; Using filesort
select * from t1 join (select * from t2 group by f2) tt on t1.f1=tt.f2 join t1 xx on tt.f22=xx.f1;
f1 f11 f2 f22 f1 f11
1 1 1 1 1 1
2 2 2 2 2 2
3 3 3 3 3 3
TODO: Add test with 64 tables mergeable view to test fall back to
materialization on tables > MAX_TABLES merge
drop table t1,t2;
drop view v1,v2,v3,v4,v6,v7;

View file

@ -102,7 +102,7 @@ INSERT INTO t2 VALUES (),(),();
EXPLAIN SELECT 1 FROM
(SELECT 1 FROM t2,t1 WHERE b < c GROUP BY 1 LIMIT 1) AS d2;
id select_type table type possible_keys key key_len ref rows Extra
X X X X X X X X X const row not found
X X X X X X X X X
X X X X X X X X X
X X X X X X X X X Range checked for each record (index map: 0xFFFFFFFFFF)
DROP TABLE t2;
@ -114,7 +114,7 @@ INSERT INTO t2 VALUES (1),(2);
EXPLAIN EXTENDED SELECT 1
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
@ -122,7 +122,7 @@ Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT
EXPLAIN EXTENDED SELECT 1
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
@ -132,7 +132,7 @@ prepare s1 from
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1';
execute s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
@ -142,14 +142,14 @@ prepare s1 from
FROM (SELECT COUNT(DISTINCT t1.a) FROM t1,t2 GROUP BY t1.a) AS s1';
execute s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
Note 1003 select 1 AS `1` from (select count(distinct `test`.`t1`.`a`) AS `COUNT(DISTINCT t1.a)` from `test`.`t1` join `test`.`t2` group by `test`.`t1`.`a`) `s1`
execute s1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
@ -312,8 +312,7 @@ INSERT INTO t2 VALUES (8);
EXPLAIN EXTENDED
SELECT * FROM ( SELECT t1.a FROM t1,t2 WHERE t2.a = t1.a ) AS t;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 0.00 const row not found
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1003 select NULL AS `a` from (select NULL AS `a` from `test`.`t1` join `test`.`t2` where 0) `t`
Note 1003 select NULL AS `a` from `test`.`t1` join `test`.`t2` where 0
DROP TABLE t1,t2;

View file

@ -983,10 +983,10 @@ INSERT INTO t1 VALUES (),();
EXPLAIN EXTENDED SELECT 1 FROM
(SELECT DISTINCT GROUP_CONCAT(td.f1) FROM t1,t1 AS td GROUP BY td.f1) AS d,t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort; Distinct
2 DERIVED td ALL NULL NULL NULL NULL 2 100.00 Distinct; Using join buffer (flat, BNL join)
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00 Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED td ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
Note 1003 select 1 AS `1` from (select distinct group_concat(`test`.`td`.`f1` separator ',') AS `GROUP_CONCAT(td.f1)` from `test`.`t1` join `test`.`t1` `td` group by `test`.`td`.`f1`) `d` join `test`.`t1`
SELECT 1 FROM
@ -1005,7 +1005,7 @@ EXPLAIN EXTENDED SELECT 1 FROM
(SELECT GROUP_CONCAT(t1.a ORDER BY t1.a ASC) FROM
t1 t2, t1 GROUP BY t1.a) AS d;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
2 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
Warnings:
@ -1035,7 +1035,7 @@ DROP TABLE t1;
CREATE TABLE t1(f1 int);
INSERT INTO t1 values (0),(0);
SELECT POLYGON((SELECT 1 FROM (SELECT 1 IN (GROUP_CONCAT(t1.f1)) FROM t1, t1 t GROUP BY t.f1 ) d));
ERROR 22007: Illegal non geometric '(select 1 from (select (1 = group_concat(`test`.`t1`.`f1` separator ',')) AS `1 IN (GROUP_CONCAT(t1.f1))` from `test`.`t1` join `test`.`t1` `t` group by `t`.`f1`) `d`)' value found during parsing
ERROR 22007: Illegal non geometric '(select 1 from (select (1 = group_concat(`test`.`t1`.`f1` separator ',')) AS `1 IN (GROUP_CONCAT(t1.f1))` from `test`.`t1` join `test`.`t1` `t` group by `test`.`t`.`f1`) `d`)' value found during parsing
DROP TABLE t1;
#
# Bug#58396 group_concat and explain extended are still crashy

View file

@ -1874,9 +1874,8 @@ HAVING ('m') IN (
SELECT v
FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
1 PRIMARY empty1 system NULL NULL NULL NULL 0 const row not found
3 SUBQUERY t2 ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
#
# 5) Test that subquery materialization is setup for query with

View file

@ -2549,14 +2549,12 @@ create table t1(f1 tinyint default null)engine=myisam;
insert into t1 values (-1),(null);
explain select 1 as a from t1,(select decode(f1,f1) as b from t1) a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
explain select 1 as a from t1,(select encode(f1,f1) as b from t1) a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
drop table t1;
#
# Bug#49141: Encode function is significantly slower in 5.1 compared to 5.0

View file

@ -691,8 +691,7 @@ SELECT COUNT(*) FROM
(SELECT * FROM t1 FORCE INDEX(primary,idx)
WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 DERIVED t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL 11419 Using sort_union(idx,PRIMARY); Using where
1 SIMPLE t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL 11419 Using sort_union(idx,PRIMARY); Using where
SELECT COUNT(*) FROM
(SELECT * FROM t1 FORCE INDEX(primary,idx)
WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;
@ -703,8 +702,7 @@ SELECT COUNT(*) FROM
(SELECT * FROM t1 IGNORE INDEX(idx)
WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL # Select tables optimized away
2 DERIVED t1 ALL PRIMARY NULL NULL NULL # Using where
1 SIMPLE t1 ALL PRIMARY NULL NULL NULL # Using where
SELECT COUNT(*) FROM
(SELECT * FROM t1 IGNORE INDEX(idx)
WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;

View file

@ -287,8 +287,7 @@ id select_type table type possible_keys key key_len ref rows Extra
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t1 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
1 SIMPLE t1 index_merge i1,i2,i8 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where
create table t3 like t0;
insert into t3 select * from t0;
alter table t3 add key9 int not null, add index i9(key9);

View file

@ -1288,8 +1288,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE tables ALL NULL NULL NULL NULL NULL Open_frm_only; Scanned all databases; Using filesort
explain select * from (select table_name from information_schema.tables) as a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
2 DERIVED tables ALL NULL NULL NULL NULL NULL Skip_open_table; Scanned all databases
1 SIMPLE tables ALL NULL NULL NULL NULL NULL Skip_open_table; Scanned all databases
drop view v1;
create table t1 (f1 int(11));
create table t2 (f1 int(11), f2 int(11));

View file

@ -2,7 +2,9 @@ SET @odl_sync_frm = @@global.sync_frm;
SET @@global.sync_frm = OFF;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1( a INT, b INT );
CREATE TABLE t2( a INT, b INT );
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4);
INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (4, 4);
# 1. test regular tables
# 1.1. test altering of columns that multiupdate doesn't use
# 1.1.1. normal mode
@ -18,5 +20,5 @@ ALTER TABLE t1 ADD COLUMN a INT;
# 2.2. test altering of columns that multiupdate uses
# 2.2.1. normal mode
# 2.2.2. PS mode
DROP TABLE t1;
DROP TABLE t1,t2;
SET @@global.sync_frm = @odl_sync_frm;

View file

@ -205,7 +205,7 @@ CREATE TABLE t1 (f1 INT);
CREATE VIEW v1 AS SELECT f1 FROM t1;
SELECT f1 FROM v1 va;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def test v1 va f1 f1 3 11 0 Y 32768 0 63
def test va va f1 f1 3 11 0 Y 32768 0 63
f1
DROP VIEW v1;
DROP TABLE t1;

View file

@ -668,6 +668,11 @@ INSERT INTO t1 VALUES('2001-01-01');
UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
Warnings:
Warning 1292 Truncated incorrect date value: '1'
CREATE view v1 as SELECT f1() FROM t1;
UPDATE (SELECT 1 FROM t1 WHERE f1 = (select * from v1)) x, t1 SET f1 = 1;
Warnings:
Warning 1292 Truncated incorrect date value: '1'
DROP VIEW v1;
DROP FUNCTION f1;
DROP TABLE t1;
end of tests

View file

@ -1673,7 +1673,7 @@ SELECT * FROM t1 r JOIN t1 s ON r.a = s.a
WHERE s.a IN (2,9) OR s.a < 100 AND s.a != 0
ORDER BY 1 LIMIT 10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE r index PRIMARY PRIMARY 4 NULL 10 120.00 Using where; Using index
1 SIMPLE r index PRIMARY PRIMARY 4 NULL 10 100.00 Using where; Using index
1 SIMPLE s eq_ref PRIMARY PRIMARY 4 test.r.a 1 100.00 Using index
Warnings:
Note 1003 select `test`.`r`.`a` AS `a`,`test`.`s`.`a` AS `a` from `test`.`t1` `r` join `test`.`t1` `s` where ((`test`.`s`.`a` = `test`.`r`.`a`) and ((`test`.`r`.`a` in (2,9)) or ((`test`.`r`.`a` < 100) and (`test`.`r`.`a` <> 0)))) order by 1 limit 10

View file

@ -156,7 +156,6 @@ prepare stmt1 from @stmt ;
execute stmt1 ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@ -164,7 +163,6 @@ id select_type table type possible_keys key key_len ref rows Extra
execute stmt1 ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
@ -172,7 +170,6 @@ id select_type table type possible_keys key key_len ref rows Extra
explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables

View file

@ -1508,12 +1508,12 @@ create view v_27690_1 as select A.a, A.b from t_27690_1 A, t_27690_1 B;
execute stmt;
a b a b
1 1 1 1
2 2 1 1
1 1 1 1
2 2 1 1
1 1 2 2
2 2 1 1
2 2 2 2
1 1 1 1
1 1 2 2
2 2 1 1
2 2 2 2
call p_verify_reprepare_count(1);
SUCCESS
@ -1521,12 +1521,12 @@ SUCCESS
execute stmt;
a b a b
1 1 1 1
2 2 1 1
1 1 1 1
2 2 1 1
1 1 2 2
2 2 1 1
2 2 2 2
1 1 1 1
1 1 2 2
2 2 1 1
2 2 2 2
call p_verify_reprepare_count(0);
SUCCESS

View file

@ -47,13 +47,13 @@ SELECT (SELECT a) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
EXPLAIN EXTENDED SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><1>((select 1)) = 1)
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><`b`.`a`>((select `b`.`a`)) = 1)
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@ -202,11 +202,10 @@ select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> system NULL NULL NULL NULL 1 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,2 AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` > 1)) `tt`
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` > 1)
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
2
@ -366,9 +365,9 @@ INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
@ -1343,7 +1342,7 @@ a
explain extended select * from t2 where t2.a in (select a from t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index a a 5 NULL 4 100.00 Using where; Using index
1 PRIMARY t1 ref a a 5 test.t2.a 101 100.00 Using index; FirstMatch(t2)
1 PRIMARY t1 ref a a 5 test.t2.a 100 100.00 Using index; FirstMatch(t2)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where (`test`.`t1`.`a` = `test`.`t2`.`a`)
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
@ -1353,7 +1352,7 @@ a
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index a a 5 NULL 4 100.00 Using where; Using index
1 PRIMARY t1 ref a a 5 test.t2.a 101 100.00 Using where; Using index; FirstMatch(t2)
1 PRIMARY t1 ref a a 5 test.t2.a 100 100.00 Using where; Using index; FirstMatch(t2)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` <> 30))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
@ -1364,7 +1363,7 @@ explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index a a 5 NULL 4 100.00 Using where; Using index
1 PRIMARY t3 index a a 5 NULL 3 100.00 Using where; Using index
1 PRIMARY t1 ref a a 10 test.t2.a,test.t3.a 116 100.00 Using index; FirstMatch(t2)
1 PRIMARY t1 ref a a 10 test.t2.a,test.t3.a 11 100.00 Using index; FirstMatch(t2)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1` join `test`.`t3`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` = `test`.`t3`.`a`))
insert into t1 values (3,31);
@ -1380,7 +1379,7 @@ a
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index a a 5 NULL 4 100.00 Using where; Using index
1 PRIMARY t1 ref a a 5 test.t2.a 101 100.00 Using where; Using index; FirstMatch(t2)
1 PRIMARY t1 ref a a 5 test.t2.a 100 100.00 Using where; Using index; FirstMatch(t2)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` <> 30))
drop table t0, t1, t2, t3;

View file

@ -887,7 +887,7 @@ Level Code Message
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
Note 1276 Field or reference 'test.t1.c' of SELECT #3 was resolved in SELECT #2
Error 1054 Unknown column 'c' in 'field list'
Note 1003 select `c` AS `c` from (select <expr_cache><count(`test`.`t1`.`a`),`test`.`t1`.`c`>((select count(`test`.`t1`.`a`) from (select count(`test`.`t1`.`b`) AS `COUNT(b)` from `test`.`t1`) `x` group by `t1`.`c`)) AS `(SELECT COUNT(a) FROM
Note 1003 select `c` AS `c` from (select (select count(`test`.`t1`.`a`) from (select count(`test`.`t1`.`b`) AS `COUNT(b)` from `test`.`t1`) `x` group by `test`.`t1`.`c`) AS `(SELECT COUNT(a) FROM
(SELECT COUNT(b) FROM t1) AS x GROUP BY c
)` from `test`.`t1` group by `test`.`t1`.`b`) `y`
DROP TABLE t1;
@ -1114,9 +1114,8 @@ a
set @@optimizer_switch=@save_optimizer_switch;
explain select * from (select a from t0) X where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11
1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using where; FirstMatch(<derived2>)
2 DERIVED t0 ALL NULL NULL NULL NULL 11
1 PRIMARY t0 ALL NULL NULL NULL NULL 11
1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using where; FirstMatch(t0)
drop table t0, t1;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

View file

@ -894,7 +894,7 @@ Level Code Message
Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #2
Note 1276 Field or reference 'test.t1.c' of SELECT #3 was resolved in SELECT #2
Error 1054 Unknown column 'c' in 'field list'
Note 1003 select `c` AS `c` from (select <expr_cache><count(`test`.`t1`.`a`),`test`.`t1`.`c`>((select count(`test`.`t1`.`a`) from (select count(`test`.`t1`.`b`) AS `COUNT(b)` from `test`.`t1`) `x` group by `t1`.`c`)) AS `(SELECT COUNT(a) FROM
Note 1003 select `c` AS `c` from (select (select count(`test`.`t1`.`a`) from (select count(`test`.`t1`.`b`) AS `COUNT(b)` from `test`.`t1`) `x` group by `test`.`t1`.`c`) AS `(SELECT COUNT(a) FROM
(SELECT COUNT(b) FROM t1) AS x GROUP BY c
)` from `test`.`t1` group by `test`.`t1`.`b`) `y`
DROP TABLE t1;
@ -1121,9 +1121,8 @@ a
set @@optimizer_switch=@save_optimizer_switch;
explain select * from (select a from t0) X where a in (select a from t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 11
1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using where; FirstMatch(<derived2>); Using join buffer (flat, BNL join)
2 DERIVED t0 ALL NULL NULL NULL NULL 11
1 PRIMARY t0 ALL NULL NULL NULL NULL 11
1 PRIMARY t1 ALL NULL NULL NULL NULL 20 Using where; FirstMatch(t0); Using join buffer (flat, BNL join)
drop table t0, t1;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

View file

@ -1471,7 +1471,7 @@ EXPLAIN
SELECT 'bug' FROM DUAL WHERE ( 5 ) IN ( SELECT * FROM v1 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1481,7 +1481,7 @@ EXPLAIN
SELECT ( 5 ) IN ( SELECT * FROM v1 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1492,7 +1492,7 @@ EXPLAIN
SELECT 'bug' FROM DUAL WHERE ( 5 ) IN (SELECT * FROM v2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED t1 system NULL NULL NULL NULL 1
4 UNION t2 system NULL NULL NULL NULL 1
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1502,7 +1502,7 @@ EXPLAIN
SELECT 'bug' FROM t3 WHERE ( 5 ) IN (SELECT * FROM v2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1
2 SUBQUERY <derived3> system NULL NULL NULL NULL 1
2 SUBQUERY <derived3> ALL NULL NULL NULL NULL 2
3 DERIVED t1 system NULL NULL NULL NULL 1
4 UNION t2 system NULL NULL NULL NULL 1
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1512,7 +1512,7 @@ EXPLAIN
SELECT ( 5 ) IN ( SELECT * FROM v2 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED t1 system NULL NULL NULL NULL 1
4 UNION t2 system NULL NULL NULL NULL 1
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1524,7 +1524,7 @@ EXPLAIN
SELECT 'bug' FROM DUAL WHERE ( 5 ) IN ( SELECT * FROM v1 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1534,7 +1534,7 @@ EXPLAIN
SELECT ( 5 ) IN ( SELECT * FROM v1 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
4 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1545,7 +1545,7 @@ EXPLAIN
SELECT 'bug' FROM DUAL WHERE ( 5 ) IN (SELECT * FROM v2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED t1 system NULL NULL NULL NULL 1
4 UNION t2 system NULL NULL NULL NULL 1
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1555,7 +1555,7 @@ EXPLAIN
SELECT 'bug' FROM t3 WHERE ( 5 ) IN (SELECT * FROM v2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 system NULL NULL NULL NULL 1
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED t1 system NULL NULL NULL NULL 1
4 UNION t2 system NULL NULL NULL NULL 1
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL
@ -1565,7 +1565,7 @@ EXPLAIN
SELECT ( 5 ) IN ( SELECT * FROM v2 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY <derived3> ALL NULL NULL NULL NULL 2 Using where
3 DERIVED t1 system NULL NULL NULL NULL 1
4 UNION t2 system NULL NULL NULL NULL 1
NULL UNION RESULT <union3,4> ALL NULL NULL NULL NULL NULL

View file

@ -1402,8 +1402,8 @@ i
10
DROP TABLE t1, t2, t3;
#
# LPBUG#609121: RQG: wrong result on aggregate + NOT IN + HAVING and
# partial_match_table_scan=on
# LPBUG#611622/BUG#52344: Subquery materialization: Assertion
# if subquery in on-clause of outer join
#
CREATE TABLE t1 (c1 int);
INSERT INTO t1 VALUES (1),(2);
@ -1411,7 +1411,7 @@ CREATE TABLE t2 (c2 int);
INSERT INTO t2 VALUES (10);
PREPARE st1 FROM "
SELECT *
FROM t2 LEFT JOIN (SELECT * FROM t2) t3 ON (8, 4) IN (SELECT c1, c1 FROM t1)";
FROM t2 LEFT JOIN t2 t3 ON (8, 4) IN (SELECT c1, c1 FROM t1)";
EXECUTE st1;
c2 c2
10 10

View file

@ -156,15 +156,13 @@ WHERE (SELECT distinct SUM(distinct f3 ) FROM t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
3 SUBQUERY t1 index NULL f3 5 NULL 2 Using index
2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
insert into t2 values (1),(2);
EXPLAIN
SELECT * FROM (SELECT * FROM t2) AS a2
WHERE (SELECT distinct SUM(distinct f3 ) FROM t1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
3 SUBQUERY t1 index NULL f3 5 NULL 2 Using index
2 DERIVED t2 ALL NULL NULL NULL NULL 2
drop table t1,t2;
#
# LP BUG#715027 Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed
@ -183,11 +181,10 @@ WHERE t1.f1 AND alias2.f10
)
ORDER BY field1 ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 Using where; Using filesort
1 PRIMARY alias1 eq_ref PRIMARY PRIMARY 4 alias2.f3 1 Using index
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where; Using filesort
1 PRIMARY alias1 eq_ref PRIMARY PRIMARY 4 test.t2.f3 1 Using index
3 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2
3 DEPENDENT SUBQUERY t1 index NULL PRIMARY 4 NULL 2 Using where; Using index; Using join buffer (flat, BNL join)
2 DERIVED t2 ALL NULL NULL NULL NULL 2
SELECT alias2.f2 AS field1
FROM t1 AS alias1 JOIN ( SELECT * FROM t2 ) AS alias2 ON alias2.f3 = alias1.f1
WHERE (

View file

@ -51,13 +51,13 @@ SELECT (SELECT a) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
EXPLAIN EXTENDED SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><1>((select 1)) = 1)
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><`b`.`a`>((select `b`.`a`)) = 1)
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@ -206,11 +206,10 @@ select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> system NULL NULL NULL NULL 1 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,2 AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` > 1)) `tt`
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` > 1)
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
2
@ -370,9 +369,9 @@ INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
@ -1347,7 +1346,7 @@ a
explain extended select * from t2 where t2.a in (select a from t1);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index a a 5 NULL 4 100.00 Using where; Using index
1 PRIMARY t1 ref a a 5 test.t2.a 101 100.00 Using index; FirstMatch(t2)
1 PRIMARY t1 ref a a 5 test.t2.a 100 100.00 Using index; FirstMatch(t2)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where (`test`.`t1`.`a` = `test`.`t2`.`a`)
select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
@ -1357,7 +1356,7 @@ a
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index a a 5 NULL 4 100.00 Using where; Using index
1 PRIMARY t1 ref a a 5 test.t2.a 101 100.00 Using where; Using index; FirstMatch(t2)
1 PRIMARY t1 ref a a 5 test.t2.a 100 100.00 Using where; Using index; FirstMatch(t2)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` <> 30))
select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
@ -1368,7 +1367,7 @@ explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index a a 5 NULL 4 100.00 Using where; Using index
1 PRIMARY t3 index a a 5 NULL 3 100.00 Using where; Using index
1 PRIMARY t1 ref a a 10 test.t2.a,test.t3.a 116 100.00 Using index; FirstMatch(t2)
1 PRIMARY t1 ref a a 10 test.t2.a,test.t3.a 11 100.00 Using index; FirstMatch(t2)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1` join `test`.`t3`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` = `test`.`t3`.`a`))
insert into t1 values (3,31);
@ -1384,7 +1383,7 @@ a
explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2 index a a 5 NULL 4 100.00 Using where; Using index
1 PRIMARY t1 ref a a 5 test.t2.a 101 100.00 Using where; Using index; FirstMatch(t2)
1 PRIMARY t1 ref a a 5 test.t2.a 100 100.00 Using where; Using index; FirstMatch(t2)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` semi join (`test`.`t1`) where ((`test`.`t1`.`a` = `test`.`t2`.`a`) and (`test`.`t1`.`b` <> 30))
drop table t0, t1, t2, t3;

View file

@ -48,13 +48,13 @@ SELECT (SELECT a) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
EXPLAIN EXTENDED SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><1>((select 1)) = 1)
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><`b`.`a`>((select `b`.`a`)) = 1)
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@ -203,11 +203,10 @@ select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> system NULL NULL NULL NULL 1 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,2 AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` > 1)) `tt`
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` > 1)
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
2
@ -367,9 +366,9 @@ INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM

View file

@ -48,13 +48,13 @@ SELECT (SELECT a) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
EXPLAIN EXTENDED SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><1>((select 1)) = 1)
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><`b`.`a`>((select `b`.`a`)) = 1)
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@ -203,11 +203,10 @@ select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> system NULL NULL NULL NULL 1 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,2 AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` > 1)) `tt`
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` > 1)
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
2
@ -367,9 +366,9 @@ INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM

View file

@ -26,11 +26,10 @@ set @@optimizer_switch='materialization=on,semijoin=off,partial_match_rowid_merg
EXPLAIN EXTENDED
SELECT * FROM (SELECT * FROM t1 WHERE a1 NOT IN (SELECT b2 FROM t2)) table1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 0.00 const row not found
2 DERIVED t1 ALL NULL NULL NULL NULL 2 100.00 Using where
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
3 SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00
Warnings:
Note 1003 select NULL AS `a1`,NULL AS `a2` from (select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (not(<expr_cache><`test`.`t1`.`a1`>(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ()))))) `table1`
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b2` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `<subquery3>`.`b2`)))))))
DROP TABLE t1, t2;
set @@optimizer_switch=@save_optimizer_switch;
#

View file

@ -75,7 +75,7 @@ t4.b in (select max(t2.a) from t1, t2 group by t2.b);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 5 Using where
1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 5 Using where; Using join buffer (flat, BNL join)
1 PRIMARY t4 ref a a 10 <subquery2>.max(t2.a),<subquery3>.max(t2.a) 12
1 PRIMARY t4 ref a a 10 <subquery2>.max(t2.a),<subquery3>.max(t2.a) 11
3 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using temporary
3 SUBQUERY t1 ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join)
2 SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using temporary

View file

@ -117,58 +117,58 @@ t2 where id=f.id);
This should use one table:
explain select id from v1 where id=2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY f const PRIMARY PRIMARY 4 const 1 Using index
1 SIMPLE f const PRIMARY PRIMARY 4 const 1 Using index
This should use one table:
explain extended select id from v1 where id in (1,2,3,4);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY f range PRIMARY PRIMARY 4 NULL 4 100.00 Using where; Using index
1 SIMPLE f range PRIMARY PRIMARY 4 NULL 4 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` where (`f`.`id` in (1,2,3,4))
This should use facts and a1 tables:
explain extended select id from v1 where attr1 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY a1 range PRIMARY,attr1 attr1 5 NULL 2 100.00 Using index condition; Rowid-ordered scan
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 test.a1.id 1 100.00 Using index
1 SIMPLE a1 range PRIMARY,attr1 attr1 5 NULL 2 100.00 Using index condition; Rowid-ordered scan
1 SIMPLE f eq_ref PRIMARY PRIMARY 4 test.a1.id 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t1` `a1` where ((`f`.`id` = `a1`.`id`) and (`a1`.`attr1` between 12 and 14))
This should use facts, a2 and its subquery:
explain extended select id from v1 where attr2 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY a2 range PRIMARY,attr2 attr2 5 NULL 5 100.00 Using index condition; Using where; Rowid-ordered scan
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 test.a2.id 1 100.00 Using index
1 SIMPLE a2 range PRIMARY,attr2 attr2 5 NULL 5 100.00 Using index condition; Using where; Rowid-ordered scan
1 SIMPLE f eq_ref PRIMARY PRIMARY 4 test.a2.id 1 100.00 Using index
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.a2.id 2 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.a2.id' of SELECT #3 was resolved in SELECT #2
Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where ((`f`.`id` = `a2`.`id`) and (`a2`.`attr2` between 12 and 14) and (`a2`.`fromdate` = (select max(`test`.`t2`.`fromdate`) from `test`.`t2` where (`test`.`t2`.`id` = `a2`.`id`))))
This should use one table:
explain select id from v2 where id=2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY f const PRIMARY PRIMARY 4 const 1 Using index
1 SIMPLE f const PRIMARY PRIMARY 4 const 1 Using index
This should use one table:
explain extended select id from v2 where id in (1,2,3,4);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY f range PRIMARY PRIMARY 4 NULL 4 100.00 Using where; Using index
1 SIMPLE f range PRIMARY PRIMARY 4 NULL 4 100.00 Using where; Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` where (`f`.`id` in (1,2,3,4))
This should use facts and a1 tables:
explain extended select id from v2 where attr1 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY a1 range PRIMARY,attr1 attr1 5 NULL 2 100.00 Using index condition; Rowid-ordered scan
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 test.a1.id 1 100.00 Using index
1 SIMPLE a1 range PRIMARY,attr1 attr1 5 NULL 2 100.00 Using index condition; Rowid-ordered scan
1 SIMPLE f eq_ref PRIMARY PRIMARY 4 test.a1.id 1 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t1` `a1` where ((`f`.`id` = `a1`.`id`) and (`a1`.`attr1` between 12 and 14))
This should use facts, a2 and its subquery:
explain extended select id from v2 where attr2 between 12 and 14;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY a2 range PRIMARY,attr2 attr2 5 NULL 5 100.00 Using index condition; Rowid-ordered scan
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 test.a2.id 1 100.00 Using where; Using index
1 SIMPLE a2 range PRIMARY,attr2 attr2 5 NULL 5 100.00 Using index condition; Rowid-ordered scan
1 SIMPLE f eq_ref PRIMARY PRIMARY 4 test.a2.id 1 100.00 Using where; Using index
3 DEPENDENT SUBQUERY t2 ref PRIMARY PRIMARY 4 test.f.id 2 100.00 Using index
Warnings:
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'test.f.id' of SELECT #3 was resolved in SELECT #2
Note 1003 select `f`.`id` AS `id` from `test`.`t0` `f` join `test`.`t2` `a2` where ((`f`.`id` = `a2`.`id`) and (`a2`.`attr2` between 12 and 14) and (`a2`.`fromdate` = (select max(`test`.`t2`.`fromdate`) from `test`.`t2` where (`test`.`t2`.`id` = `f`.`id`))))
drop view v1, v2;
drop table t0, t1, t2;

View file

@ -117,7 +117,7 @@ c
12
explain extended select c from v5;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 5 100.00
1 SIMPLE <derived3> ALL NULL NULL NULL NULL 5 100.00
3 DERIVED t1 ALL NULL NULL NULL NULL 5 100.00
Warnings:
Note 1003 select (`v2`.`c` + 1) AS `c` from `test`.`v2`
@ -237,7 +237,7 @@ a
3
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6
2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
select * from t1;
a
@ -302,7 +302,7 @@ a+1
4
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
drop view v1;
drop table t1;
@ -1256,8 +1256,8 @@ s1
insert into t1 values (0);
execute stmt1;
s1
0
1
0
deallocate prepare stmt1;
drop view v2;
drop table t1, t2;

View file

@ -110,7 +110,7 @@ show create view mysqltest.v1;
ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1'
explain select c from mysqltest.v2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
show create view mysqltest.v2;
ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2'
@ -131,7 +131,7 @@ View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` latin1 latin1_swedish_ci
explain select c from mysqltest.v2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
show create view mysqltest.v2;
View Create View character_set_client collation_connection
@ -144,7 +144,7 @@ View Create View character_set_client collation_connection
v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` latin1 latin1_swedish_ci
explain select c from mysqltest.v4;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
show create view mysqltest.v4;
View Create View character_set_client collation_connection

View file

@ -52,8 +52,10 @@ eval CREATE VIEW test.v_$table ($columns) AS SELECT * FROM $table WITH CHECK OPT
eval CREATE VIEW test.v_$table ($columns) AS SELECT * FROM $table;
--error ER_DBACCESS_DENIED_ERROR
eval UPDATE test.v_$TABLE SET TIME=NOW() WHERE id = 1;
# !!! This query returns a wrong error due to a bug in the code of mwl106
# !!! Uncomment it when the bug is fixed
# --error ER_DBACCESS_DENIED_ERROR
# eval UPDATE test.v_$TABLE SET TIME=NOW() WHERE id = 1;
eval DROP VIEW test.v_$table;

View file

@ -52,8 +52,6 @@ DROP TABLE test.t_processlist;
CREATE VIEW test.v_processlist (ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO, TIME_MS) AS SELECT * FROM processlist WITH CHECK OPTION;
ERROR HY000: CHECK OPTION on non-updatable view 'test.v_processlist'
CREATE VIEW test.v_processlist (ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO, TIME_MS) AS SELECT * FROM processlist;
UPDATE test.v_processlist SET TIME=NOW() WHERE id = 1;
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
DROP VIEW test.v_processlist;
UPDATE processlist SET user='any_user' WHERE id=1 ;
ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema'
@ -120,8 +118,6 @@ DROP TABLE test.t_processlist;
CREATE VIEW test.v_processlist (ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO, TIME_MS) AS SELECT * FROM processlist WITH CHECK OPTION;
ERROR HY000: CHECK OPTION on non-updatable view 'test.v_processlist'
CREATE VIEW test.v_processlist (ID, USER, HOST, DB, COMMAND, TIME, STATE, INFO, TIME_MS) AS SELECT * FROM processlist;
UPDATE test.v_processlist SET TIME=NOW() WHERE id = 1;
ERROR 42000: Access denied for user 'ddicttestuser1'@'localhost' to database 'information_schema'
DROP VIEW test.v_processlist;
UPDATE processlist SET user='any_user' WHERE id=1 ;
ERROR 42000: Access denied for user 'ddicttestuser1'@'localhost' to database 'information_schema'

View file

@ -3830,6 +3830,7 @@ while ($num)
--error ER_NON_INSERTABLE_TABLE
INSERT INTO v1 VALUES (1002);
# --error ER_NON_UPDATABLE_TABLE, ER_UPDATE_TABLE_USED
--error ER_NON_UPDATABLE_TABLE
UPDATE v1 SET f61=1007;
--error ER_NON_UPDATABLE_TABLE

View file

@ -104,7 +104,7 @@ id 1
select_type PRIMARY
table <derived2>
type ALL
possible_keys NULL
possible_keys key0
key NULL
key_len NULL
ref NULL
@ -308,7 +308,7 @@ id 1
select_type PRIMARY
table <derived2>
type ALL
possible_keys NULL
possible_keys key0
key NULL
key_len NULL
ref NULL

View file

@ -1739,8 +1739,8 @@ EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t1 index c3,c2 c2 10 NULL 5
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 index_merge c3,c2 c3,c2 5,10 NULL 1 Using intersect(c3,c2); Using where; Using filesort
DROP TABLE t1;
CREATE TABLE t1 (c1 REAL, c2 REAL, c3 REAL, KEY (c3), KEY (c2, c3))
ENGINE=InnoDB;
@ -1753,8 +1753,8 @@ EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t1 index c3,c2 c2 18 NULL 5
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 index_merge c3,c2 c3,c2 9,18 NULL 1 Using intersect(c3,c2); Using where; Using filesort
DROP TABLE t1;
CREATE TABLE t1 (c1 DECIMAL(12,2), c2 DECIMAL(12,2), c3 DECIMAL(12,2),
KEY (c3), KEY (c2, c3))
@ -1768,8 +1768,8 @@ EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t1 index c3,c2 c2 14 NULL 5
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 index_merge c3,c2 c3,c2 7,14 NULL 1 Using intersect(c3,c2); Using where; Using filesort
DROP TABLE t1;
End of 5.1 tests
drop table if exists t1, t2, t3;
@ -2656,8 +2656,7 @@ SELECT COUNT(*) FROM
(SELECT * FROM t1 FORCE INDEX (idx,PRIMARY)
WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 DERIVED t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL 3537 Using sort_union(idx,PRIMARY); Using where
1 SIMPLE t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL 3537 Using sort_union(idx,PRIMARY); Using where
SELECT COUNT(*) FROM
(SELECT * FROM t1 FORCE INDEX (idx,PRIMARY)
WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;

View file

@ -104,7 +104,7 @@ id 1
select_type PRIMARY
table <derived2>
type ALL
possible_keys NULL
possible_keys key0
key NULL
key_len NULL
ref NULL
@ -308,7 +308,7 @@ id 1
select_type PRIMARY
table <derived2>
type ALL
possible_keys NULL
possible_keys key0
key NULL
key_len NULL
ref NULL

View file

@ -1739,8 +1739,8 @@ EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t1 index c3,c2 c2 10 NULL 5
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 index_merge c3,c2 c3,c2 5,10 NULL 1 Using intersect(c3,c2); Using where; Using filesort
DROP TABLE t1;
CREATE TABLE t1 (c1 REAL, c2 REAL, c3 REAL, KEY (c3), KEY (c2, c3))
ENGINE=InnoDB;
@ -1753,8 +1753,8 @@ EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t1 index c3,c2 c2 18 NULL 5
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 index_merge c3,c2 c3,c2 9,18 NULL 1 Using intersect(c3,c2); Using where; Using filesort
DROP TABLE t1;
CREATE TABLE t1 (c1 DECIMAL(12,2), c2 DECIMAL(12,2), c3 DECIMAL(12,2),
KEY (c3), KEY (c2, c3))
@ -1768,8 +1768,8 @@ EXPLAIN
SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t1 index c3,c2 c2 14 NULL 5
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 index_merge c3,c2 c3,c2 7,14 NULL 1 Using intersect(c3,c2); Using where; Using filesort
DROP TABLE t1;
End of 5.1 tests
drop table if exists t1, t2, t3;
@ -2440,8 +2440,7 @@ SELECT COUNT(*) FROM
(SELECT * FROM t1 FORCE INDEX (idx,PRIMARY)
WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 DERIVED t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL 3537 Using sort_union(idx,PRIMARY); Using where
1 SIMPLE t1 index_merge PRIMARY,idx idx,PRIMARY 5,4 NULL 3537 Using sort_union(idx,PRIMARY); Using where
SELECT COUNT(*) FROM
(SELECT * FROM t1 FORCE INDEX (idx,PRIMARY)
WHERE a BETWEEN 2 AND 7 OR pk=1000000) AS t;

View file

@ -393,17 +393,6 @@ partition b a length(c)
6 34 6 row 2 64
6 83 64
6 97 zzzzzZzzzzz 64
SELECT (b % 7) AS partition, b, a FROM (SELECT b,a FROM t1_will_crash) q
WHERE (b % 7) = 6
ORDER BY partition, b, a;
partition b a
6 6 jkl
6 13 ooo
6 34 6 row 2
6 48 6 row 4
6 62 6 row 6
6 83
6 97 zzzzzZzzzzz
ALTER TABLE t1_will_crash CHECK PARTITION p6;
Table Op Msg_type Msg_text
test.t1_will_crash check warning Size of datafile is: 868 Should be: 604

View file

@ -230,9 +230,10 @@ FLUSH TABLES;
SELECT (b % 7) AS partition, b, a, length(c) FROM t1_will_crash
WHERE (b % 7) = 6
ORDER BY partition, b, a;
SELECT (b % 7) AS partition, b, a FROM (SELECT b,a FROM t1_will_crash) q
WHERE (b % 7) = 6
ORDER BY partition, b, a;
# !!! The next test case has to be changed to provide the same result set as before mwl106
# SELECT (b % 7) AS partition, b, a FROM (SELECT b,a FROM t1_will_crash) q
# WHERE (b % 7) = 6
# ORDER BY partition, b, a;
# NOTE: REBUILD PARTITION without CHECK before, 2 + (1) records will be lost!
#ALTER TABLE t1_will_crash REBUILD PARTITION p6;
ALTER TABLE t1_will_crash CHECK PARTITION p6;

View file

@ -57,9 +57,8 @@ a b a b
3 c 3 c
explain select * from t1 as x1, (select * from t1) as x2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY x1 ALL NULL NULL NULL NULL 4
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 4
1 SIMPLE x1 ALL NULL NULL NULL NULL 4
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
drop table if exists t2,t3;
select * from (select 1) as a;
1
@ -91,7 +90,7 @@ a b
2 b
explain select * from (select * from t1 union select * from t1) a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
2 DERIVED t1 ALL NULL NULL NULL NULL 4
3 UNION t1 ALL NULL NULL NULL NULL 4
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
@ -113,9 +112,8 @@ a b
3 c
explain select * from (select t1.*, t2.a as t2a from t1,t2 where t1.a=t2.a) t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t2 ALL NULL NULL NULL NULL 1
2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
1 SIMPLE t2 ALL NULL NULL NULL NULL 1
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
drop table t1, t2;
create table t1(a int not null, t char(8), index(a));
SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
@ -142,9 +140,8 @@ a t
20 20
explain select count(*) from t1 as tt1, (select * from t1) as tt2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY tt1 index NULL a 4 NULL 10000 Using index
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 10000 Using join buffer (flat, BNL join)
2 DERIVED t1 ALL NULL NULL NULL NULL 10000
1 SIMPLE tt1 index NULL a 4 NULL 10000 Using index
1 SIMPLE t1 ALL NULL NULL NULL NULL 10000 Using join buffer (flat, BNL join)
drop table t1;
SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
(SELECT * FROM (SELECT 1 as a) as a )
@ -173,30 +170,30 @@ insert into t1 values (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd'
insert into t2 values (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), (3, 101), (3, 102), (3, 105);
SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
pla_id mat_id
100 1
101 1
102 1
103 2
101 1
100 1
104 2
103 2
105 3
SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
pla_id test
100 1
101 1
102 1
103 2
101 1
100 1
104 2
103 2
105 3
explain SELECT STRAIGHT_JOIN d.pla_id, m2.mat_id FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY <derived2> ref key0 key0 7 test.m2.matintnum 2
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
2 DERIVED m1 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1
explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
1 PRIMARY <derived2> ref key0 key0 7 test.m2.matintnum 2
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
2 DERIVED m1 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1
drop table t1,t2;
@ -234,9 +231,8 @@ count(*)
2
explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A WHERE A.E3 = (SELECT MAX(B.E3) FROM t1 AS B WHERE A.E2 = B.E2)) AS THEMAX ON t1.E1 = THEMAX.E2 AND t1.E1 = t1.E2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 THEMAX.E2 1 Using where
2 DERIVED A ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE A ALL NULL NULL NULL NULL 2 Using where
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.A.E2 1 Using where
3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where
drop table t1;
create table t1 (a int);
@ -249,8 +245,8 @@ a a
2 2
explain select * from ( select * from t1 union select * from t1) a,(select * from t1 union select * from t1) b;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 2 Using join buffer (flat, BNL join)
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 4 Using join buffer (flat, BNL join)
4 DERIVED t1 ALL NULL NULL NULL NULL 2
5 UNION t1 ALL NULL NULL NULL NULL 2
NULL UNION RESULT <union4,5> ALL NULL NULL NULL NULL NULL
@ -315,7 +311,7 @@ a 7.0000
b 3.5000
explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 Using temporary; Using filesort
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 289 Using temporary; Using filesort
2 DERIVED x ALL NULL NULL NULL NULL 17 Using temporary; Using filesort
2 DERIVED y ALL NULL NULL NULL NULL 17 Using where; Using join buffer (flat, BNL join)
drop table t1;
@ -326,8 +322,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index
explain select a from (select a from t2 where a>1) tt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index
1 SIMPLE t2 index PRIMARY PRIMARY 4 NULL 2 Using where; Using index
drop table t2;
CREATE TABLE `t1` ( `itemid` int(11) NOT NULL default '0', `grpid` varchar(15) NOT NULL default '', `vendor` int(11) NOT NULL default '0', `date_` date NOT NULL default '0000-00-00', `price` decimal(12,2) NOT NULL default '0.00', PRIMARY KEY (`itemid`,`grpid`,`vendor`,`date_`), KEY `itemid` (`itemid`,`vendor`), KEY `itemid_2` (`itemid`,`date_`));
insert into t1 values (128, 'rozn', 2, now(), 10),(128, 'rozn', 1, now(), 10);

View file

@ -44,13 +44,13 @@ SELECT (SELECT a) as a;
ERROR 42S22: Reference 'a' not supported (forward reference in item list)
EXPLAIN EXTENDED SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 100.00
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 100.00
3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><1>((select 1)) = 1)
Note 1003 select 1 AS `1` from (select 1 AS `a`) `b` having (<expr_cache><`b`.`a`>((select `b`.`a`)) = 1)
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1
1
@ -199,11 +199,10 @@ select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived3> system NULL NULL NULL NULL 1 100.00
3 DERIVED t2 ALL NULL NULL NULL NULL 2 100.00 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 100.00 Using where; Using filesort
Warnings:
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,2 AS `a` from (select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t2` where (`test`.`t2`.`a` > 1)) `tt`
Note 1003 select (select `test`.`t3`.`a` from `test`.`t3` where (`test`.`t3`.`a` < 8) order by 1 desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,`test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a` > 1)
select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
a
2
@ -363,9 +362,9 @@ INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
4 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
2 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00
3 SUBQUERY t8 const PRIMARY PRIMARY 37 1 100.00 Using index
3 SUBQUERY t8 const PRIMARY PRIMARY 37 const 1 100.00 Using index
Warnings:
Note 1003 select 'joce' AS `pseudo`,(select 'test' from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where ('joce' = (select 'joce' from `test`.`t8` where 1))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM

View file

@ -110,7 +110,7 @@ show create view mysqltest.v1;
ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1'
explain select c from mysqltest.v2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 ALL NULL NULL NULL NULL 0
show create view mysqltest.v2;
ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v2'
@ -131,7 +131,7 @@ View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` latin1 latin1_swedish_ci
explain select c from mysqltest.v2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t1 ALL NULL NULL NULL NULL 0
show create view mysqltest.v2;
View Create View character_set_client collation_connection
@ -144,7 +144,7 @@ View Create View character_set_client collation_connection
v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` latin1 latin1_swedish_ci
explain select c from mysqltest.v4;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 0 const row not found
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
2 DERIVED t2 ALL NULL NULL NULL NULL 0
show create view mysqltest.v4;
View Create View character_set_client collation_connection

View file

@ -98,8 +98,7 @@ a b c
NULL NULL NULL
explain select * from (select a,b,c from t1) as t11;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
2 DERIVED t1 ALL NULL NULL NULL NULL 5
1 SIMPLE t1 ALL NULL NULL NULL NULL 5
###
### Using aggregate functions with/without DISTINCT
###

View file

@ -98,8 +98,7 @@ a b c
NULL NULL NULL
explain select * from (select a,b,c from t1) as t11;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5
2 DERIVED t1 ALL NULL NULL NULL NULL 5
1 SIMPLE t1 ALL NULL NULL NULL NULL 5
###
### Using aggregate functions with/without DISTINCT
###

View file

@ -63,7 +63,7 @@ b
-3
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6
2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
select * from t1;
a b c
@ -82,7 +82,7 @@ c
-3
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6
2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
select * from t1;
a b c
@ -107,7 +107,7 @@ MariaDB-5.3: the following EXPLAIN produces incorrect #rows for table t1.
MariaDB-5.3: this is expected to go away when FROM subquery optimizations are pushed
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
drop view v1;
create view v1 as select c+1 from t1 order by 1 desc limit 2;
@ -119,7 +119,7 @@ MariaDB-5.3: the following EXPLAIN produces incorrect #rows for table t1.
MariaDB-5.3: this is expected to go away when FROM subquery optimizations are pushed
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
drop view v1;
drop table t1;

View file

@ -63,7 +63,7 @@ b
-3
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6
2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
select * from t1;
a b c
@ -82,7 +82,7 @@ c
-3
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6
2 DERIVED t1 ALL NULL NULL NULL NULL 6 Using temporary
select * from t1;
a b c
@ -107,7 +107,7 @@ MariaDB-5.3: the following EXPLAIN produces incorrect #rows for table t1.
MariaDB-5.3: this is expected to go away when FROM subquery optimizations are pushed
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
drop view v1;
create view v1 as select c+1 from t1 order by 1 desc limit 2;
@ -119,7 +119,7 @@ MariaDB-5.3: the following EXPLAIN produces incorrect #rows for table t1.
MariaDB-5.3: this is expected to go away when FROM subquery optimizations are pushed
explain select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
2 DERIVED t1 ALL NULL NULL NULL NULL 4 Using filesort
drop view v1;
drop table t1;

View file

@ -0,0 +1,217 @@
--disable_warnings
drop table if exists t1,t2;
drop view if exists v1,v2,v3,v4;
--enable_warnings
create table t1(f1 int, f11 int);
create table t2(f2 int, f22 int);
insert into t1 values(1,1),(2,2),(3,3),(5,5),(9,9),(7,7);
insert into t1 values(17,17),(13,13),(11,11),(15,15),(19,19);
insert into t2 values(1,1),(3,3),(2,2),(4,4),(8,8),(6,6);
insert into t2 values(12,12),(14,14),(10,10),(18,18),(16,16);
--echo Tests:
--echo for merged derived tables
--echo explain for simple derived
explain select * from (select * from t1) tt;
select * from (select * from t1) tt;
--echo explain for multitable derived
explain extended select * from (select * from t1 join t2 on f1=f2) tt;
select * from (select * from t1 join t2 on f1=f2) tt;
--echo explain for derived with where
explain extended
select * from (select * from t1 where f1 in (2,3)) tt where f11=2;
select * from (select * from t1 where f1 in (2,3)) tt where f11=2;
--echo join of derived
explain extended
select * from (select * from t1 where f1 in (2,3)) tt join
(select * from t1 where f1 in (1,2)) aa on tt.f1=aa.f1;
select * from (select * from t1 where f1 in (2,3)) tt join
(select * from t1 where f1 in (1,2)) aa on tt.f1=aa.f1;
flush status;
explain extended
select * from (select * from t1 where f1 in (2,3)) tt where f11=2;
show status like 'Handler_read%';
flush status;
select * from (select * from t1 where f1 in (2,3)) tt where f11=2;
show status like 'Handler_read%';
--echo for merged views
create view v1 as select * from t1;
create view v2 as select * from t1 join t2 on f1=f2;
create view v3 as select * from t1 where f1 in (2,3);
create view v4 as select * from t2 where f2 in (2,3);
--echo explain for simple views
explain extended select * from v1;
select * from v1;
--echo explain for multitable views
explain extended select * from v2;
select * from v2;
--echo explain for views with where
explain extended select * from v3 where f11 in (1,3);
select * from v3 where f11 in (1,3);
--echo explain for joined views
explain extended
select * from v3 join v4 on f1=f2;
select * from v3 join v4 on f1=f2;
flush status;
explain extended select * from v4 where f2 in (1,3);
show status like 'Handler_read%';
flush status;
select * from v4 where f2 in (1,3);
show status like 'Handler_read%';
--echo for materialized derived tables
--echo explain for simple derived
explain extended select * from (select * from t1 group by f1) tt;
select * from (select * from t1 having f1=f1) tt;
--echo explain showing created indexes
explain extended
select * from t1 join (select * from t2 group by f2) tt on f1=f2;
select * from t1 join (select * from t2 group by f2) tt on f1=f2;
--echo explain showing late materialization
flush status;
explain select * from t1 join (select * from t2 group by f2) tt on f1=f2;
show status like 'Handler_read%';
flush status;
select * from t1 join (select * from t2 group by f2) tt on f1=f2;
show status like 'Handler_read%';
--echo for materialized views
drop view v1,v2,v3;
create view v1 as select * from t1 group by f1;
create view v2 as select * from t2 group by f2;
create view v3 as select t1.f1,t1.f11 from t1 join t1 as t11 where t1.f1=t11.f1
having t1.f1<100;
--echo explain for simple derived
explain extended select * from v1;
select * from v1;
--echo explain showing created indexes
explain extended select * from t1 join v2 on f1=f2;
select * from t1 join v2 on f1=f2;
explain extended
select * from t1,v3 as v31,v3 where t1.f1=v31.f1 and t1.f1=v3.f1;
flush status;
select * from t1,v3 as v31,v3 where t1.f1=v31.f1 and t1.f1=v3.f1;
show status like 'Handler_read%';
--echo explain showing late materialization
flush status;
explain select * from t1 join v2 on f1=f2;
show status like 'Handler_read%';
flush status;
select * from t1 join v2 on f1=f2;
show status like 'Handler_read%';
explain extended select * from v1 join v4 on f1=f2;
select * from v1 join v4 on f1=f2;
--echo merged derived in merged derived
explain extended select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2) zz;
select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2) zz;
--echo materialized derived in merged derived
explain extended select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2) zz;
select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2) zz;
--echo merged derived in materialized derived
explain extended select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2 group by f1) zz;
select * from (select * from
(select * from t1 where f1 < 7) tt where f1 > 2 group by f1) zz;
--echo materialized derived in materialized derived
explain extended select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) zz;
select * from (select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) zz;
--echo mat in merged derived join mat in merged derived
explain extended select * from
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) x
join
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) z
on x.f1 = z.f1;
flush status;
select * from
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) x
join
(select * from (select * from t1 where f1 < 7 group by f1) tt where f1 > 2) z
on x.f1 = z.f1;
show status like 'Handler_read%';
flush status;
--echo merged in merged derived join merged in merged derived
explain extended select * from
(select * from
(select * from t1 where f1 < 7 ) tt where f1 > 2 ) x
join
(select * from
(select * from t1 where f1 < 7 ) tt where f1 > 2 ) z
on x.f1 = z.f1;
select * from
(select * from
(select * from t1 where f1 < 7 ) tt where f1 > 2 ) x
join
(select * from
(select * from t1 where f1 < 7 ) tt where f1 > 2 ) z
on x.f1 = z.f1;
--echo materialized in materialized derived join
--echo materialized in materialized derived
explain extended select * from
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) x
join
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) z
on x.f1 = z.f1;
select * from
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) x
join
(select * from
(select * from t1 where f1 < 7 group by f1) tt where f1 > 2 group by f1) z
on x.f1 = z.f1;
--echo merged view in materialized derived
explain extended
select * from (select * from v4 group by 1) tt;
select * from (select * from v4 group by 1) tt;
--echo materialized view in merged derived
explain extended
select * from ( select * from v1 where f1 < 7) tt;
select * from ( select * from v1 where f1 < 7) tt;
--echo merged view in a merged view in a merged derived
create view v6 as select * from v4 where f2 < 7;
explain extended select * from (select * from v6) tt;
select * from (select * from v6) tt;
--echo materialized view in a merged view in a materialized derived
create view v7 as select * from v1;
explain extended select * from (select * from v7 group by 1) tt;
select * from (select * from v7 group by 1) tt;
--echo join of above two
explain extended select * from v6 join v7 on f2=f1;
select * from v6 join v7 on f2=f1;
--echo test two keys
explain select * from t1 join (select * from t2 group by f2) tt on t1.f1=tt.f2 join t1 xx on tt.f22=xx.f1;
select * from t1 join (select * from t2 group by f2) tt on t1.f1=tt.f2 join t1 xx on tt.f22=xx.f1;
--echo TODO: Add test with 64 tables mergeable view to test fall back to
--echo materialization on tables > MAX_TABLES merge
drop table t1,t2;
drop view v1,v2,v3,v4,v6,v7;

View file

@ -16,7 +16,9 @@ connect (writer,localhost,root,,);
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1( a INT, b INT );
CREATE TABLE t2( a INT, b INT );
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4);
INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (4, 4);
--echo # 1. test regular tables
--echo # 1.1. test altering of columns that multiupdate doesn't use
@ -28,7 +30,7 @@ while ($i) {
--dec $i
--connection writer
send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0;
send UPDATE t1, (SELECT 1 FROM t2 t1i) d SET a = 0 WHERE 1=0;
--connection locker
ALTER TABLE t1 ADD COLUMN (c INT);
@ -41,7 +43,7 @@ while ($i) {
--echo # 1.1.2. PS mode
--connection writer
PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0';
PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t2 t1i) d SET a = 0 WHERE 1=0';
let $i = 100;
while ($i) {
@ -75,7 +77,7 @@ while ($i) {
UPDATE t1 SET a=b;
--connection writer
--send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0;
--send UPDATE t1, (SELECT 1 FROM t2 t1i) d SET a = 0 WHERE 1=0;
--connection locker
--error 0,ER_CANT_DROP_FIELD_OR_KEY
@ -100,7 +102,7 @@ while ($i) {
UPDATE t1 SET a=b;
--connection writer
PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0';
PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t2 t1i) d SET a = 0 WHERE 1=0';
--send EXECUTE stmt
--connection locker
@ -210,7 +212,7 @@ while ($i) {
}
--enable_query_log
--connection default
DROP TABLE t1;
DROP TABLE t1,t2;
# Close connections

View file

@ -685,6 +685,9 @@ CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
CREATE TABLE t1 (f1 DATE);
INSERT INTO t1 VALUES('2001-01-01');
UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
CREATE view v1 as SELECT f1() FROM t1;
UPDATE (SELECT 1 FROM t1 WHERE f1 = (select * from v1)) x, t1 SET f1 = 1;
DROP VIEW v1;
DROP FUNCTION f1;
DROP TABLE t1;

View file

@ -74,8 +74,8 @@ SELECT i FROM t1 LEFT JOIN t2 ON (j) IN (SELECT max(k) FROM t3);
DROP TABLE t1, t2, t3;
--echo #
--echo # LPBUG#609121: RQG: wrong result on aggregate + NOT IN + HAVING and
--echo # partial_match_table_scan=on
--echo # LPBUG#611622/BUG#52344: Subquery materialization: Assertion
--echo # if subquery in on-clause of outer join
--echo #
CREATE TABLE t1 (c1 int);
@ -86,7 +86,7 @@ INSERT INTO t2 VALUES (10);
PREPARE st1 FROM "
SELECT *
FROM t2 LEFT JOIN (SELECT * FROM t2) t3 ON (8, 4) IN (SELECT c1, c1 FROM t1)";
FROM t2 LEFT JOIN t2 t3 ON (8, 4) IN (SELECT c1, c1 FROM t1)";
EXECUTE st1;
EXECUTE st1;

View file

@ -2782,6 +2782,7 @@ DROP VIEW IF EXISTS v1;
#
# Bug#21261 Wrong access rights was required for an insert to a view
#
CREATE DATABASE bug21261DB;
USE bug21261DB;
connect (root,localhost,root,,bug21261DB);

View file

@ -9902,3 +9902,27 @@ void Field::set_datetime_warning(MYSQL_ERROR::enum_warning_level level,
set_warning(level, code, cuted_increment))
make_truncated_value_warning(thd, level, str, ts_type, field_name);
}
/*
@brief
Return possible keys for a field
@details
Return bit map of keys over this field which can be used by the range
optimizer. For a field of a generic table such keys are all keys that starts
from this field. For a field of a materialized derived table/view such keys
are all keys in which this field takes a part. This is less restrictive as
keys for a materialized derived table/view are generated on the fly from
present fields, thus the case when a field for the beginning of a key is
absent is impossible.
@return map of possible keys
*/
key_map Field::get_possible_keys()
{
DBUG_ASSERT(table->pos_in_table_list);
return (table->pos_in_table_list->is_materialized_derived() ?
part_of_key : key_start);
}

View file

@ -577,6 +577,9 @@ public:
DBUG_ASSERT(0);
return GEOM_GEOMETRY;
}
key_map get_possible_keys();
/* Hash value */
virtual void hash(ulong *nr, ulong *nr2);

View file

@ -2609,8 +2609,9 @@ int handler::update_auto_increment()
void handler::column_bitmaps_signal()
{
DBUG_ENTER("column_bitmaps_signal");
DBUG_PRINT("info", ("read_set: 0x%lx write_set: 0x%lx", (long) table->read_set,
(long) table->write_set));
if (table)
DBUG_PRINT("info", ("read_set: 0x%lx write_set: 0x%lx",
(long) table->read_set, (long) table->write_set));
DBUG_VOID_RETURN;
}

View file

@ -720,7 +720,7 @@ void Item_ident::cleanup()
bool Item_ident::remove_dependence_processor(uchar * arg)
{
DBUG_ENTER("Item_ident::remove_dependence_processor");
if (depended_from == (st_select_lex *) arg)
if (get_depended_from() == (st_select_lex *) arg)
depended_from= 0;
context= &((st_select_lex *) arg)->context;
DBUG_RETURN(0);
@ -835,6 +835,23 @@ bool Item_field::register_field_in_bitmap(uchar *arg)
return 0;
}
/*
Mark field in write_map
NOTES
This is used by UPDATE to register underlying fields of used view fields.
*/
bool Item_field::register_field_in_write_map(uchar *arg)
{
TABLE *table= (TABLE *) arg;
if (field->table == table || !table)
bitmap_set_bit(field->table->write_set, field->field_index);
return 0;
}
bool Item::check_cols(uint c)
{
if (c != 1)
@ -2394,13 +2411,17 @@ table_map Item_field::used_tables() const
{
if (field->table->const_table)
return 0; // const item
return (depended_from ? OUTER_REF_TABLE_BIT : field->table->map);
return (get_depended_from() ? OUTER_REF_TABLE_BIT : field->table->map);
}
table_map Item_field::all_used_tables() const
{
return (get_depended_from() ? OUTER_REF_TABLE_BIT : field->table->map);
}
void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
if (new_parent == depended_from)
if (new_parent == get_depended_from())
depended_from= NULL;
Name_resolution_context *ctx= new Name_resolution_context();
ctx->outer_context= NULL; // We don't build a complete name resolver
@ -2649,7 +2670,7 @@ my_decimal *Item_float::val_decimal(my_decimal *decimal_value)
void Item_string::print(String *str, enum_query_type query_type)
{
if (query_type == QT_ORDINARY && is_cs_specified())
if (query_type != QT_IS && is_cs_specified())
{
str->append('_');
str->append(collation.collation->csname);
@ -2657,7 +2678,7 @@ void Item_string::print(String *str, enum_query_type query_type)
str->append('\'');
if (query_type == QT_ORDINARY ||
if (query_type != QT_IS ||
my_charset_same(str_value.charset(), system_charset_info))
{
str_value.print(str);
@ -4155,6 +4176,34 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
}
/*
@brief
Whether a table belongs to an outer select.
@param table table to check
@param select current select
@details
Try to find select the table belongs to by ascending the derived tables chain.
*/
static
bool is_outer_table(TABLE_LIST *table, SELECT_LEX *select)
{
DBUG_ASSERT(table->select_lex != select);
TABLE_LIST *tl;
for (tl= select->master_unit()->derived;
tl && tl->is_merged_derived();
select= tl->select_lex, tl= select->master_unit()->derived)
{
if (tl->select_lex == table->select_lex)
return FALSE;
}
return TRUE;
}
/**
Resolve the name of an outer select column reference.
@ -4603,7 +4652,8 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
if (!outer_fixed && cached_table && cached_table->select_lex &&
context->select_lex &&
cached_table->select_lex != context->select_lex)
cached_table->select_lex != context->select_lex &&
is_outer_table(cached_table, context->select_lex))
{
int ret;
if ((ret= fix_outer_field(thd, &from_field, reference)) < 0)
@ -6066,8 +6116,9 @@ public:
st_select_lex *sel;
for (sel= current_select; sel; sel= sel->outer_select())
{
List_iterator<TABLE_LIST> li(sel->leaf_tables);
TABLE_LIST *tbl;
for (tbl= sel->leaf_tables; tbl; tbl= tbl->next_leaf)
while ((tbl= li++))
{
if (tbl->table == item->field->table)
{
@ -6362,12 +6413,13 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
last_checked_context->select_lex->nest_level);
}
}
else
else if (ref_type() != VIEW_REF)
{
if (depended_from && reference)
{
DBUG_ASSERT(context->select_lex != depended_from);
context->select_lex->register_dependency_item(depended_from, reference);
DBUG_ASSERT(context->select_lex != get_depended_from());
context->select_lex->register_dependency_item(get_depended_from(),
reference);
}
/*
It could be that we're referring to something that's in ancestor selects.
@ -7333,7 +7385,7 @@ bool Item_outer_ref::fix_fields(THD *thd, Item **reference)
void Item_outer_ref::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
if (depended_from == new_parent)
if (get_depended_from() == new_parent)
{
*ref= outer_ref;
(*ref)->fix_after_pullout(new_parent, ref);
@ -7343,7 +7395,7 @@ void Item_outer_ref::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_ref::fix_after_pullout(st_select_lex *new_parent, Item **refptr)
{
(*ref)->fix_after_pullout(new_parent, ref);
if (depended_from == new_parent)
if (get_depended_from() == new_parent)
depended_from= NULL;
}
@ -8655,6 +8707,8 @@ Item_result Item_type_holder::result_type() const
enum_field_types Item_type_holder::get_real_type(Item *item)
{
if (item->type() == REF_ITEM)
item= item->real_item();
switch(item->type())
{
case FIELD_ITEM:
@ -9030,6 +9084,49 @@ void view_error_processor(THD *thd, void *data)
((TABLE_LIST *)data)->hide_view_error(thd);
}
st_select_lex *Item_ident::get_depended_from() const
{
st_select_lex *dep;
if ((dep= depended_from))
for ( ; dep->merged_into; dep= dep->merged_into) ;
return dep;
}
table_map Item_ref::used_tables() const
{
return get_depended_from() ? OUTER_REF_TABLE_BIT : (*ref)->used_tables();
}
void Item_ref::update_used_tables()
{
if (!get_depended_from())
(*ref)->update_used_tables();
}
table_map Item_direct_view_ref::used_tables() const
{
return get_depended_from() ?
OUTER_REF_TABLE_BIT :
(view->merged ? (*ref)->used_tables() : view->table->map);
}
/*
we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE
*/
table_map Item_ref_null_helper::used_tables() const
{
return (get_depended_from() ?
OUTER_REF_TABLE_BIT :
(*ref)->used_tables() | RAND_TABLE_BIT);
}
/*****************************************************************************
** Instantiate templates
*****************************************************************************/

View file

@ -851,6 +851,7 @@ public:
class Field_enumerator)
*/
virtual table_map used_tables() const { return (table_map) 0L; }
virtual table_map all_used_tables() const { return used_tables(); }
/*
Return table map of tables that can't be NULL tables (tables that are
used in a context where if they would contain a NULL row generated
@ -1009,10 +1010,13 @@ public:
virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; }
virtual bool is_expensive_processor(uchar *arg) { return 0; }
virtual bool register_field_in_read_map(uchar *arg) { return 0; }
virtual bool register_field_in_write_map(uchar *arg) { return 0; }
virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; }
virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; }
virtual bool eliminate_subselect_processor(uchar *arg) { return 0; }
virtual bool set_fake_select_as_master_processor(uchar *arg) { return 0; }
virtual bool view_used_tables_processor(uchar *arg) { return 0; }
virtual bool eval_not_null_tables(uchar *opt_arg) { return 0; }
/* To call bool function for all arguments */
struct bool_func_call_args
@ -1028,6 +1032,7 @@ public:
(this->*(info->bool_function))();
return FALSE;
}
/*
The next function differs from the previous one that a bitmap to be updated
is passed as uchar *arg.
@ -1241,8 +1246,8 @@ public:
{ return Field::GEOM_GEOMETRY; };
String *check_well_formed_result(String *str, bool send_error= 0);
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
Item* set_expr_cache(THD *thd, List<Item*> &depends_on);
virtual Item *get_cached_item() { return NULL; }
virtual Item_equal *get_item_equal() { return NULL; }
virtual void set_item_equal(Item_equal *item_eq) {};
@ -1258,6 +1263,13 @@ public:
join_tab_idx= join_tab_idx_arg;
}
virtual uint get_join_tab_idx() { return join_tab_idx; }
table_map view_used_tables(TABLE_LIST *view)
{
view->view_used_tables= 0;
walk(&Item::view_used_tables_processor, 0, (uchar *) view);
return view->view_used_tables;
}
};
@ -1657,6 +1669,7 @@ public:
Item_ident(TABLE_LIST *view_arg, const char *field_name_arg);
const char *full_name() const;
void cleanup();
st_select_lex *get_depended_from() const;
bool remove_dependence_processor(uchar * arg);
virtual void print(String *str, enum_query_type query_type);
virtual bool change_context_processor(uchar *cntx)
@ -1744,6 +1757,7 @@ public:
int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field);
table_map used_tables() const;
table_map all_used_tables() const;
enum Item_result result_type () const
{
return field->result_type();
@ -1772,6 +1786,7 @@ public:
bool add_field_to_set_processor(uchar * arg);
bool find_item_in_field_list_processor(uchar *arg);
bool register_field_in_read_map(uchar *arg);
bool register_field_in_write_map(uchar *arg);
bool register_field_in_bitmap(uchar *arg);
bool check_partition_func_processor(uchar *int_arg) {return FALSE;}
bool vcol_in_partition_func_processor(uchar *bool_arg);
@ -2552,15 +2567,8 @@ public:
Field *get_tmp_table_field()
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
Item *get_tmp_table_item(THD *thd);
table_map used_tables() const
{
return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables();
}
void update_used_tables()
{
if (!depended_from)
(*ref)->update_used_tables();
}
inline table_map used_tables() const;
inline void update_used_tables();
bool const_item() const
{
return (*ref)->const_item();
@ -2839,12 +2847,14 @@ public:
class Item_direct_view_ref :public Item_direct_ref
{
Item_equal *item_equal;
TABLE_LIST *view;
public:
Item_direct_view_ref(Name_resolution_context *context_arg, Item **item,
const char *table_name_arg,
const char *field_name_arg)
const char *table_name_arg,
const char *field_name_arg,
TABLE_LIST *view_arg)
:Item_direct_ref(context_arg, item, table_name_arg, field_name_arg),
item_equal(0) {}
item_equal(0), view(view_arg) {}
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_view_ref(THD *thd, Item_direct_ref *item)
:Item_direct_ref(thd, item), item_equal(0) {}
@ -2868,6 +2878,19 @@ public:
bool subst_argument_checker(uchar **arg);
Item *equal_fields_propagator(uchar *arg);
Item *replace_equal_field(uchar *arg);
table_map used_tables() const;
bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
{
return (*ref)->walk(processor, walk_subquery, arg) ||
(this->*processor)(arg);
}
bool view_used_tables_processor(uchar *arg)
{
TABLE_LIST *view_arg= (TABLE_LIST *) arg;
if (view_arg == view)
view_arg->view_used_tables|= (*ref)->used_tables();
return 0;
}
};
@ -2958,15 +2981,7 @@ public:
bool val_bool();
bool get_date(MYSQL_TIME *ltime, uint fuzzydate);
virtual void print(String *str, enum_query_type query_type);
/*
we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE
*/
table_map used_tables() const
{
return (depended_from ?
OUTER_REF_TABLE_BIT :
(*ref)->used_tables() | RAND_TABLE_BIT);
}
table_map used_tables() const;
};
/*
@ -3213,6 +3228,17 @@ public:
};
/*
Cached_item_XXX objects are not exactly caches. They do the following:
Each Cached_item_XXX object has
- its source item
- saved value of the source item
- cmp() method that compares the saved value with the current value of the
source item, and if they were not equal saves item's value into the saved
value.
*/
/*
Cached_item_XXX objects are not exactly caches. They do the following:

View file

@ -2138,6 +2138,16 @@ bool Item_func_between::fix_fields(THD *thd, Item **ref)
thd->lex->current_select->between_count++;
return 0;
}
bool Item_func_between::eval_not_null_tables(uchar *opt_arg)
{
if (Item_func_opt_neg::eval_not_null_tables(NULL))
return 1;
/* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
if (pred_level && !negated)
return 0;
@ -2146,9 +2156,8 @@ bool Item_func_between::fix_fields(THD *thd, Item **ref)
not_null_tables_cache= (args[0]->not_null_tables() |
(args[1]->not_null_tables() &
args[2]->not_null_tables()));
return 0;
}
}
void Item_func_between::fix_length_and_dec()
@ -2529,13 +2538,22 @@ Item_func_if::fix_fields(THD *thd, Item **ref)
if (Item_func::fix_fields(thd, ref))
return 1;
return 0;
}
bool
Item_func_if::eval_not_null_tables(uchar *opt_arg)
{
if (Item_func::eval_not_null_tables(NULL))
return 1;
not_null_tables_cache= (args[1]->not_null_tables() &
args[2]->not_null_tables());
return 0;
}
void
Item_func_if::fix_length_and_dec()
{
@ -3742,11 +3760,22 @@ bool Item_func_in::nulls_in_row()
bool
Item_func_in::fix_fields(THD *thd, Item **ref)
{
Item **arg, **arg_end;
if (Item_func_opt_neg::fix_fields(thd, ref))
return 1;
return 0;
}
bool
Item_func_in::eval_not_null_tables(uchar *opt_arg)
{
Item **arg, **arg_end;
if (Item_func_opt_neg::eval_not_null_tables(NULL))
return 1;
/* not_null_tables_cache == union(T1(e),union(T1(ei))) */
if (pred_level && negated)
return 0;
@ -4177,7 +4206,6 @@ Item_cond::fix_fields(THD *thd, Item **ref)
*/
while ((item=li++))
{
table_map tmp_table_map;
while (item->type() == Item::COND_ITEM &&
((Item_cond*) item)->functype() == functype() &&
!((Item_cond*) item)->list.is_empty())
@ -4199,11 +4227,12 @@ Item_cond::fix_fields(THD *thd, Item **ref)
and_tables_cache= (table_map) 0;
else
{
tmp_table_map= item->not_null_tables();
table_map tmp_table_map= item->not_null_tables();
not_null_tables_cache|= tmp_table_map;
and_tables_cache&= tmp_table_map;
const_item_cache= FALSE;
}
}
with_sum_func= with_sum_func || item->with_sum_func;
with_field= with_field || item->with_field;
with_subselect|= item->with_subselect;
@ -4218,6 +4247,28 @@ Item_cond::fix_fields(THD *thd, Item **ref)
}
bool
Item_cond::eval_not_null_tables(uchar *opt_arg)
{
Item *item;
List_iterator<Item> li(list);
and_tables_cache= ~(table_map) 0;
while ((item=li++))
{
table_map tmp_table_map;
if (item->const_item())
and_tables_cache= (table_map) 0;
else
{
tmp_table_map= item->not_null_tables();
not_null_tables_cache|= tmp_table_map;
and_tables_cache&= tmp_table_map;
}
}
return 0;
}
void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
List_iterator<Item> li(list);

View file

@ -637,6 +637,7 @@ public:
bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
uint decimal_precision() const { return 1; }
bool eval_not_null_tables(uchar *opt_arg);
};
@ -737,6 +738,7 @@ public:
void fix_length_and_dec();
uint decimal_precision() const;
const char *func_name() const { return "if"; }
bool eval_not_null_tables(uchar *opt_arg);
};
@ -1273,6 +1275,7 @@ public:
bool nulls_in_row();
bool is_bool_func() { return 1; }
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
bool eval_not_null_tables(uchar *opt_arg);
};
class cmp_item_row :public cmp_item
@ -1528,6 +1531,7 @@ public:
bool subst_argument_checker(uchar **arg) { return TRUE; }
Item *compile(Item_analyzer analyzer, uchar **arg_p,
Item_transformer transformer, uchar *arg_t);
bool eval_not_null_tables(uchar *opt_arg);
};

View file

@ -202,7 +202,6 @@ Item_func::fix_fields(THD *thd, Item **ref)
with_sum_func= with_sum_func || item->with_sum_func;
with_field= with_field || item->with_field;
used_tables_cache|= item->used_tables();
not_null_tables_cache|= item->not_null_tables();
const_item_cache&= item->const_item();
with_subselect|= item->with_subselect;
}
@ -231,6 +230,21 @@ Item_func::quick_fix_field()
}
bool
Item_func::eval_not_null_tables(uchar *opt_arg)
{
Item **arg,**arg_end;
if (arg_count)
{
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
not_null_tables_cache|= (*arg)->not_null_tables();
}
}
return FALSE;
}
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
Item **arg,**arg_end;
@ -3984,6 +3998,21 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
cached_result_type= args[0]->result_type();
if (thd->lex->current_select)
{
/*
When this function is used in a derived table/view force the derived
table to be materialized to preserve possible side-effect of setting a
user variable.
*/
SELECT_LEX_UNIT *unit= thd->lex->current_select->master_unit();
TABLE_LIST *derived;
for (derived= unit->derived;
derived;
derived= derived->select_lex->master_unit()->derived)
derived->set_materialized_derived();
}
return FALSE;
}

View file

@ -191,6 +191,7 @@ public:
Item_transformer transformer, uchar *arg_t);
void traverse_cond(Cond_traverser traverser,
void * arg, traverse_order order);
bool eval_not_null_tables(uchar *opt_arg);
// bool is_expensive_processor(uchar *arg);
// virtual bool is_expensive() { return 0; }
inline double fix_result(double value)
@ -1713,14 +1714,7 @@ public:
void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
bool check_vcol_func_processor(uchar *int_arg)
{
#if 0
DBUG_ENTER("Item_func_is_free_lock::check_vcol_func_processor");
DBUG_PRINT("info",
("check_vcol_func_processor returns TRUE: unsupported function"));
DBUG_RETURN(TRUE);
#else
return trace_unsupported_by_check_vcol_func_processor(func_name());
#endif
}
};

View file

@ -3204,6 +3204,9 @@ int subselect_uniquesubquery_engine::exec()
DBUG_RETURN(0);
}
if (!tab->preread_init_done && tab->preread_init())
DBUG_RETURN(1);
if (null_keypart)
DBUG_RETURN(scan_table());
@ -3336,7 +3339,7 @@ subselect_uniquesubquery_engine::~subselect_uniquesubquery_engine()
int subselect_indexsubquery_engine::exec()
{
DBUG_ENTER("subselect_indexsubquery_engine::exec");
DBUG_ENTER("subselect_indexsubquery_engine");
int error;
bool null_finding= 0;
TABLE *table= tab->table;
@ -3367,6 +3370,9 @@ int subselect_indexsubquery_engine::exec()
DBUG_RETURN(0);
}
if (!tab->preread_init_done && tab->preread_init())
DBUG_RETURN(1);
if (null_keypart)
DBUG_RETURN(scan_table());
@ -3468,10 +3474,13 @@ void subselect_uniquesubquery_engine::exclude()
}
table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
table_map subselect_engine::calc_const_tables(List<TABLE_LIST> &list)
{
table_map map= 0;
for (; table; table= table->next_leaf)
List_iterator<TABLE_LIST> ti(list);
TABLE_LIST *table;
//for (; table; table= table->next_leaf)
while ((table= ti++))
{
TABLE *tbl= table->table;
if (tbl && tbl->const_table)
@ -4060,7 +4069,7 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
result_sink->get_tmp_table_param()->materialized_subquery= true;
if (result_sink->create_result_table(thd, tmp_columns, TRUE,
tmp_create_options,
name, TRUE))
name, TRUE, TRUE))
DBUG_RETURN(TRUE);
tmp_table= result_sink->table;
@ -4218,6 +4227,7 @@ subselect_hash_sj_engine::make_unique_engine()
DBUG_RETURN(NULL);
tab->table= tmp_table;
tab->preread_init_done= FALSE;
tab->ref.tmp_table_index_lookup_init(thd, tmp_key, it, FALSE);
DBUG_RETURN(new subselect_uniquesubquery_engine(thd, tab, item,

View file

@ -621,6 +621,7 @@ public:
virtual bool may_be_null() { return maybe_null; };
virtual table_map upper_select_const_tables()= 0;
static table_map calc_const_tables(TABLE_LIST *);
static table_map calc_const_tables(List<TABLE_LIST> &list);
virtual void print(String *str, enum_query_type query_type)= 0;
virtual bool change_result(Item_subselect *si,
select_result_interceptor *result,

View file

@ -61,12 +61,15 @@ class Parser_state;
QT_ORDINARY -- ordinary SQL query.
QT_IS -- SQL query to be shown in INFORMATION_SCHEMA (in utf8 and without
character set introducers).
character set introducers).
QT_VIEW_INTERNAL -- view internal representation (like QT_ORDINARY except
ORDER BY clause)
*/
enum enum_query_type
{
QT_ORDINARY,
QT_IS
QT_IS,
QT_VIEW_INTERNAL
};
/* TODO convert all these three maps to Bitmap classes */
@ -515,7 +518,6 @@ protected:
#define OPTION_PROFILING (ULL(1) << 33)
/**
Maximum length of time zone name that we support
(Time zone name is char(64) in db). mysqlbinlog needs it.
@ -1408,11 +1410,9 @@ int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result);
bool mysql_union(THD *thd, LEX *lex, select_result *result,
SELECT_LEX_UNIT *unit, ulong setup_tables_done_option);
bool mysql_handle_derived(LEX *lex, bool (*processor)(THD *thd,
LEX *lex,
TABLE_LIST *table));
bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t);
bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t);
bool mysql_handle_derived(LEX *lex, uint phases);
bool mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases);
bool mysql_handle_list_of_derived(LEX *lex, TABLE_LIST *dt_list, uint phases);
bool check_table_file_presence(char *old_path, char *path,
const char *db,
const char *table_name,
@ -1426,6 +1426,11 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
bool make_copy_field,
uint convert_blob_length);
bool open_tmp_table(TABLE *table);
bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
ENGINE_COLUMNDEF *start_recinfo,
ENGINE_COLUMNDEF **recinfo,
ulonglong options);
void sp_prepare_create_field(THD *thd, Create_field *sql_field);
int prepare_create_field(Create_field *sql_field,
uint *blob_columns,
@ -1733,17 +1738,21 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
bool insert_fields(THD *thd, Name_resolution_context *context,
const char *db_name, const char *table_name,
List_iterator<Item> *it, bool any_privileges);
void make_leaves_list(List<TABLE_LIST> &list, TABLE_LIST *tables,
bool full_table_list, TABLE_LIST *boundary);
bool setup_tables(THD *thd, Name_resolution_context *context,
List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
TABLE_LIST **leaves, bool select_insert);
List<TABLE_LIST> &leaves, bool select_insert,
bool full_table_list);
bool setup_tables_and_check_access(THD *thd,
Name_resolution_context *context,
List<TABLE_LIST> *from_clause,
TABLE_LIST *tables,
TABLE_LIST **leaves,
List<TABLE_LIST> &leaves,
bool select_insert,
ulong want_access_first,
ulong want_access);
ulong want_access,
bool full_table_list);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num);
bool setup_fields(THD *thd, Item** ref_pointer_array,
@ -1762,7 +1771,7 @@ inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
thd->lex->select_lex.no_wrap_view_item= FALSE;
return res;
}
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
COND **conds);
void wrap_ident(THD *thd, Item **conds);
int setup_ftfuncs(SELECT_LEX* select);
@ -1785,7 +1794,8 @@ inline int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
/* simple open_and_lock_tables without derived handling for single table */
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
thr_lock_type lock_type);
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
uint dt_phases);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen);
int decide_logging_format(THD *thd, TABLE_LIST *tables);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
@ -1815,6 +1825,7 @@ void flush_tables();
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
char *make_default_log_name(char *buff,const char* log_ext);
char *make_once_alloced_filename(const char *basename, const char *ext);
void unfix_fields(List<Item> &items);
#ifdef WITH_PARTITION_STORAGE_ENGINE
uint fast_alter_partition_table(THD *thd, TABLE *table,
@ -2709,7 +2720,7 @@ Item * all_any_subquery_creator(Item *left_expr,
inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
{
table->used_fields= 0;
table->const_table= 0;
table_list->reset_const_table();
table->null_row= 0;
table->status= STATUS_NO_RECORD;
table->maybe_null= table_list->outer_join;
@ -2725,6 +2736,14 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr)
table->force_index_order= table->force_index_group= 0;
table->covering_keys= table->s->keys_for_keyread;
table->merge_keys.clear_all();
TABLE_LIST *orig= table_list->select_lex ?
table_list->select_lex->master_unit()->derived : 0;
if (!orig || !orig->is_merged_derived())
{
/* Tables merged from derived were set up already.*/
table->covering_keys= table->s->keys_for_keyread;
table->merge_keys.clear_all();
}
}

View file

@ -9497,7 +9497,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
SEL_ARG_RANGE_SEQ seq;
RANGE_SEQ_IF seq_if = {NULL, sel_arg_range_seq_init, sel_arg_range_seq_next, 0, 0};
handler *file= param->table->file;
ha_rows rows;
ha_rows rows= HA_POS_ERROR;
uint keynr= param->real_keynr[idx];
DBUG_ENTER("check_quick_select");
@ -9537,8 +9537,13 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
*mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
*bufsize= param->thd->variables.mrr_buff_size;
rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0,
bufsize, mrr_flags, cost);
/*
Skip materialized derived table/view result table from MRR check as
they aren't contain any data yet.
*/
if (param->table->pos_in_table_list->is_non_derived())
rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0,
bufsize, mrr_flags, cost);
if (rows != HA_POS_ERROR)
{
param->quick_rows[keynr]= rows;

View file

@ -183,8 +183,6 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred);
static bool convert_subq_to_jtbm(JOIN *parent_join,
Item_in_subselect *subq_pred, bool *remove);
static TABLE_LIST *alloc_join_nest(THD *thd);
static
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist);
static uint get_tmp_table_rec_length(List<Item> &items);
static double get_tmp_table_lookup_cost(THD *thd, double row_count,
uint row_size);
@ -344,9 +342,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!join->having && !select_lex->with_sum_func && // 4
thd->thd_marker.emb_on_expr_nest && // 5
select_lex->outer_select()->join && // 6
parent_unit->first_select()->leaf_tables && // 7
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->in_strategy && // 8
select_lex->outer_select()->leaf_tables && // 9
select_lex->outer_select()->leaf_tables.elements && // 9
!((join->select_options | // 10
select_lex->outer_select()->join->select_options) // 10
& SELECT_STRAIGHT_JOIN)) // 10
@ -412,9 +410,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
*/
if (optimizer_flag(thd, OPTIMIZER_SWITCH_MATERIALIZATION) && // 0
!select_lex->is_part_of_union() && // 1
parent_unit->first_select()->leaf_tables && // 2
parent_unit->first_select()->leaf_tables.elements && // 2
thd->lex->sql_command == SQLCOM_SELECT && // *
select_lex->outer_select()->leaf_tables && // 2A
select_lex->outer_select()->leaf_tables.elements && // 2A
subquery_types_allow_materialization(in_subs) &&
(in_subs->is_top_level_item() || //3
optimizer_flag(thd,
@ -422,7 +420,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
optimizer_flag(thd,
OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN)) && //3
!in_subs->is_correlated) //4
{
{
in_subs->in_strategy|= SUBS_MATERIALIZATION;
/*
@ -736,11 +734,25 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
Item_in_subselect **in_subq;
Item_in_subselect **in_subq_end;
THD *thd= join->thd;
List_iterator<TABLE_LIST> ti(join->select_lex->leaf_tables);
DBUG_ENTER("convert_join_subqueries_to_semijoins");
if (join->sj_subselects.elements() == 0)
DBUG_RETURN(FALSE);
for (in_subq= join->sj_subselects.front(),
in_subq_end= join->sj_subselects.back();
in_subq != in_subq_end;
in_subq++)
{
SELECT_LEX *subq_sel= (*in_subq)->get_select_lex();
if (subq_sel->handle_derived(thd->lex, DT_OPTIMIZE))
DBUG_RETURN(1);
if (subq_sel->handle_derived(thd->lex, DT_MERGE))
DBUG_RETURN(TRUE);
subq_sel->update_used_tables();
}
/* First, convert child join's subqueries. We proceed bottom-up here */
for (in_subq= join->sj_subselects.front(),
in_subq_end= join->sj_subselects.back();
@ -1149,7 +1161,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
st_select_lex *subq_lex= subq_pred->unit->first_select();
nested_join->join_list.empty();
List_iterator_fast<TABLE_LIST> li(subq_lex->top_join_list);
TABLE_LIST *tl, *last_leaf;
TABLE_LIST *tl;
while ((tl= li++))
{
tl->embedding= sj_nest;
@ -1164,17 +1176,15 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
NOTE: We actually insert them at the front! That's because the order is
reversed in this list.
*/
for (tl= parent_lex->leaf_tables; tl->next_leaf; tl= tl->next_leaf) ;
tl->next_leaf= subq_lex->leaf_tables;
last_leaf= tl;
parent_lex->leaf_tables.concat(&subq_lex->leaf_tables);
/*
Same as above for next_local chain
(a theory: a next_local chain always starts with ::leaf_tables
because view's tables are inserted after the view)
*/
for (tl= parent_lex->leaf_tables; tl->next_local; tl= tl->next_local) ;
tl->next_local= subq_lex->leaf_tables;
for (tl= parent_lex->leaf_tables.head(); tl->next_local; tl= tl->next_local) ;
tl->next_local= subq_lex->leaf_tables.head();
/* A theory: no need to re-connect the next_global chain */
@ -1187,7 +1197,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
/* n. Adjust the parent_join->table_count counter */
uint table_no= parent_join->table_count;
/* n. Walk through child's tables and adjust table->map */
for (tl= subq_lex->leaf_tables; tl; tl= tl->next_leaf, table_no++)
List_iterator_fast<TABLE_LIST> si(subq_lex->leaf_tables);
while ((tl= si++))
{
tl->table->tablenr= table_no;
tl->table->map= ((table_map)1) << table_no;
@ -1197,6 +1208,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
emb && emb->select_lex == old_sl;
emb= emb->embedding)
emb->select_lex= parent_join->select_lex;
table_no++;
}
parent_join->table_count += subq_lex->join->table_count;
@ -1289,7 +1301,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
*/
save_lex= thd->lex->current_select;
thd->lex->current_select=parent_join->select_lex;
parent_join->conds->fix_fields(parent_join->thd, &parent_join->conds);
if (!parent_join->conds->fixed)
parent_join->conds->fix_fields(parent_join->thd, &parent_join->conds);
thd->lex->current_select=save_lex;
parent_join->select_lex->where= parent_join->conds;
}
@ -1381,16 +1394,14 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
Inject the jtbm table into TABLE_LIST::next_leaf list, so that
make_join_statistics() and co. can find it.
*/
for (tl= parent_lex->leaf_tables; tl->next_leaf; tl= tl->next_leaf)
{}
tl->next_leaf= jtbm;
parent_lex->leaf_tables.push_back(jtbm);
/*
Same as above for TABLE_LIST::next_local chain
(a theory: a next_local chain always starts with ::leaf_tables
because view's tables are inserted after the view)
*/
for (tl= parent_lex->leaf_tables; tl->next_local; tl= tl->next_local)
for (tl= parent_lex->leaf_tables.head(); tl->next_local; tl= tl->next_local)
{}
tl->next_local= jtbm;
@ -1451,7 +1462,6 @@ static TABLE_LIST *alloc_join_nest(THD *thd)
}
static
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist)
{
List_iterator<TABLE_LIST> it(*tlist);
@ -2033,6 +2043,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables,
TABLE_LIST *emb_sj_nest;
POSITION *pos= join->positions + idx;
remaining_tables &= ~new_join_tab->table->map;
bool disable_jbuf= join->thd->variables.join_cache_level == 0;
pos->prefix_cost.convert_from_cost(*current_read_time);
pos->prefix_record_count= *current_record_count;
@ -2200,7 +2211,8 @@ void advance_sj_state(JOIN *join, table_map remaining_tables,
optimize_wo_join_buffering(join, pos->first_loosescan_table, idx,
remaining_tables,
TRUE, //first_alt
pos->first_loosescan_table + n_tables,
disable_jbuf ? join->table_count :
pos->first_loosescan_table + n_tables,
current_record_count,
current_read_time);
/*
@ -2339,8 +2351,8 @@ void advance_sj_state(JOIN *join, table_map remaining_tables,
/* Need to re-run best-access-path as we prefix_rec_count has changed */
for (i= first_tab + mat_info->tables; i <= idx; i++)
{
best_access_path(join, join->positions[i].table, rem_tables, i, FALSE,
prefix_rec_count, &curpos, &dummy);
best_access_path(join, join->positions[i].table, rem_tables, i,
disable_jbuf, prefix_rec_count, &curpos, &dummy);
prefix_rec_count *= curpos.records_read;
prefix_cost += curpos.read_time;
}
@ -2699,8 +2711,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
join->cur_sj_inner_tables= 0;
for (i= first + sjm->tables; i <= tablenr; i++)
{
best_access_path(join, join->best_positions[i].table, rem_tables, i, FALSE,
prefix_rec_count, join->best_positions + i, &dummy);
best_access_path(join, join->best_positions[i].table, rem_tables, i,
FALSE, prefix_rec_count,
join->best_positions + i, &dummy);
prefix_rec_count *= join->best_positions[i].records_read;
rem_tables &= ~join->best_positions[i].table->table->map;
}

View file

@ -74,10 +74,12 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
# Multiplication of number of rows in all tables
*/
static ulonglong get_exact_record_count(TABLE_LIST *tables)
static ulonglong get_exact_record_count(List<TABLE_LIST> &tables)
{
ulonglong count= 1;
for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf)
TABLE_LIST *tl;
List_iterator<TABLE_LIST> ti(tables);
while ((tl= ti++))
{
ha_rows tmp= tl->table->file->records();
if ((tmp == HA_POS_ERROR))
@ -234,9 +236,11 @@ static int get_index_max_value(TABLE *table, TABLE_REF *ref, uint range_fl)
*/
int opt_sum_query(THD *thd,
TABLE_LIST *tables, List<Item> &all_fields, COND *conds)
List<TABLE_LIST> &tables, List<Item> &all_fields, COND *conds)
{
List_iterator_fast<Item> it(all_fields);
List_iterator<TABLE_LIST> ti(tables);
TABLE_LIST *tl;
int const_result= 1;
bool recalc_const_item= 0;
ulonglong count= 1;
@ -244,7 +248,7 @@ int opt_sum_query(THD *thd,
table_map removed_tables= 0, outer_tables= 0, used_tables= 0;
table_map where_tables= 0;
Item *item;
int error;
int error= 0;
DBUG_ENTER("opt_sum_query");
if (conds)
@ -254,7 +258,7 @@ int opt_sum_query(THD *thd,
Analyze outer join dependencies, and, if possible, compute the number
of returned rows.
*/
for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf)
while ((tl= ti++))
{
TABLE_LIST *embedded;
for (embedded= tl ; embedded; embedded= embedded->embedding)
@ -295,6 +299,14 @@ int opt_sum_query(THD *thd,
is_exact_count= FALSE;
count= 1; // ensure count != 0
}
else if (tl->is_materialized_derived())
{
/*
Can't remove a derived table as it's number of rows is just an
estimate.
*/
DBUG_RETURN(0);
}
else
{
error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);

View file

@ -299,7 +299,8 @@ void end_read_record(READ_RECORD *info)
if (info->table)
{
filesort_free_buffers(info->table,0);
(void) info->file->extra(HA_EXTRA_NO_CACHE);
if (info->table->created)
(void) info->file->extra(HA_EXTRA_NO_CACHE);
if (info->read_record != rr_quick) // otherwise quick_range does it
(void) info->file->ha_index_or_rnd_end();
info->table=0;

View file

@ -2835,6 +2835,9 @@ int sp_instr::exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
result= -1;
else
result= 0;
/* Prepare all derived tables/views to catch possible errors. */
if (!result)
result= mysql_handle_derived(thd->lex, DT_PREPARE) ? -1 : 0;
return result;
}

View file

@ -3058,7 +3058,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
class LEX_COLUMN *column;
List_iterator <LEX_COLUMN> column_iter(columns);
if (open_and_lock_tables(thd, table_list))
if (open_and_lock_tables(thd, table_list) ||
mysql_handle_derived(thd->lex, DT_PREPARE))
DBUG_RETURN(TRUE);
while ((column = column_iter++))

View file

@ -3025,6 +3025,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
*/
DBUG_ASSERT(table->file->pushed_cond == NULL);
table->reginfo.impossible_range= 0;
table->created= TRUE;
/* Catch wrong handling of the auto_increment_field_not_null. */
DBUG_ASSERT(!table->auto_increment_field_not_null);
table->auto_increment_field_not_null= FALSE;
@ -5122,9 +5123,10 @@ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived)
close_tables_for_reopen(thd, &tables);
}
if (derived &&
(mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
(thd->fill_derived_tables() &&
mysql_handle_derived(thd->lex, &mysql_derived_filling))))
(mysql_handle_derived(thd->lex, DT_INIT)))
DBUG_RETURN(TRUE); /* purecov: inspected */
if (thd->prepare_derived_at_open && derived &&
(mysql_handle_derived(thd->lex, DT_PREPARE)))
DBUG_RETURN(TRUE); /* purecov: inspected */
DBUG_RETURN(0);
}
@ -5140,6 +5142,7 @@ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived)
flags - bitmap of flags to modify how the tables will be open:
MYSQL_LOCK_IGNORE_FLUSH - open table even if someone has
done a flush on it.
dt_phases - set of flags to pass to the mysql_handle_derived
RETURN
FALSE - ok
@ -5150,13 +5153,14 @@ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived)
data from the tables.
*/
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags)
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
uint dt_phases)
{
uint counter;
DBUG_ENTER("open_normal_and_derived_tables");
DBUG_ASSERT(!thd->fill_derived_tables());
if (open_tables(thd, &tables, &counter, flags) ||
mysql_handle_derived(thd->lex, &mysql_derived_prepare))
mysql_handle_derived(thd->lex, dt_phases))
DBUG_RETURN(TRUE); /* purecov: inspected */
DBUG_RETURN(0);
}
@ -5828,9 +5832,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
Field_iterator_view field_it;
field_it.set(table_list);
Query_arena *arena= 0, backup;
DBUG_ASSERT(table_list->schema_table_reformed ||
(ref != 0 && table_list->view != 0));
for (; !field_it.end_of_fields(); field_it.next())
{
if (!my_strcasecmp(system_charset_info, field_it.name(), name))
@ -5849,6 +5851,8 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
if (!item)
DBUG_RETURN(0);
if (!ref)
DBUG_RETURN((Field*) view_ref_found);
/*
*ref != NULL means that *ref contains the item that we need to
replace. If the item was aliased by the user, set the alias to
@ -6253,6 +6257,8 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
Field *field_to_set= NULL;
if (fld == view_ref_found)
{
if (!ref)
DBUG_RETURN(fld);
Item *it= (*ref)->real_item();
if (it->type() == Item::FIELD_ITEM)
field_to_set= ((Item_field*)it)->field;
@ -6260,6 +6266,8 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
{
if (thd->mark_used_columns == MARK_COLUMNS_READ)
it->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
else
it->walk(&Item::register_field_in_write_map, 1, (uchar *) 0);
}
}
else
@ -6399,8 +6407,11 @@ find_field_in_tables(THD *thd, Item_ident *item,
find_field_in_table even in the case of information schema tables
when table_ref->field_translation != NULL.
*/
if (table_ref->table && !table_ref->view)
if (table_ref->table && !table_ref->view &&
(!table_ref->is_merged_derived() ||
(!table_ref->is_multitable() && table_ref->merged_for_insert)))
{
found= find_field_in_table(thd, table_ref->table, name, length,
TRUE, &(item->cached_field_index));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@ -6425,7 +6436,8 @@ find_field_in_tables(THD *thd, Item_ident *item,
Only views fields should be marked as dependent, not an underlying
fields.
*/
if (!table_ref->belong_to_view)
if (!table_ref->belong_to_view &&
!table_ref->belong_to_derived)
{
SELECT_LEX *current_sel= thd->lex->current_select;
SELECT_LEX *last_select= table_ref->select_lex;
@ -7020,6 +7032,10 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
*/
if (nj_col_2 && (!using_fields ||is_using_column_1))
{
/*
Create non-fixed fully qualified field and let fix_fields to
resolve it.
*/
Item *item_1= nj_col_1->create_item(thd);
Item *item_2= nj_col_2->create_item(thd);
Field *field_1= nj_col_1->field();
@ -7468,7 +7484,11 @@ static bool setup_natural_join_row_types(THD *thd,
for (left_neighbor= table_ref_it++; left_neighbor ; )
{
table_ref= left_neighbor;
left_neighbor= table_ref_it++;
do
{
left_neighbor= table_ref_it++;
}
while (left_neighbor && left_neighbor->sj_subq_pred);
/*
Do not redo work if already done:
1) for stored procedures,
@ -7683,27 +7703,36 @@ bool setup_fields(THD *thd, Item **ref_pointer_array,
make_leaves_list()
list pointer to pointer on list first element
tables table list
full_table_list whether to include tables from mergeable derived table/view.
we need them for checks for INSERT/UPDATE statements only.
RETURN pointer on pointer to next_leaf of last element
*/
TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
void make_leaves_list(List<TABLE_LIST> &list, TABLE_LIST *tables,
bool full_table_list, TABLE_LIST *boundary)
{
for (TABLE_LIST *table= tables; table; table= table->next_local)
{
if (table->merge_underlying_list)
if (table == boundary)
full_table_list= !full_table_list;
if (full_table_list && table->is_merged_derived())
{
DBUG_ASSERT(table->view &&
table->effective_algorithm == VIEW_ALGORITHM_MERGE);
list= make_leaves_list(list, table->merge_underlying_list);
SELECT_LEX *select_lex= table->get_single_select();
/*
It's safe to use select_lex->leaf_tables because all derived
tables/views were already prepared and has their leaf_tables
set properly.
*/
make_leaves_list(list, select_lex->get_table_list(),
full_table_list, boundary);
}
else
{
*list= table;
list= &table->next_leaf;
list.push_back(table);
}
}
return list;
}
/*
@ -7718,6 +7747,7 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
leaves List of join table leaves list (select_lex->leaf_tables)
refresh It is onle refresh for subquery
select_insert It is SELECT ... INSERT command
full_table_list a parameter to pass to the make_leaves_list function
NOTE
Check also that the 'used keys' and 'ignored keys' exists and set up the
@ -7736,9 +7766,13 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
bool setup_tables(THD *thd, Name_resolution_context *context,
List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
TABLE_LIST **leaves, bool select_insert)
List<TABLE_LIST> &leaves, bool select_insert,
bool full_table_list)
{
uint tablenr= 0;
List_iterator<TABLE_LIST> ti(leaves);
TABLE_LIST *table_list;
DBUG_ENTER("setup_tables");
DBUG_ASSERT ((select_insert && !tables->next_name_resolution_table) || !tables ||
@ -7750,49 +7784,66 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
TABLE_LIST *first_select_table= (select_insert ?
tables->next_local:
0);
if (!(*leaves))
make_leaves_list(leaves, tables);
TABLE_LIST *table_list;
for (table_list= *leaves;
table_list;
table_list= table_list->next_leaf, tablenr++)
SELECT_LEX *select_lex= select_insert ? &thd->lex->select_lex :
thd->lex->current_select;
if (select_lex->first_cond_optimization)
{
TABLE *table= table_list->table;
if (first_select_table &&
table_list->top_table() == first_select_table)
{
/* new counting for SELECT of INSERT ... SELECT command */
first_select_table= 0;
tablenr= 0;
}
if (table_list->jtbm_subselect)
{
table_list->jtbm_table_no= tablenr;
}
else
leaves.empty();
select_lex->leaf_tables_exec.empty();
make_leaves_list(leaves, tables, full_table_list, first_select_table);
while ((table_list= ti++))
{
TABLE *table= table_list->table;
table->pos_in_table_list= table_list;
setup_table_map(table, table_list, tablenr);
if (first_select_table &&
table_list->top_table() == first_select_table)
{
/* new counting for SELECT of INSERT ... SELECT command */
first_select_table= 0;
thd->lex->select_lex.insert_tables= tablenr;
tablenr= 0;
}
if(table_list->jtbm_subselect)
{
table_list->jtbm_table_no= tablenr;
}
else
{
table->pos_in_table_list= table_list;
setup_table_map(table, table_list, tablenr);
if (table_list->process_index_hints(table))
DBUG_RETURN(1);
if (table_list->process_index_hints(table))
DBUG_RETURN(1);
}
tablenr++;
}
if (tablenr > MAX_TABLES)
{
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
DBUG_RETURN(1);
}
}
if (tablenr > MAX_TABLES)
{
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
DBUG_RETURN(1);
}
else
{
List_iterator_fast <TABLE_LIST> ti(select_lex->leaf_tables_exec);
select_lex->leaf_tables.empty();
while ((table_list= ti++))
{
table_list->table->tablenr= table_list->tablenr_exec;
table_list->table->map= table_list->map_exec;
table_list->table->pos_in_table_list= table_list;
select_lex->leaf_tables.push_back(table_list);
}
}
for (table_list= tables;
table_list;
table_list= table_list->next_local)
{
if (table_list->merge_underlying_list)
{
DBUG_ASSERT(table_list->view &&
table_list->effective_algorithm == VIEW_ALGORITHM_MERGE);
DBUG_ASSERT(table_list->is_merged_derived());
Query_arena *arena= thd->stmt_arena, backup;
bool res;
if (arena->is_conventional())
@ -7830,7 +7881,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
prepare tables and check access for the view tables
SYNOPSIS
setup_tables_and_check_view_access()
setup_tables_and_check_access()
thd Thread handler
context name resolution contest to setup table list there
from_clause Top-level list of table references in the FROM clause
@ -7840,6 +7891,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
refresh It is onle refresh for subquery
select_insert It is SELECT ... INSERT command
want_access what access is needed
full_table_list a parameter to pass to the make_leaves_list function
NOTE
a wrapper for check_tables that will also check the resulting
@ -7853,27 +7905,26 @@ bool setup_tables_and_check_access(THD *thd,
Name_resolution_context *context,
List<TABLE_LIST> *from_clause,
TABLE_LIST *tables,
TABLE_LIST **leaves,
List<TABLE_LIST> &leaves,
bool select_insert,
ulong want_access_first,
ulong want_access)
ulong want_access,
bool full_table_list)
{
TABLE_LIST *leaves_tmp= NULL;
bool first_table= true;
DBUG_ENTER("setup_tables_and_check_access");
if (setup_tables(thd, context, from_clause, tables,
&leaves_tmp, select_insert))
leaves, select_insert, full_table_list))
DBUG_RETURN(TRUE);
if (leaves)
*leaves= leaves_tmp;
for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf)
List_iterator<TABLE_LIST> ti(leaves);
TABLE_LIST *table_list;
while((table_list= ti++))
{
if (leaves_tmp->belong_to_view &&
if (table_list->belong_to_view && !table_list->view &&
check_single_table_access(thd, first_table ? want_access_first :
want_access, leaves_tmp, FALSE))
want_access, table_list, FALSE))
{
tables->hide_view_error(thd);
DBUG_RETURN(TRUE);
@ -8016,8 +8067,10 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
information_schema table, or a nested table reference. See the comment
for TABLE_LIST.
*/
if (!((table && !tables->view && (table->grant.privilege & SELECT_ACL)) ||
(tables->view && (tables->grant.privilege & SELECT_ACL))) &&
if (!((table && tables->is_non_derived() &&
(table->grant.privilege & SELECT_ACL)) ||
((!tables->is_non_derived() &&
(tables->grant.privilege & SELECT_ACL)))) &&
!any_privileges)
{
field_iterator.set(tables);
@ -8047,7 +8100,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
if (!(item= field_iterator.create_item(thd)))
DBUG_RETURN(TRUE);
DBUG_ASSERT(item->fixed);
// DBUG_ASSERT(item->fixed);
/* cache the table for the Item_fields inserted by expanding stars */
if (item->type() == Item::FIELD_ITEM && tables->cacheable_table)
((Item_field *)item)->cached_table= tables;
@ -8200,13 +8253,14 @@ void wrap_ident(THD *thd, Item **conds)
FALSE if all is OK
*/
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
COND **conds)
{
SELECT_LEX *select_lex= thd->lex->current_select;
Query_arena *arena= thd->stmt_arena, backup;
TABLE_LIST *table= NULL; // For HP compilers
TABLE_LIST *save_emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
List_iterator<TABLE_LIST> ti(leaves);
/*
it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
which belong to LEX, i.e. most up SELECT) will be updated by
@ -8218,9 +8272,15 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
bool it_is_update= (select_lex == &thd->lex->select_lex) &&
thd->lex->which_check_option_applicable();
bool save_is_item_list_lookup= select_lex->is_item_list_lookup;
select_lex->is_item_list_lookup= 0;
TABLE_LIST *derived= select_lex->master_unit()->derived;
DBUG_ENTER("setup_conds");
/* Do not fix conditions for the derived tables that have been merged */
if (derived && derived->merged)
DBUG_RETURN(0);
select_lex->is_item_list_lookup= 0;
if (select_lex->conds_processed_with_permanent_arena ||
arena->is_conventional())
arena= 0; // For easier test
@ -8233,7 +8293,10 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
for (table= tables; table; table= table->next_local)
{
if (table->prepare_where(thd, conds, FALSE))
if (select_lex == &thd->lex->select_lex &&
select_lex->first_cond_optimization &&
table->merged_for_insert &&
table->prepare_where(thd, conds, FALSE))
goto err_no_arena;
}
@ -8249,7 +8312,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
Wrap alone field in WHERE clause in case it will be outer field of subquery
which need persistent pointer on it, but conds could be changed by optimizer
*/
if ((*conds)->type() == Item::FIELD_ITEM)
if ((*conds)->type() == Item::FIELD_ITEM && !derived)
wrap_ident(thd, conds);
if ((!(*conds)->fixed && (*conds)->fix_fields(thd, conds)) ||
(*conds)->check_cols(1))
@ -8261,7 +8324,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
Apply fix_fields() to all ON clauses at all levels of nesting,
including the ones inside view definitions.
*/
for (table= leaves; table; table= table->next_leaf)
while ((table= ti++))
{
TABLE_LIST *embedded; /* The table at the current level of nesting. */
TABLE_LIST *embedding= table; /* The parent nested table reference. */
@ -9455,6 +9518,27 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup)
}
/**
@brief
Remove 'fixed' flag from items in a list
@param items list of items to un-fix
@details
This function sets to 0 the 'fixed' flag for items in the 'items' list.
It's needed to force correct marking of views' fields for INSERT/UPDATE
statements.
*/
void unfix_fields(List<Item> &fields)
{
List_iterator<Item> li(fields);
Item *item;
while ((item= li++))
item->fixed= 0;
}
/**
Check result of dynamic column function and issue error if it is needed

View file

@ -91,6 +91,10 @@ public:
DBUG_ASSERT(sizeof(buffer) >= 4);
return (ulonglong) uint4korr(buffer);
}
uint bits_set()
{
return bitmap_bits_set(&map);
}
};
/* An iterator to quickly walk over bits in unlonglong bitmap. */
@ -169,5 +173,16 @@ public:
public:
Iterator(Bitmap<64> &bmp) : Table_map_iterator(bmp.map) {}
};
uint bits_set()
{
//TODO: use my_count_bits()
uint res= 0, i= 0;
for (; i < 64 ; i++)
{
if (map & ((ulonglong)1<<i))
res++;
}
return res;
}
};

View file

@ -3853,16 +3853,17 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
}
else
{
DBUG_PRINT("qcache", ("table: %s db: %s type: %u",
tables_used->table->s->table_name.str,
tables_used->table->s->db.str,
tables_used->table->s->db_type()->db_type));
if (tables_used->derived)
{
DBUG_PRINT("qcache", ("table: %s", tables_used->alias));
table_count--;
DBUG_PRINT("qcache", ("derived table skipped"));
continue;
}
DBUG_PRINT("qcache", ("table: %s db: %s type: %u",
tables_used->table->s->table_name.str,
tables_used->table->s->db.str,
tables_used->table->s->db_type()->db_type));
*tables_type|= tables_used->table->file->table_cache_type();
/*

View file

@ -813,6 +813,7 @@ THD::THD()
m_binlog_invoker= FALSE;
memset(&invoker_user, 0, sizeof(invoker_user));
memset(&invoker_host, 0, sizeof(invoker_host));
prepare_derived_at_open= FALSE;
}
@ -3047,7 +3048,8 @@ bool
select_materialize_with_stats::
create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *table_alias, bool bit_fields_as_long)
const char *table_alias, bool bit_fields_as_long,
bool create_table)
{
DBUG_ASSERT(table == 0);
tmp_table_param.field_count= column_types->elements;

View file

@ -1568,6 +1568,9 @@ public:
*/
TABLE_LIST *emb_on_expr_nest;
} thd_marker;
bool prepare_derived_at_open;
#ifndef MYSQL_CLIENT
int binlog_setup_trx_data();
@ -3056,13 +3059,14 @@ public:
class select_union :public select_result_interceptor
{
protected:
public:
TMP_TABLE_PARAM tmp_table_param;
int write_err; /* Error code from the last send_data->ha_write_row call. */
public:
TABLE *table;
ha_rows records;
select_union() :write_err(0),table(0) { tmp_table_param.init(); }
select_union() :write_err(0), table(0), records(0) { tmp_table_param.init(); }
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
int send_data(List<Item> &items);
bool send_eof();
@ -3070,7 +3074,9 @@ public:
void cleanup();
virtual bool create_result_table(THD *thd, List<Item> *column_types,
bool is_distinct, ulonglong options,
const char *alias, bool bit_fields_as_long);
const char *alias,
bool bit_fields_as_long,
bool create_table);
TMP_TABLE_PARAM *get_tmp_table_param() { return &tmp_table_param; }
};
@ -3136,9 +3142,11 @@ protected:
public:
select_materialize_with_stats() { tmp_table_param.init(); }
virtual bool create_result_table(THD *thd, List<Item> *column_types,
bool is_distinct, ulonglong options,
const char *alias, bool bit_fields_as_long);
bool create_result_table(THD *thd, List<Item> *column_types,
bool is_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long,
bool create_table);
bool init_result_table(ulonglong select_options);
int send_data(List<Item> &items);
void cleanup();
@ -3446,7 +3454,7 @@ public:
class multi_update :public select_result_interceptor
{
TABLE_LIST *all_tables; /* query/update command tables */
TABLE_LIST *leaves; /* list of leves of join table tree */
List<TABLE_LIST> *leaves; /* list of leves of join table tree */
TABLE_LIST *update_tables, *table_being_updated;
TABLE **tmp_tables, *main_table, *table_to_update;
TMP_TABLE_PARAM *tmp_table_param;
@ -3472,7 +3480,7 @@ class multi_update :public select_result_interceptor
bool error_handled;
public:
multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list,
multi_update(TABLE_LIST *ut, List<TABLE_LIST> *leaves_list,
List<Item> *fields, List<Item> *values,
enum_duplicates handle_duplicates, bool ignore);
~multi_update();

View file

@ -722,8 +722,8 @@ bool Select_materialize::send_fields(List<Item> &list, uint flags)
DBUG_ASSERT(table == 0);
if (create_result_table(unit->thd, unit->get_unit_column_types(),
FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, "",
FALSE))
return TRUE;
FALSE, TRUE))
return TRUE;
materialized_cursor= new (&table->mem_root)
Materialized_cursor(result, table);

View file

@ -60,10 +60,20 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(TRUE);
if (!(table= table_list->table))
if (mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE))
DBUG_RETURN(TRUE);
if (!table_list->updatable)
{
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
DBUG_RETURN(TRUE);
}
if (!(table= table_list->table) || !table->created)
{
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(TRUE);
}
thd_proc_info(thd, "init");
@ -72,6 +82,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (mysql_prepare_delete(thd, table_list, &conds))
DBUG_RETURN(TRUE);
if (thd->lex->current_select->first_cond_optimization)
{
thd->lex->current_select->save_leaf_tables(thd);
thd->lex->current_select->first_cond_optimization= 0;
}
/* check ORDER BY even if it can be ignored */
if (order && order->elements)
{
@ -405,6 +420,12 @@ cleanup:
query_cache_invalidate3(thd, table_list, 1);
}
if (thd->lex->current_select->first_cond_optimization)
{
thd->lex->current_select->save_leaf_tables(thd);
thd->lex->current_select->first_cond_optimization= 0;
}
delete select;
transactional_table= table->file->has_transactions();
@ -506,8 +527,8 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
table_list,
&select_lex->leaf_tables, FALSE,
DELETE_ACL, SELECT_ACL) ||
select_lex->leaf_tables, FALSE,
DELETE_ACL, SELECT_ACL, TRUE) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
setup_ftfuncs(select_lex))
DBUG_RETURN(TRUE);
@ -565,6 +586,11 @@ int mysql_multi_delete_prepare(THD *thd)
TABLE_LIST *target_tbl;
DBUG_ENTER("mysql_multi_delete_prepare");
TABLE_LIST *tables= lex->query_tables;
if (mysql_handle_derived(lex, DT_INIT) ||
mysql_handle_list_of_derived(lex, tables, DT_MERGE_FOR_INSERT) ||
mysql_handle_list_of_derived(lex, tables, DT_PREPARE))
DBUG_RETURN(TRUE);
/*
setup_tables() need for VIEWs. JOIN::prepare() will not do it second
time.
@ -574,8 +600,8 @@ int mysql_multi_delete_prepare(THD *thd)
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
lex->query_tables,
&lex->select_lex.leaf_tables, FALSE,
DELETE_ACL, SELECT_ACL))
lex->select_lex.leaf_tables, FALSE,
DELETE_ACL, SELECT_ACL, TRUE))
DBUG_RETURN(TRUE);
@ -589,16 +615,13 @@ int mysql_multi_delete_prepare(THD *thd)
target_tbl;
target_tbl= target_tbl->next_local)
{
if (!(target_tbl->table= target_tbl->correspondent_table->table))
{
DBUG_ASSERT(target_tbl->correspondent_table->view &&
target_tbl->correspondent_table->merge_underlying_list &&
target_tbl->correspondent_table->merge_underlying_list->
next_local);
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
target_tbl->correspondent_table->view_db.str,
target_tbl->correspondent_table->view_name.str);
DBUG_RETURN(TRUE);
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
target_tbl->correspondent_table->view_db.str,
target_tbl->correspondent_table->view_name.str);
DBUG_RETURN(TRUE);
}
if (!target_tbl->correspondent_table->updatable ||
@ -648,6 +671,12 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
unit= u;
do_delete= 1;
thd_proc_info(thd, "deleting from main table");
SELECT_LEX *select_lex= u->first_select();
if (select_lex->first_cond_optimization)
{
if (select_lex->handle_derived(thd->lex, DT_MERGE))
DBUG_RETURN(TRUE);
}
DBUG_RETURN(0);
}

File diff suppressed because it is too large Load diff

View file

@ -109,7 +109,8 @@ void Expression_cache_tmptable::init()
~(OPTION_BIG_TABLES |
TMP_TABLE_FORCE_MYISAM)),
HA_POS_ERROR,
(char *)"subquery-cache-table")))
(char *)"subquery-cache-table",
TRUE)))
{
DBUG_PRINT("error", ("create_tmp_table failed, caching switched off"));
DBUG_VOID_RETURN;

View file

@ -637,7 +637,7 @@ bool mysqld_help(THD *thd, const char *mask)
Protocol *protocol= thd->protocol;
SQL_SELECT *select;
st_find_field used_fields[array_elements(init_used_fields)];
TABLE_LIST *leaves= 0;
List<TABLE_LIST> leaves;
TABLE_LIST tables[4];
List<String> topics_list, categories_list, subcategories_list;
String name, description, example;
@ -676,7 +676,7 @@ bool mysqld_help(THD *thd, const char *mask)
thd->lex->select_lex.context.first_name_resolution_table= &tables[0];
if (setup_tables(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
tables, &leaves, FALSE))
tables, leaves, FALSE, FALSE))
goto error;
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))

View file

@ -115,7 +115,7 @@ bool check_view_single_update(List<Item> &fields, List<Item> *values,
{
it.init(*values);
while ((item= it++))
tables|= item->used_tables();
tables|= item->view_used_tables(view);
}
/* Convert to real table bits */
@ -131,6 +131,11 @@ bool check_view_single_update(List<Item> &fields, List<Item> *values,
if (view->check_single_table(&tbl, tables, view) || tbl == 0)
goto error;
/*
A buffer for the insert values was allocated for the merged view.
Use it.
*/
//tbl->table->insert_values= view->table->insert_values;
view->table= tbl->table;
*map= tables;
@ -234,6 +239,10 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
*/
table_list->next_local= 0;
context->resolve_in_table_list_only(table_list);
/* 'Unfix' fields to allow correct marking by the setup_fields function. */
if (table_list->is_view())
unfix_fields(fields);
res= setup_fields(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0);
/* Restore the current context. */
@ -243,7 +252,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
if (res)
return -1;
if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
if (table_list->is_view() && table_list->is_merged_derived())
{
if (check_view_single_update(fields,
fields_and_values_from_different_maps ?
@ -332,7 +341,8 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
if (setup_fields(thd, 0, update_fields, MARK_COLUMNS_WRITE, 0, 0))
return -1;
if (insert_table_list->effective_algorithm == VIEW_ALGORITHM_MERGE &&
if (insert_table_list->is_view() &&
insert_table_list->is_merged_derived() &&
check_view_single_update(update_fields, &update_values,
insert_table_list, map))
return -1;
@ -631,6 +641,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
table_list->table_name);
DBUG_RETURN(TRUE);
}
/*
mark the table_list as a target for insert, to skip the DT/view prepare phase
for correct access rights checks
TODO: remove this hack
*/
table_list->skip_prepare_derived= TRUE;
if (table_list->lock_type == TL_WRITE_DELAYED)
{
@ -642,6 +658,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(TRUE);
}
lock_type= table_list->lock_type;
thd_proc_info(thd, "init");
@ -1005,6 +1022,12 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
::my_ok(thd, (ulong) thd->row_count_func, id, buff);
}
thd->abort_on_warning= 0;
if (thd->lex->current_select->first_cond_optimization)
{
thd->lex->current_select->save_leaf_tables(thd);
thd->lex->current_select->first_cond_optimization= 0;
}
DBUG_RETURN(FALSE);
abort:
@ -1133,6 +1156,11 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
bool insert_into_view= (table_list->view != 0);
DBUG_ENTER("mysql_prepare_insert_check_table");
if (!table_list->updatable)
{
my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT");
DBUG_RETURN(TRUE);
}
/*
first table in list is the one we'll INSERT into, requires INSERT_ACL.
all others require SELECT_ACL only. the ACL requirement below is for
@ -1143,14 +1171,16 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
table_list,
&thd->lex->select_lex.leaf_tables,
select_insert, INSERT_ACL, SELECT_ACL))
thd->lex->select_lex.leaf_tables,
select_insert, INSERT_ACL, SELECT_ACL,
TRUE))
DBUG_RETURN(TRUE);
if (insert_into_view && !fields.elements)
{
thd->lex->empty_field_list_on_rset= 1;
if (!table_list->table)
if (!thd->lex->select_lex.leaf_tables.head()->table ||
table_list->is_multitable())
{
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
table_list->view_db.str, table_list->view_name.str);
@ -1241,6 +1271,12 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
/* INSERT should have a SELECT or VALUES clause */
DBUG_ASSERT (!select_insert || !values);
if (mysql_handle_derived(thd->lex, DT_INIT))
DBUG_RETURN(TRUE);
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
DBUG_RETURN(TRUE);
if (mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE))
DBUG_RETURN(TRUE);
/*
For subqueries in VALUES() we should not see the table in which we are
inserting (for INSERT ... SELECT this is done by changing table_list,
@ -2934,9 +2970,9 @@ bool mysql_insert_select_prepare(THD *thd)
{
LEX *lex= thd->lex;
SELECT_LEX *select_lex= &lex->select_lex;
TABLE_LIST *first_select_leaf_table;
DBUG_ENTER("mysql_insert_select_prepare");
/*
Statement-based replication of INSERT ... SELECT ... LIMIT is not safe
as order of rows is not defined, so in mixed mode we go to row-based.
@ -2962,21 +2998,37 @@ bool mysql_insert_select_prepare(THD *thd)
&select_lex->where, TRUE, FALSE, FALSE))
DBUG_RETURN(TRUE);
DBUG_ASSERT(select_lex->leaf_tables.elements != 0);
List_iterator<TABLE_LIST> ti(select_lex->leaf_tables);
TABLE_LIST *table;
uint insert_tables;
if (select_lex->first_cond_optimization)
{
/* Back up leaf_tables list. */
Query_arena *arena= thd->stmt_arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test
insert_tables= select_lex->insert_tables;
while ((table= ti++) && insert_tables--)
{
select_lex->leaf_tables_exec.push_back(table);
table->tablenr_exec= table->table->tablenr;
table->map_exec= table->table->map;
}
if (arena)
thd->restore_active_arena(arena, &backup);
}
ti.rewind();
/*
exclude first table from leaf tables list, because it belong to
INSERT
*/
DBUG_ASSERT(select_lex->leaf_tables != 0);
lex->leaf_tables_insert= select_lex->leaf_tables;
/* skip all leaf tables belonged to view where we are insert */
for (first_select_leaf_table= select_lex->leaf_tables->next_leaf;
first_select_leaf_table &&
first_select_leaf_table->belong_to_view &&
first_select_leaf_table->belong_to_view ==
lex->leaf_tables_insert->belong_to_view;
first_select_leaf_table= first_select_leaf_table->next_leaf)
{}
select_lex->leaf_tables= first_select_leaf_table;
insert_tables= select_lex->insert_tables;
while ((table= ti++) && insert_tables--)
ti.remove();
DBUG_RETURN(FALSE);
}
@ -3193,7 +3245,7 @@ void select_insert::cleanup()
select_insert::~select_insert()
{
DBUG_ENTER("~select_insert");
if (table)
if (table && table->created)
{
table->next_number_field=0;
table->auto_increment_field_not_null= FALSE;

View file

@ -23,6 +23,7 @@
#include <hash.h>
#include "sp.h"
#include "sp_head.h"
#include "sql_select.h"
/*
We are using pointer to this variable for distinguishing between assignment
@ -309,7 +310,6 @@ void lex_start(THD *thd)
lex->derived_tables= 0;
lex->lock_option= TL_READ;
lex->safe_to_cache_query= 1;
lex->leaf_tables_insert= 0;
lex->parsing_options.reset();
lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1;
@ -1594,6 +1594,7 @@ void st_select_lex_unit::init_query()
describe= 0;
found_rows_for_union= 0;
insert_table_with_stored_vcol= 0;
derived= 0;
}
void st_select_lex::init_query()
@ -1602,7 +1603,8 @@ void st_select_lex::init_query()
table_list.empty();
top_join_list.empty();
join_list= &top_join_list;
embedding= leaf_tables= 0;
embedding= 0;
leaf_tables.empty();
item_list.empty();
join= 0;
having= prep_having= where= prep_where= 0;
@ -1670,6 +1672,8 @@ void st_select_lex::init_select()
cond_value= having_value= Item::COND_UNDEF;
inner_refs_list.empty();
full_group_by_flag= 0;
insert_tables= 0;
merged_into= 0;
}
/*
@ -2154,9 +2158,27 @@ void st_select_lex::print_order(String *str,
{
if (order->counter_used)
{
char buffer[20];
size_t length= my_snprintf(buffer, 20, "%d", order->counter);
str->append(buffer, (uint) length);
if (query_type != QT_VIEW_INTERNAL)
{
char buffer[20];
size_t length= my_snprintf(buffer, 20, "%d", order->counter);
str->append(buffer, (uint) length);
}
else
{
/* replace numeric reference with expression */
if (order->item[0]->type() == Item::INT_ITEM &&
order->item[0]->basic_const_item())
{
char buffer[20];
size_t length= my_snprintf(buffer, 20, "%d", order->counter);
str->append(buffer, (uint) length);
/* make it expression instead of integer constant */
str->append(STRING_WITH_LEN("+0"));
}
else
(*order->item)->print(str, query_type);
}
}
else
(*order->item)->print(str, query_type);
@ -2993,7 +3015,11 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl)
thd->check_and_register_item_tree(&tbl->prep_on_expr, &tbl->on_expr);
tbl->on_expr= tbl->on_expr->copy_andor_structure(thd);
}
fix_prepare_info_in_table_list(thd, tbl->merge_underlying_list);
if (tbl->is_view_or_derived() && tbl->is_merged_derived())
{
SELECT_LEX *sel= tbl->get_single_select();
fix_prepare_info_in_table_list(thd, sel->get_table_list());
}
}
}
@ -3127,6 +3153,8 @@ bool st_select_lex::optimize_unflattened_subqueries()
for (SELECT_LEX *sl= un->first_select(); sl; sl= sl->next_select())
{
JOIN *inner_join= sl->join;
if (!inner_join)
continue;
SELECT_LEX *save_select= un->thd->lex->current_select;
ulonglong save_options;
int res;
@ -3153,19 +3181,349 @@ bool st_select_lex::optimize_unflattened_subqueries()
}
/**
@brief Process all derived tables/views of the SELECT.
@param lex LEX of this thread
@param phase phases to run derived tables/views through
@details
This function runs specified 'phases' on all tables from the
table_list of this select.
@return FALSE ok.
@return TRUE an error occur.
*/
bool st_select_lex::handle_derived(struct st_lex *lex, uint phases)
{
for (TABLE_LIST *cursor= (TABLE_LIST*) table_list.first;
cursor;
cursor= cursor->next_local)
{
if (cursor->is_view_or_derived() && cursor->handle_derived(lex, phases))
return TRUE;
}
return FALSE;
}
/**
@brief
Returns first unoccupied table map and table number
@param map [out] return found map
@param tablenr [out] return found tablenr
@details
Returns first unoccupied table map and table number in this select.
Map and table are returned in *'map' and *'tablenr' accordingly.
@retrun TRUE no free table map/table number
@return FALSE found free table map/table number
*/
bool st_select_lex::get_free_table_map(table_map *map, uint *tablenr)
{
*map= 0;
*tablenr= 0;
TABLE_LIST *tl;
if (!join)
{
(*map)= 1<<1;
(*tablenr)++;
return FALSE;
}
List_iterator<TABLE_LIST> ti(leaf_tables);
while ((tl= ti++))
{
if (tl->table->map > *map)
*map= tl->table->map;
if (tl->table->tablenr > *tablenr)
*tablenr= tl->table->tablenr;
}
(*map)<<= 1;
(*tablenr)++;
if (*tablenr >= MAX_TABLES)
return TRUE;
return FALSE;
}
/**
@brief
Append given table to the leaf_tables list.
@param link Offset to which list in table structure to use
@param table Table to append
@details
Append given 'table' to the leaf_tables list using the 'link' offset.
If the 'table' is linked with other tables through next_leaf/next_local
chains then whole list will be appended.
*/
void st_select_lex::append_table_to_list(TABLE_LIST *TABLE_LIST::*link,
TABLE_LIST *table)
{
TABLE_LIST *tl;
for (tl= leaf_tables.head(); tl->*link; tl= tl->*link) ;
tl->*link= table;
}
/*
@brief
Remove given table from the leaf_tables list.
@param link Offset to which list in table structure to use
@param table Table to remove
@details
Remove 'table' from the leaf_tables list using the 'link' offset.
*/
void st_select_lex::remove_table_from_list(TABLE_LIST *table)
{
TABLE_LIST *tl;
List_iterator<TABLE_LIST> ti(leaf_tables);
while ((tl= ti++))
{
if (tl == table)
{
ti.remove();
break;
}
}
}
/**
@brief
Assigns new table maps to tables in the leaf_tables list
@param derived Derived table to take initial table map from
@param map table map to begin with
@param tablenr table number to begin with
@param parent_lex new parent select_lex
@details
Assign new table maps/table numbers to all tables in the leaf_tables list.
'map'/'tablenr' are used for the first table and shifted to left/
increased for each consequent table in the leaf_tables list.
If the 'derived' table is given then it's table map/number is used for the
first table in the list and 'map'/'tablenr' are used for the second and
all consequent tables.
The 'parent_lex' is set as the new parent select_lex for all tables in the
list.
*/
void st_select_lex::remap_tables(TABLE_LIST *derived, table_map map,
uint tablenr, SELECT_LEX *parent_lex)
{
bool first_table= TRUE;
TABLE_LIST *tl;
table_map first_map;
uint first_tablenr;
if (derived && derived->table)
{
first_map= derived->table->map;
first_tablenr= derived->table->tablenr;
}
else
{
first_map= map;
map<<= 1;
first_tablenr= tablenr++;
}
/*
Assign table bit/table number.
To the first table of the subselect the table bit/tablenr of the
derived table is assigned. The rest of tables are getting bits
sequentially, starting from the provided table map/tablenr.
*/
List_iterator<TABLE_LIST> ti(leaf_tables);
while ((tl= ti++))
{
if (first_table)
{
first_table= FALSE;
tl->table->set_table_map(first_map, first_tablenr);
}
else
{
tl->table->set_table_map(map, tablenr);
tablenr++;
map<<= 1;
}
SELECT_LEX *old_sl= tl->select_lex;
tl->select_lex= parent_lex;
for(TABLE_LIST *emb= tl->embedding;
emb && emb->select_lex == old_sl;
emb= emb->embedding)
emb->select_lex= parent_lex;
}
}
/**
@brief
Merge a subquery into this select.
@param derived derived table of the subquery to be merged
@param subq_select select_lex of the subquery
@param map table map for assigning to merged tables from subquery
@param table_no table number for assigning to merged tables from subquery
@details
This function merges a subquery into its parent select. In short the
merge operation appends the subquery FROM table list to the parent's
FROM table list. In more details:
.) the top_join_list of the subquery is wrapped into a join_nest
and attached to 'derived'
.) subquery's leaf_tables list is merged with the leaf_tables
list of this select_lex
.) the table maps and table numbers of the tables merged from
the subquery are adjusted to reflect their new binding to
this select
@return TRUE an error occur
@return FALSE ok
*/
bool SELECT_LEX::merge_subquery(TABLE_LIST *derived, SELECT_LEX *subq_select,
uint table_no, table_map map)
{
derived->wrap_into_nested_join(subq_select->top_join_list);
/* Reconnect the next_leaf chain. */
leaf_tables.concat(&subq_select->leaf_tables);
ftfunc_list->concat(subq_select->ftfunc_list);
if (join)
{
Item_in_subselect **in_subq;
Item_in_subselect **in_subq_end;
for (in_subq= subq_select->join->sj_subselects.front(),
in_subq_end= subq_select->join->sj_subselects.back();
in_subq != in_subq_end;
in_subq++)
{
join->sj_subselects.append(join->thd->mem_root, *in_subq);
(*in_subq)->emb_on_expr_nest= derived;
}
}
/*
Remove merged table from chain.
When merge_subquery is called at a subquery-to-semijoin transformation
the derived isn't in the leaf_tables list, so in this case the call of
remove_table_from_list does not cause any actions.
*/
remove_table_from_list(derived);
/* Walk through child's tables and adjust table map, tablenr,
* parent_lex */
subq_select->remap_tables(derived, map, table_no, this);
subq_select->merged_into= this;
return FALSE;
}
/**
@brief
Mark tables from the leaf_tables list as belong to a derived table.
@param derived tables will be marked as belonging to this derived
@details
Run through the leaf_list and mark all tables as belonging to the 'derived'.
*/
void SELECT_LEX::mark_as_belong_to_derived(TABLE_LIST *derived)
{
/* Mark tables as belonging to this DT */
TABLE_LIST *tl;
List_iterator<TABLE_LIST> ti(leaf_tables);
while ((tl= ti++))
{
tl->skip_temporary= 1;
tl->belong_to_derived= derived;
}
}
/**
@brief
Update used_tables cache for this select
@details
This function updates used_tables cache of ON expressions of all tables
in the leaf_tables list and of the conds expression (if any).
*/
void SELECT_LEX::update_used_tables()
{
TABLE_LIST *tl;
List_iterator<TABLE_LIST> ti(leaf_tables);
while ((tl= ti++))
{
if (tl->on_expr)
{
tl->on_expr->update_used_tables();
tl->on_expr->walk(&Item::eval_not_null_tables, 0, NULL);
}
TABLE_LIST *embedding= tl->embedding;
while (embedding)
{
if (embedding->on_expr &&
embedding->nested_join->join_list.head() == tl)
{
embedding->on_expr->update_used_tables();
embedding->on_expr->walk(&Item::eval_not_null_tables, 0, NULL);
}
tl= embedding;
embedding= tl->embedding;
}
}
if (join->conds)
{
join->conds->update_used_tables();
join->conds->walk(&Item::eval_not_null_tables, 0, NULL);
}
}
/**
Set the EXPLAIN type for this subquery.
*/
void st_select_lex::set_explain_type()
{
bool is_primary= FALSE;
if (next_select())
is_primary= TRUE;
if (!is_primary && first_inner_unit())
{
/*
If there is at least one materialized derived|view then it's a PRIMARY select.
Otherwise, all derived tables/views were merged and this select is a SIMPLE one.
*/
for (SELECT_LEX_UNIT *un= first_inner_unit(); un; un= un->next_unit())
{
if ((!un->derived || un->derived->is_materialized_derived()))
{
is_primary= TRUE;
break;
}
}
}
SELECT_LEX *first= master_unit()->first_select();
/* drop UNCACHEABLE_EXPLAIN, because it is for internal usage only */
uint8 is_uncacheable= (uncacheable & ~UNCACHEABLE_EXPLAIN);
type= ((&master_unit()->thd->lex->select_lex == this) ?
(first_inner_unit() || next_select() ?
"PRIMARY" : "SIMPLE") :
(is_primary ? "PRIMARY" : "SIMPLE"):
((this == first) ?
((linkage == DERIVED_TABLE_TYPE) ?
"DERIVED" :
@ -3181,6 +3539,76 @@ void st_select_lex::set_explain_type()
}
/**
@brief
Increase estimated number of records for a derived table/view
@param records number of records to increase estimate by
@details
This function increases estimated number of records by the 'records'
for the derived table to which this select belongs to.
*/
void SELECT_LEX::increase_derived_records(ha_rows records)
{
SELECT_LEX_UNIT *unit= master_unit();
DBUG_ASSERT(unit->derived);
select_union *result= (select_union*)unit->result;
result->records+= records;
}
/**
@brief
Mark select's derived table as a const one.
@param empty Whether select has an empty result set
@details
Mark derived table/view of this select as a constant one (to
materialize it at the optimization phase) unless this select belongs to a
union. Estimated number of rows is incremented if this select has non empty
result set.
*/
void SELECT_LEX::mark_const_derived(bool empty)
{
TABLE_LIST *derived= master_unit()->derived;
if (!join->thd->lex->describe && derived)
{
if (!empty)
increase_derived_records(1);
if (!master_unit()->is_union() && !derived->is_merged_derived())
derived->fill_me= TRUE;
}
}
bool st_select_lex::save_leaf_tables(THD *thd)
{
Query_arena *arena= thd->stmt_arena, backup;
if (arena->is_conventional())
arena= 0;
else
thd->set_n_backup_active_arena(arena, &backup);
List_iterator_fast<TABLE_LIST> li(leaf_tables);
TABLE_LIST *table;
while ((table= li++))
{
if (leaf_tables_exec.push_back(table))
return 1;
table->tablenr_exec= table->table->tablenr;
table->map_exec= table->table->map;
}
if (arena)
thd->restore_active_arena(arena, &backup);
return 0;
}
/**
A routine used by the parser to decide whether we are specifying a full
partitioning or if only partitions to add or to split.

View file

@ -472,6 +472,11 @@ public:
friend bool mysql_new_select(struct st_lex *lex, bool move_down);
friend bool mysql_make_view(THD *thd, File_parser *parser,
TABLE_LIST *table, uint flags);
friend bool mysql_derived_prepare(THD *thd, st_lex *lex,
TABLE_LIST *orig_table_list);
friend bool mysql_derived_merge(THD *thd, st_lex *lex,
TABLE_LIST *orig_table_list);
friend bool TABLE_LIST::init_derived(THD *thd, bool init_view);
private:
void fast_exclude();
};
@ -490,13 +495,12 @@ class st_select_lex_unit: public st_select_lex_node {
protected:
TABLE_LIST result_table_list;
select_union *union_result;
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
ulonglong found_rows_for_union;
bool saved_error;
public:
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
bool prepared, // prepare phase already performed for UNION (unit)
optimized, // optimize phase already performed for UNION (unit)
executed, // already executed
@ -523,6 +527,11 @@ public:
ha_rows select_limit_cnt, offset_limit_cnt;
/* not NULL if unit used in subselect, point to subselect item */
Item_subselect *item;
/*
TABLE_LIST representing this union in the embedding select. Used for
derived tables/views handling.
*/
TABLE_LIST *derived;
/* thread handler */
THD *thd;
/*
@ -559,6 +568,7 @@ public:
/* UNION methods */
bool prepare(THD *thd, select_result *result, ulong additional_options);
bool optimize();
bool exec();
bool cleanup();
inline void unclean() { cleaned= 0; }
@ -575,6 +585,8 @@ public:
void set_thd(THD *thd_arg) { thd= thd_arg; }
inline bool is_union ();
void set_unique_exclude();
friend void lex_start(THD *thd);
friend int subselect_union_engine::exec();
@ -620,8 +632,17 @@ public:
Beginning of the list of leaves in a FROM clause, where the leaves
inlcude all base tables including view tables. The tables are connected
by TABLE_LIST::next_leaf, so leaf_tables points to the left-most leaf.
List of all base tables local to a subquery including all view
tables. Unlike 'next_local', this in this list views are *not*
leaves. Created in setup_tables() -> make_leaves_list().
*/
TABLE_LIST *leaf_tables;
List<TABLE_LIST> leaf_tables;
List<TABLE_LIST> leaf_tables_exec;
uint insert_tables;
st_select_lex *merged_into; /* select which this select is merged into */
/* (not 0 only for views/derived tables) */
const char *type; /* type of select for EXPLAIN */
SQL_I_List<ORDER> order_list; /* ORDER clause */
@ -857,6 +878,27 @@ public:
bool optimize_unflattened_subqueries();
/* Set the EXPLAIN type for this subquery. */
void set_explain_type();
bool handle_derived(struct st_lex *lex, uint phases);
void append_table_to_list(TABLE_LIST *TABLE_LIST::*link, TABLE_LIST *table);
bool get_free_table_map(table_map *map, uint *tablenr);
void remove_table_from_list(TABLE_LIST *table);
void remap_tables(TABLE_LIST *derived, table_map map,
uint tablenr, st_select_lex *parent_lex);
bool merge_subquery(TABLE_LIST *derived, st_select_lex *subq_lex,
uint tablenr, table_map map);
inline bool is_mergeable()
{
return (next_select() == 0 && group_list.elements == 0 &&
having == 0 && with_sum_func == 0 &&
table_list.elements >= 1 && !(options & SELECT_DISTINCT) &&
select_limit == 0);
}
void mark_as_belong_to_derived(TABLE_LIST *derived);
void increase_derived_records(ha_rows records);
void update_used_tables();
void mark_const_derived(bool empty);
bool save_leaf_tables(THD *thd);
private:
/* current index hint kind. used in filling up index_hints */
@ -1629,8 +1671,6 @@ typedef struct st_lex : public Query_tables_list
CHARSET_INFO *charset;
bool text_string_is_7bit;
/* store original leaf_tables for INSERT SELECT and PS/SP */
TABLE_LIST *leaf_tables_insert;
/** SELECT of CREATE VIEW statement */
LEX_STRING create_view_select;
@ -1747,7 +1787,7 @@ typedef struct st_lex : public Query_tables_list
DERIVED_SUBQUERY and DERIVED_VIEW).
*/
uint8 derived_tables;
uint8 create_view_algorithm;
uint16 create_view_algorithm;
uint8 create_view_check;
bool drop_if_exists, drop_temporary, local_file, one_shot_set;
bool autocommit;
@ -1935,6 +1975,8 @@ typedef struct st_lex : public Query_tables_list
switch (sql_command) {
case SQLCOM_UPDATE:
case SQLCOM_UPDATE_MULTI:
case SQLCOM_DELETE:
case SQLCOM_DELETE_MULTI:
case SQLCOM_INSERT:
case SQLCOM_INSERT_SELECT:
case SQLCOM_REPLACE:

View file

@ -265,6 +265,8 @@ public:
prev= &node->next;
node= node->next;
elements++;
if (node == &end_of_list)
return;
}
*prev= *last;
last= prev;

View file

@ -172,12 +172,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(TRUE);
if (mysql_handle_single_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
mysql_handle_single_derived(thd->lex, table_list, DT_PREPARE))
DBUG_RETURN(TRUE);
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
&thd->lex->select_lex.top_join_list,
table_list,
&thd->lex->select_lex.leaf_tables, FALSE,
thd->lex->select_lex.leaf_tables, FALSE,
INSERT_ACL | UPDATE_ACL,
INSERT_ACL | UPDATE_ACL))
INSERT_ACL | UPDATE_ACL, FALSE))
DBUG_RETURN(-1);
if (!table_list->table || // do not suport join view
!table_list->updatable || // and derived tables

View file

@ -153,8 +153,7 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
if (setup_tables(lex->thd, &select_lex->context, &select_lex->top_join_list,
select_lex->table_list.first
&select_lex->leaf_tables, FALSE) ||
FALSE, FALSE) ||
setup_fields(lex->thd, 0, select_lex->item_list, MARK_COLUMNS_READ,
&all_fields,1) ||
setup_fields(lex->thd, 0, item_list_copy, MARK_COLUMNS_READ,

View file

@ -2697,6 +2697,9 @@ mysql_execute_command(THD *thd)
}
}
}
if (mysql_handle_single_derived(thd->lex, create_table,
DT_MERGE_FOR_INSERT))
DBUG_RETURN(1);
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
@ -3223,6 +3226,10 @@ end_with_restore_list:
if (!(res= open_and_lock_tables(thd, all_tables)))
{
/*
Only the INSERT table should be merged. Other will be handled by
select.
*/
/* Skip first table, which is the table we are inserting in */
TABLE_LIST *second_table= first_table->next_local;
select_lex->table_list.first= second_table;

View file

@ -1168,7 +1168,7 @@ static bool mysql_test_insert(Prepared_statement *stmt,
If we would use locks, then we have to ensure we are not using
TL_WRITE_DELAYED as having two such locks can cause table corruption.
*/
if (open_normal_and_derived_tables(thd, table_list, 0))
if (open_normal_and_derived_tables(thd, table_list, 0, DT_INIT))
goto error;
if ((values= its++))
@ -1252,7 +1252,10 @@ static int mysql_test_update(Prepared_statement *stmt,
open_tables(thd, &table_list, &table_count, 0))
goto error;
if (table_list->multitable_view)
if (mysql_handle_derived(thd->lex, DT_INIT))
goto error;
if (table_list->is_multitable())
{
DBUG_ASSERT(table_list->view != 0);
DBUG_PRINT("info", ("Switch to multi-update"));
@ -1266,9 +1269,16 @@ static int mysql_test_update(Prepared_statement *stmt,
thd->fill_derived_tables() is false here for sure (because it is
preparation of PS, so we even do not check it).
*/
if (mysql_handle_derived(thd->lex, &mysql_derived_prepare))
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT) ||
table_list->handle_derived(thd->lex, DT_PREPARE))
goto error;
if (!table_list->updatable)
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
goto error;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Force privilege re-checking for views after they have been opened. */
want_privilege= (table_list->view ? UPDATE_ACL :
@ -1321,15 +1331,26 @@ error:
static bool mysql_test_delete(Prepared_statement *stmt,
TABLE_LIST *table_list)
{
uint table_count= 0;
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
DBUG_ENTER("mysql_test_delete");
if (delete_precheck(thd, table_list) ||
open_normal_and_derived_tables(thd, table_list, 0))
open_tables(thd, &table_list, &table_count, 0))
goto error;
if (!table_list->table)
if (mysql_handle_derived(thd->lex, DT_INIT) ||
mysql_handle_list_of_derived(thd->lex, table_list, DT_MERGE_FOR_INSERT) ||
mysql_handle_list_of_derived(thd->lex, table_list, DT_PREPARE))
goto error;
if (!table_list->updatable)
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
goto error;
}
if (!table_list->table || !table_list->table->created)
{
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
@ -1384,7 +1405,8 @@ static int mysql_test_select(Prepared_statement *stmt,
goto error;
}
if (open_normal_and_derived_tables(thd, tables, 0))
if (open_normal_and_derived_tables(thd, tables, 0,
DT_PREPARE | DT_CREATE))
goto error;
thd->used_tables= 0; // Updated by setup_fields
@ -1445,7 +1467,8 @@ static bool mysql_test_do_fields(Prepared_statement *stmt,
if (tables && check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE))
DBUG_RETURN(TRUE);
if (open_normal_and_derived_tables(thd, tables, 0))
if (open_normal_and_derived_tables(thd, tables, 0,
DT_PREPARE | DT_CREATE))
DBUG_RETURN(TRUE);
DBUG_RETURN(setup_fields(thd, 0, *values, MARK_COLUMNS_NONE, 0, 0));
}
@ -1475,7 +1498,8 @@ static bool mysql_test_set_fields(Prepared_statement *stmt,
if ((tables &&
check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)) ||
open_normal_and_derived_tables(thd, tables, 0))
open_normal_and_derived_tables(thd, tables, 0,
DT_PREPARE | DT_CREATE))
goto error;
while ((var= it++))
@ -1512,7 +1536,7 @@ static bool mysql_test_call_fields(Prepared_statement *stmt,
if ((tables &&
check_table_access(thd, SELECT_ACL, tables, UINT_MAX, FALSE)) ||
open_normal_and_derived_tables(thd, tables, 0))
open_normal_and_derived_tables(thd, tables, 0, DT_PREPARE))
goto err;
while ((item= it++))
@ -1587,6 +1611,7 @@ select_like_stmt_test_with_open(Prepared_statement *stmt,
int (*specific_prepare)(THD *thd),
ulong setup_tables_done_option)
{
uint table_count= 0;
DBUG_ENTER("select_like_stmt_test_with_open");
/*
@ -1595,7 +1620,8 @@ select_like_stmt_test_with_open(Prepared_statement *stmt,
prepared EXPLAIN yet so derived tables will clean up after
themself.
*/
if (open_normal_and_derived_tables(stmt->thd, tables, 0))
THD *thd= stmt->thd;
if (open_tables(thd, &tables, &table_count, 0))
DBUG_RETURN(TRUE);
DBUG_RETURN(select_like_stmt_test(stmt, specific_prepare,
@ -1640,7 +1666,8 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
create_table->skip_temporary= true;
}
if (open_normal_and_derived_tables(stmt->thd, lex->query_tables, 0))
if (open_normal_and_derived_tables(stmt->thd, lex->query_tables, 0,
DT_PREPARE | DT_CREATE))
DBUG_RETURN(TRUE);
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
@ -1658,7 +1685,8 @@ static bool mysql_test_create_table(Prepared_statement *stmt)
we validate metadata of all CREATE TABLE statements,
which keeps metadata validation code simple.
*/
if (open_normal_and_derived_tables(stmt->thd, lex->query_tables, 0))
if (open_normal_and_derived_tables(stmt->thd, lex->query_tables, 0,
DT_PREPARE))
DBUG_RETURN(TRUE);
}
@ -1693,7 +1721,7 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
if (create_view_precheck(thd, tables, view, lex->create_view_mode))
goto err;
if (open_normal_and_derived_tables(thd, tables, 0))
if (open_normal_and_derived_tables(thd, tables, 0, DT_PREPARE))
goto err;
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
@ -2429,6 +2457,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
/* Fix ORDER list */
for (order= sl->order_list.first; order; order= order->next)
order->item= &order->item_ptr;
sl->handle_derived(lex, DT_REINIT);
/* clear the no_error flag for INSERT/UPDATE IGNORE */
sl->no_error= FALSE;
@ -2472,9 +2501,6 @@ void reinit_stmt_before_use(THD *thd, LEX *lex)
}
lex->current_select= &lex->select_lex;
/* restore original list used in INSERT ... SELECT */
if (lex->leaf_tables_insert)
lex->select_lex.leaf_tables= lex->leaf_tables_insert;
if (lex->result)
{

File diff suppressed because it is too large Load diff

View file

@ -369,6 +369,8 @@ typedef struct st_join_table {
uint n_sj_tables;
bool preread_init_done;
void cleanup();
inline bool is_using_loose_index_scan()
{
@ -474,6 +476,8 @@ typedef struct st_join_table {
{
return (is_hash_join_key_no(key) ? hj_key : table->key_info+key);
}
double scan_time();
bool preread_init();
} JOIN_TAB;
@ -1121,6 +1125,7 @@ public:
{
return (table_map(1) << table_count) - 1;
}
void drop_unused_derived_keys();
/*
Return the table for which an index scan can be used to satisfy
the sort order needed by the ORDER BY/(implicit) GROUP BY clause
@ -1203,7 +1208,7 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field,
/* functions from opt_sum.cc */
bool simple_pred(Item_func *func_item, Item **args, bool *inv_order);
int opt_sum_query(THD* thd,
TABLE_LIST *tables, List<Item> &all_fields, COND *conds);
List<TABLE_LIST> &tables, List<Item> &all_fields, COND *conds);
/* from sql_delete.cc, used by opt_range.cc */
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b);
@ -1466,7 +1471,7 @@ void push_index_cond(JOIN_TAB *tab, uint keyno);
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit,
char* alias);
char* alias, bool do_not_open=FALSE);
void free_tmp_table(THD *thd, TABLE *entry);
bool create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
ENGINE_COLUMNDEF *start_recinfo,
@ -1479,5 +1484,6 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
bool open_tmp_table(TABLE *table);
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps);
double prev_record_reads(POSITION *positions, uint idx, table_map found_ref);
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist);
#endif /* SQL_SELECT_INCLUDED */

View file

@ -755,7 +755,8 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
Show_create_error_handler view_error_suppressor(thd, table_list);
thd->push_internal_handler(&view_error_suppressor);
bool error= open_normal_and_derived_tables(thd, table_list, 0);
bool error= open_normal_and_derived_tables(thd, table_list, 0,
DT_PREPARE | DT_CREATE);
thd->pop_internal_handler();
if (error && (thd->killed || thd->main_da.is_error()))
DBUG_RETURN(TRUE);
@ -930,7 +931,8 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
DBUG_ENTER("mysqld_list_fields");
DBUG_PRINT("enter",("table: %s",table_list->table_name));
if (open_normal_and_derived_tables(thd, table_list, 0))
if (open_normal_and_derived_tables(thd, table_list, 0,
DT_PREPARE | DT_CREATE))
DBUG_VOID_RETURN;
table= table_list->table;
@ -1744,7 +1746,7 @@ view_store_options(THD *thd, TABLE_LIST *table, String *buff)
static void append_algorithm(TABLE_LIST *table, String *buff)
{
buff->append(STRING_WITH_LEN("ALGORITHM="));
switch ((int8)table->algorithm) {
switch ((int16)table->algorithm) {
case VIEW_ALGORITHM_UNDEFINED:
buff->append(STRING_WITH_LEN("UNDEFINED "));
break;
@ -3443,8 +3445,9 @@ fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables,
SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
*/
lex->sql_command= SQLCOM_SHOW_FIELDS;
res= open_normal_and_derived_tables(thd, show_table_list,
MYSQL_LOCK_IGNORE_FLUSH);
res= (open_normal_and_derived_tables(thd, show_table_list,
MYSQL_LOCK_IGNORE_FLUSH,
DT_PREPARE | DT_CREATE));
lex->sql_command= save_sql_command;
/*
get_all_tables() returns 1 on failure and 0 on success thus
@ -3886,8 +3889,9 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
show_table_list->i_s_requested_object=
schema_table->i_s_requested_object;
DEBUG_SYNC(thd, "before_open_in_get_all_tables");
res= open_normal_and_derived_tables(thd, show_table_list,
MYSQL_LOCK_IGNORE_FLUSH);
res= (open_normal_and_derived_tables(thd, show_table_list,
MYSQL_LOCK_IGNORE_FLUSH,
DT_PREPARE | DT_CREATE));
lex->sql_command= save_sql_command;
/*
XXX: show_table_list has a flag i_is_requested,

View file

@ -4729,8 +4729,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
thd->no_warnings_for_error= no_warnings_for_error;
if (view_operator_func == NULL)
table->required_type=FRMTYPE_TABLE;
if (lex->sql_command == SQLCOM_CHECK ||
lex->sql_command == SQLCOM_REPAIR ||
lex->sql_command == SQLCOM_ANALYZE ||
lex->sql_command == SQLCOM_OPTIMIZE)
thd->prepare_derived_at_open= TRUE;
open_and_lock_tables(thd, table);
thd->prepare_derived_at_open= FALSE;
thd->no_warnings_for_error= 0;
table->next_global= save_next_global;
table->next_local= save_next_local;
@ -4828,7 +4833,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
else
/* Default failure code is corrupt table */
result_code= HA_ADMIN_CORRUPT;
goto send_result;
goto send_result;
}
if (table->view)

View file

@ -112,6 +112,7 @@ bool select_union::flush()
options create options
table_alias name of the temporary table
bit_fields_as_long convert bit fields to ulonglong
create_table whether to physically create result table
DESCRIPTION
Create a temporary table that is used to store the result of a UNION,
@ -126,7 +127,7 @@ bool
select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
bool is_union_distinct, ulonglong options,
const char *alias,
bool bit_fields_as_long)
bool bit_fields_as_long, bool create_table)
{
DBUG_ASSERT(table == 0);
tmp_table_param.init();
@ -135,15 +136,19 @@ select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
(ORDER*) 0, is_union_distinct, 1,
options, HA_POS_ERROR, (char*) alias)))
options, HA_POS_ERROR, (char*) alias,
!create_table)))
return TRUE;
//psergey-merge-fix:
table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
table->field[i]->flags &= ~PART_KEY_FLAG;
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
if (create_table)
{
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
}
return FALSE;
}
@ -309,6 +314,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
(is_union_select ? NULL :
thd_arg->lex->proc_list.first),
sl, this);
/* There are no * in the statement anymore (for PS) */
sl->with_wild= 0;
last_procedure= join->procedure;
@ -363,6 +369,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
List_iterator_fast<Item> tp(types);
Item *type;
ulonglong create_options;
uint save_tablenr= 0;
table_map save_map= 0;
while ((type= tp++))
{
@ -415,12 +423,22 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
create_options= create_options | TMP_TABLE_FORCE_MYISAM;
if (union_result->create_result_table(thd, &types, test(union_distinct),
create_options, "", FALSE))
create_options, "", FALSE, TRUE))
goto err;
if (fake_select_lex && !fake_select_lex->first_cond_optimization)
{
save_tablenr= result_table_list.tablenr_exec;
save_map= result_table_list.map_exec;
}
bzero((char*) &result_table_list, sizeof(result_table_list));
result_table_list.db= (char*) "";
result_table_list.table_name= result_table_list.alias= (char*) "union";
result_table_list.table= table= union_result->table;
if (fake_select_lex && !fake_select_lex->first_cond_optimization)
{
result_table_list.tablenr_exec= save_tablenr;
result_table_list.map_exec= save_map;
}
thd_arg->lex->current_select= lex_select_save;
if (!item_list.elements)
@ -484,18 +502,21 @@ err:
}
bool st_select_lex_unit::exec()
/**
Run optimization phase.
@return FALSE unit successfully passed optimization phase.
@return TRUE an error occur.
*/
bool st_select_lex_unit::optimize()
{
SELECT_LEX *lex_select_save= thd->lex->current_select;
SELECT_LEX *select_cursor=first_select();
ulonglong add_rows=0;
ha_rows examined_rows= 0;
DBUG_ENTER("st_select_lex_unit::exec");
DBUG_ENTER("st_select_lex_unit::optimize");
if (executed && !uncacheable && !describe)
if (optimized && !uncacheable && !describe)
DBUG_RETURN(FALSE);
executed= 1;
if (uncacheable || !item || !item->assigned() || describe)
{
if (item)
@ -516,12 +537,71 @@ bool st_select_lex_unit::exec()
}
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
ha_rows records_at_start= 0;
thd->lex->current_select= sl;
if (optimized)
saved_error= sl->join->reinit();
else
{
set_limit(sl);
if (sl == global_parameters || describe)
{
offset_limit_cnt= 0;
/*
We can't use LIMIT at this stage if we are using ORDER BY for the
whole query
*/
if (sl->order_list.first || describe)
select_limit_cnt= HA_POS_ERROR;
}
/*
When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
we don't calculate found_rows() per union part.
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
*/
sl->join->select_options=
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
saved_error= sl->join->optimize();
}
if (saved_error)
{
thd->lex->current_select= lex_select_save;
DBUG_RETURN(saved_error);
}
}
}
optimized= 1;
thd->lex->current_select= lex_select_save;
DBUG_RETURN(saved_error);
}
bool st_select_lex_unit::exec()
{
SELECT_LEX *lex_select_save= thd->lex->current_select;
SELECT_LEX *select_cursor=first_select();
ulonglong add_rows=0;
ha_rows examined_rows= 0;
DBUG_ENTER("st_select_lex_unit::exec");
if (executed && !uncacheable && !describe)
DBUG_RETURN(FALSE);
executed= 1;
saved_error= optimize();
if (uncacheable || !item || !item->assigned() || describe)
{
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
ha_rows records_at_start= 0;
thd->lex->current_select= sl;
{
set_limit(sl);
if (sl == global_parameters || describe)
@ -595,7 +675,6 @@ bool st_select_lex_unit::exec()
}
}
}
optimized= 1;
/* Send result to 'result' */
saved_error= TRUE;
@ -871,3 +950,27 @@ void st_select_lex::cleanup_all_joins(bool full)
for (sl= unit->first_select(); sl; sl= sl->next_select())
sl->cleanup_all_joins(full);
}
/**
Set exclude_from_table_unique_test for selects of this unit and all
underlying selects.
@note used to exclude materialized derived tables (views) from unique
table check.
*/
void st_select_lex_unit::set_unique_exclude()
{
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
sl->exclude_from_table_unique_test= TRUE;
for (SELECT_LEX_UNIT *unit= sl->first_inner_unit();
unit;
unit= unit->next_unit())
{
unit->set_unique_exclude();
}
}
}

View file

@ -229,7 +229,11 @@ int mysql_update(THD *thd,
if (open_tables(thd, &table_list, &table_count, 0))
DBUG_RETURN(1);
if (table_list->multitable_view)
//Prepare views so they are handled correctly.
if (mysql_handle_derived(thd->lex, DT_INIT))
DBUG_RETURN(1);
if (table_list->is_multitable())
{
DBUG_ASSERT(table_list->view != 0);
DBUG_PRINT("info", ("Switch to multi-update"));
@ -244,15 +248,19 @@ int mysql_update(THD *thd,
DBUG_RETURN(1);
close_tables_for_reopen(thd, &table_list);
}
if (mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
(thd->fill_derived_tables() &&
mysql_handle_derived(thd->lex, &mysql_derived_filling)))
if (table_list->handle_derived(thd->lex, DT_MERGE_FOR_INSERT))
DBUG_RETURN(1);
if (table_list->handle_derived(thd->lex, DT_PREPARE))
DBUG_RETURN(1);
thd_proc_info(thd, "init");
table= table_list->table;
if (!table_list->updatable)
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
DBUG_RETURN(1);
}
/* Calculate "table->covering_keys" based on the WHERE */
table->covering_keys= table->s->keys_in_use;
table->quick_keys.clear_all();
@ -271,13 +279,17 @@ int mysql_update(THD *thd,
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
table_list->register_want_access(want_privilege);
#endif
/* 'Unfix' fields to allow correct marking by the setup_fields function. */
if (table_list->is_view())
unfix_fields(fields);
if (setup_fields_with_no_wrap(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
DBUG_RETURN(1); /* purecov: inspected */
if (table_list->view && check_fields(thd, fields))
{
DBUG_RETURN(1);
}
if (!table_list->updatable || check_key_in_view(thd, table_list))
if (check_key_in_view(thd, table_list))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
DBUG_RETURN(1);
@ -869,6 +881,11 @@ int mysql_update(THD *thd,
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
thd->abort_on_warning= 0;
if (thd->lex->current_select->first_cond_optimization)
{
thd->lex->current_select->save_leaf_tables(thd);
thd->lex->current_select->first_cond_optimization= 0;
}
DBUG_RETURN((error >= 0 || thd->is_error()) ? 1 : 0);
err:
@ -929,8 +946,8 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
if (setup_tables_and_check_access(thd, &select_lex->context,
&select_lex->top_join_list,
table_list,
&select_lex->leaf_tables,
FALSE, UPDATE_ACL, SELECT_ACL) ||
select_lex->leaf_tables,
FALSE, UPDATE_ACL, SELECT_ACL, TRUE) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
select_lex->setup_ref_array(thd, order_num) ||
setup_order(thd, select_lex->ref_pointer_array,
@ -967,8 +984,8 @@ static table_map get_table_map(List<Item> *items)
Item_field *item;
table_map map= 0;
while ((item= (Item_field *) item_it++))
map|= item->used_tables();
while ((item= (Item_field *) item_it++))
map|= item->all_used_tables();
DBUG_PRINT("info", ("table_map: 0x%08lx", (long) map));
return map;
}
@ -990,7 +1007,7 @@ int mysql_multi_update_prepare(THD *thd)
{
LEX *lex= thd->lex;
TABLE_LIST *table_list= lex->query_tables;
TABLE_LIST *tl, *leaves;
TABLE_LIST *tl;
List<Item> *fields= &lex->select_lex.item_list;
table_map tables_for_update;
bool update_view= 0;
@ -1013,19 +1030,24 @@ reopen_tables:
/* open tables and create derived ones, but do not lock and fill them */
if (((original_multiupdate || need_reopen) &&
open_tables(thd, &table_list, &table_count, 0)) ||
mysql_handle_derived(lex, &mysql_derived_prepare))
mysql_handle_derived(lex, DT_INIT))
DBUG_RETURN(TRUE);
/*
setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
second time, but this call will do nothing (there are check for second
call in setup_tables()).
*/
//We need to merge for insert prior to prepare.
if (mysql_handle_list_of_derived(lex, table_list, DT_MERGE_FOR_INSERT))
DBUG_RETURN(1);
if (mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(TRUE);
if (setup_tables_and_check_access(thd, &lex->select_lex.context,
&lex->select_lex.top_join_list,
table_list,
&lex->select_lex.leaf_tables, FALSE,
UPDATE_ACL, SELECT_ACL))
lex->select_lex.leaf_tables, FALSE,
UPDATE_ACL, SELECT_ACL, TRUE))
DBUG_RETURN(TRUE);
if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0))
@ -1050,8 +1072,8 @@ reopen_tables:
/*
Setup timestamp handling and locking mode
*/
leaves= lex->select_lex.leaf_tables;
for (tl= leaves; tl; tl= tl->next_leaf)
List_iterator<TABLE_LIST> ti(lex->select_lex.leaf_tables);
while ((tl= ti++))
{
TABLE *table= tl->table;
/* Only set timestamp column if this is not modified */
@ -1093,7 +1115,7 @@ reopen_tables:
for (tl= table_list; tl; tl= tl->next_local)
{
/* Check access privileges for table */
if (!tl->derived)
if (!tl->is_derived())
{
uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL;
if (check_access(thd, want_privilege,
@ -1107,7 +1129,7 @@ reopen_tables:
/* check single table update for view compound from several tables */
for (tl= table_list; tl; tl= tl->next_local)
{
if (tl->effective_algorithm == VIEW_ALGORITHM_MERGE)
if (tl->is_merged_derived())
{
TABLE_LIST *for_update= 0;
if (tl->check_single_table(&for_update, tables_for_update, tl))
@ -1162,6 +1184,8 @@ reopen_tables:
*/
unit->unclean();
}
// Reset 'prepared' flags for all derived tables/views
mysql_handle_list_of_derived(thd->lex, table_list, DT_REINIT);
/*
Also we need to cleanup Natural_join_column::table_field items.
@ -1184,7 +1208,8 @@ reopen_tables:
*/
lex->select_lex.exclude_from_table_unique_test= TRUE;
/* We only need SELECT privilege for columns in the values list */
for (tl= leaves; tl; tl= tl->next_leaf)
ti.rewind();
while ((tl= ti++))
{
TABLE *table= tl->table;
TABLE_LIST *tlist;
@ -1213,10 +1238,6 @@ reopen_tables:
*/
lex->select_lex.exclude_from_table_unique_test= FALSE;
if (thd->fill_derived_tables() &&
mysql_handle_derived(lex, &mysql_derived_filling))
DBUG_RETURN(TRUE);
DBUG_RETURN (FALSE);
}
@ -1239,7 +1260,7 @@ bool mysql_multi_update(THD *thd,
DBUG_ENTER("mysql_multi_update");
if (!(result= new multi_update(table_list,
thd->lex->select_lex.leaf_tables,
&thd->lex->select_lex.leaf_tables,
fields, values,
handle_duplicates, ignore)))
DBUG_RETURN(TRUE);
@ -1274,7 +1295,7 @@ bool mysql_multi_update(THD *thd,
multi_update::multi_update(TABLE_LIST *table_list,
TABLE_LIST *leaves_list,
List<TABLE_LIST> *leaves_list,
List<Item> *field_list, List<Item> *value_list,
enum enum_duplicates handle_duplicates_arg,
bool ignore_arg)
@ -1292,6 +1313,7 @@ multi_update::multi_update(TABLE_LIST *table_list,
int multi_update::prepare(List<Item> &not_used_values,
SELECT_LEX_UNIT *lex_unit)
{
TABLE_LIST *table_ref;
SQL_I_List<TABLE_LIST> update;
@ -1301,12 +1323,20 @@ int multi_update::prepare(List<Item> &not_used_values,
List_iterator_fast<Item> value_it(*values);
uint i, max_fields;
uint leaf_table_count= 0;
List_iterator<TABLE_LIST> ti(*leaves);
DBUG_ENTER("multi_update::prepare");
thd->count_cuted_fields= CHECK_FIELD_WARN;
thd->cuted_fields=0L;
thd_proc_info(thd, "updating main table");
SELECT_LEX *select_lex= lex_unit->first_select();
if (select_lex->first_cond_optimization)
{
if (select_lex->handle_derived(thd->lex, DT_MERGE))
DBUG_RETURN(TRUE);
}
tables_to_update= get_table_map(fields);
if (!tables_to_update)
@ -1320,7 +1350,7 @@ int multi_update::prepare(List<Item> &not_used_values,
TABLE::tmp_set by pointing TABLE::read_set to it and then restore it after
setup_fields().
*/
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
while ((table_ref= ti++))
{
TABLE *table= table_ref->table;
if (tables_to_update & table->map)
@ -1338,7 +1368,8 @@ int multi_update::prepare(List<Item> &not_used_values,
int error= setup_fields(thd, 0, *values, MARK_COLUMNS_READ, 0, 0);
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
ti.rewind();
while ((table_ref= ti++))
{
TABLE *table= table_ref->table;
if (tables_to_update & table->map)
@ -1367,7 +1398,8 @@ int multi_update::prepare(List<Item> &not_used_values,
*/
update.empty();
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
ti.rewind();
while ((table_ref= ti++))
{
/* TODO: add support of view of join support */
TABLE *table=table_ref->table;
@ -1593,9 +1625,9 @@ loop_end:
{
table_map unupdated_tables= table_ref->check_option->used_tables() &
~first_table_for_update->map;
for (TABLE_LIST *tbl_ref =leaves;
unupdated_tables && tbl_ref;
tbl_ref= tbl_ref->next_leaf)
List_iterator<TABLE_LIST> ti(*leaves);
TABLE_LIST *tbl_ref;
while ((tbl_ref= ti++) && unupdated_tables)
{
if (unupdated_tables & tbl_ref->table->map)
unupdated_tables&= ~tbl_ref->table->map;

View file

@ -248,7 +248,7 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
view->definer.user= decoy.definer.user;
lex->definer= &view->definer;
}
if (lex->create_view_algorithm == VIEW_ALGORITHM_UNDEFINED)
if (lex->create_view_algorithm == DTYPE_ALGORITHM_UNDEFINED)
lex->create_view_algorithm= (uint8) decoy.algorithm;
if (lex->create_view_suid == VIEW_SUID_DEFAULT)
lex->create_view_suid= decoy.view_suid ?
@ -843,7 +843,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
ulong sql_mode= thd->variables.sql_mode & MODE_ANSI_QUOTES;
thd->variables.sql_mode&= ~MODE_ANSI_QUOTES;
lex->unit.print(&view_query, QT_ORDINARY);
lex->unit.print(&view_query, QT_VIEW_INTERNAL);
lex->unit.print(&is_query, QT_IS);
thd->variables.sql_mode|= sql_mode;
@ -876,7 +876,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE,
ER(ER_WARN_VIEW_MERGE));
lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
}
view->algorithm= lex->create_view_algorithm;
view->definer.user= lex->definer->user;
@ -1460,7 +1460,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list);
table->effective_algorithm= VIEW_ALGORITHM_MERGE;
table->derived_type= VIEW_ALGORITHM_MERGE;
DBUG_PRINT("info", ("algorithm: MERGE"));
table->updatable= (table->updatable_view != 0);
table->effective_with_check=
@ -1474,67 +1474,10 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
/* prepare view context */
lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables);
lex->select_lex.context.outer_context= 0;
lex->select_lex.context.select_lex= table->select_lex;
lex->select_lex.select_n_having_items+=
table->select_lex->select_n_having_items;
/*
Tables of the main select of the view should be marked as belonging
to the same select as original view (again we can use LEX::select_lex
for this purprose because we don't support MERGE algorithm for views
with unions).
*/
for (tbl= lex->select_lex.get_table_list(); tbl; tbl= tbl->next_local)
tbl->select_lex= table->select_lex;
{
if (view_main_select_tables->next_local)
{
table->multitable_view= TRUE;
if (table->belong_to_view)
table->belong_to_view->multitable_view= TRUE;
}
/* make nested join structure for view tables */
NESTED_JOIN *nested_join;
if (!(nested_join= table->nested_join=
(NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN))))
goto err;
nested_join->join_list= view_select->top_join_list;
/* re-nest tables of VIEW */
ti.rewind();
while ((tbl= ti++))
{
tbl->join_list= &nested_join->join_list;
tbl->embedding= table;
}
}
/* Store WHERE clause for post-processing in setup_underlying */
table->where= view_select->where;
/*
Add subqueries units to SELECT into which we merging current view.
unit(->next)* chain starts with subqueries that are used by this
view and continues with subqueries that are used by other views.
We must not add any subquery twice (otherwise we'll form a loop),
to do this we remember in end_unit the first subquery that has
been already added.
NOTE: we do not support UNION here, so we take only one select
*/
SELECT_LEX_NODE *end_unit= table->select_lex->slave;
SELECT_LEX_UNIT *next_unit;
for (SELECT_LEX_UNIT *unit= lex->select_lex.first_inner_unit();
unit;
unit= next_unit)
{
if (unit == end_unit)
break;
SELECT_LEX_NODE *save_slave= unit->slave;
next_unit= unit->next_unit();
unit->include_down(table->select_lex);
unit->slave= save_slave; // fix include_down initialisation
}
/*
We can safely ignore the VIEW's ORDER BY if we merge into union
@ -1551,23 +1494,22 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
goto ok;
}
table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE;
table->derived_type= VIEW_ALGORITHM_TMPTABLE;
DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
view_select->linkage= DERIVED_TABLE_TYPE;
table->updatable= 0;
table->effective_with_check= VIEW_CHECK_NONE;
old_lex->subqueries= TRUE;
/* SELECT tree link */
lex->unit.include_down(table->select_lex);
lex->unit.slave= view_select; // fix include_down initialisation
table->derived= &lex->unit;
}
else
goto err;
ok:
/* SELECT tree link */
lex->unit.include_down(table->select_lex);
lex->unit.slave= view_select; // fix include_down initialisation
/* global SELECT list linking */
end= view_select; // primary SELECT_LEX is always last
end->link_next= old_lex->all_selects_list;

View file

@ -1945,7 +1945,7 @@ create:
| CREATE
{
Lex->create_view_mode= VIEW_CREATE_NEW;
Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
Lex->create_view_suid= TRUE;
}
view_or_trigger_or_sp_or_event
@ -5993,7 +5993,7 @@ alter:
my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
MYSQL_YYABORT;
}
lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED;
lex->create_view_mode= VIEW_ALTER;
}
view_tail
@ -13740,7 +13740,7 @@ view_replace:
view_algorithm:
ALGORITHM_SYM EQ UNDEFINED_SYM
{ Lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED; }
{ Lex->create_view_algorithm= DTYPE_ALGORITHM_UNDEFINED; }
| ALGORITHM_SYM EQ MERGE_SYM
{ Lex->create_view_algorithm= VIEW_ALGORITHM_MERGE; }
| ALGORITHM_SYM EQ TEMPTABLE_SYM

View file

@ -3513,129 +3513,112 @@ void TABLE_LIST::calc_md5(char *buffer)
/**
@brief Set underlying table for table place holder of view.
@brief
Create field translation for mergeable derived table/view.
@details
@param thd Thread handle
Replace all views that only use one table with the table itself. This
allows us to treat the view as a simple table and even update it (it is a
kind of optimization).
@details
Create field translation for mergeable derived table/view.
@note
This optimization is potentially dangerous as it makes views
masquerade as base tables: Views don't have the pointer TABLE_LIST::table
set to non-@c NULL.
We may have the case where a view accesses tables not normally accessible
in the current Security_context (only in the definer's
Security_context). According to the table's GRANT_INFO (TABLE::grant),
access is fulfilled, but this is implicitly meant in the definer's security
context. Hence we must never look at only a TABLE's GRANT_INFO without
looking at the one of the referring TABLE_LIST.
@return FALSE ok.
@return TRUE an error occur.
*/
void TABLE_LIST::set_underlying_merge()
bool TABLE_LIST::create_field_translation(THD *thd)
{
TABLE_LIST *tbl;
Item *item;
Field_translator *transl;
SELECT_LEX *select= get_single_select();
List_iterator_fast<Item> it(select->item_list);
uint field_count= 0;
Query_arena *arena= thd->stmt_arena, backup;
bool res= FALSE;
if ((tbl= merge_underlying_list))
used_items.empty();
if (field_translation)
{
/* This is a view. Process all tables of view */
DBUG_ASSERT(view && effective_algorithm == VIEW_ALGORITHM_MERGE);
do
/*
Update items in the field translation aftet view have been prepared.
It's needed because some items in the select list, like IN subselects,
might be substituted for optimized ones.
*/
if (is_view() && get_unit()->prepared && !field_translation_updated)
{
if (tbl->merge_underlying_list) // This is a view
while ((item= it++))
{
DBUG_ASSERT(tbl->view &&
tbl->effective_algorithm == VIEW_ALGORITHM_MERGE);
/*
This is the only case where set_ancestor is called on an object
that may not be a view (in which case ancestor is 0)
*/
tbl->merge_underlying_list->set_underlying_merge();
field_translation[field_count++].item= item;
}
} while ((tbl= tbl->next_local));
if (!multitable_view)
{
table= merge_underlying_list->table;
schema_table= merge_underlying_list->schema_table;
field_translation_updated= TRUE;
}
return FALSE;
}
if (arena->is_conventional())
arena= 0; // For easier test
else
thd->set_n_backup_active_arena(arena, &backup);
/* Create view fields translation table */
if (!(transl=
(Field_translator*)(thd->stmt_arena->
alloc(select->item_list.elements *
sizeof(Field_translator)))))
{
res= TRUE;
goto exit;
}
while ((item= it++))
{
transl[field_count].name= item->name;
transl[field_count++].item= item;
}
field_translation= transl;
field_translation_end= transl + field_count;
exit:
if (arena)
thd->restore_active_arena(arena, &backup);
return res;
}
/*
setup fields of placeholder of merged VIEW
/**
@brief
Create field translation for mergeable derived table/view.
SYNOPSIS
TABLE_LIST::setup_underlying()
thd - thread handler
@param thd Thread handle
DESCRIPTION
It is:
- preparing translation table for view columns
If there are underlying view(s) procedure first will be called for them.
@details
Create field translation for mergeable derived table/view.
RETURN
FALSE - OK
TRUE - error
@return FALSE ok.
@return TRUE an error occur.
*/
bool TABLE_LIST::setup_underlying(THD *thd)
{
DBUG_ENTER("TABLE_LIST::setup_underlying");
if (!field_translation && merge_underlying_list)
if (!view || (!field_translation && merge_underlying_list))
{
Field_translator *transl;
SELECT_LEX *select= &view->select_lex;
Item *item;
TABLE_LIST *tbl;
List_iterator_fast<Item> it(select->item_list);
uint field_count= 0;
if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*) &field_count))
{
SELECT_LEX *select= get_single_select();
if (create_field_translation(thd))
DBUG_RETURN(TRUE);
}
for (tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
{
if (tbl->merge_underlying_list &&
tbl->setup_underlying(thd))
{
DBUG_RETURN(TRUE);
}
}
/* Create view fields translation table */
if (!(transl=
(Field_translator*)(thd->stmt_arena->
alloc(select->item_list.elements *
sizeof(Field_translator)))))
{
DBUG_RETURN(TRUE);
}
while ((item= it++))
{
transl[field_count].name= item->name;
transl[field_count++].item= item;
}
field_translation= transl;
field_translation_end= transl + field_count;
/* TODO: use hash for big number of fields */
/* full text function moving to current select */
if (view->select_lex.ftfunc_list->elements)
if (select->ftfunc_list->elements)
{
Item_func_match *ifm;
SELECT_LEX *current_select= thd->lex->current_select;
List_iterator_fast<Item_func_match>
li(*(view->select_lex.ftfunc_list));
li(*(select_lex->ftfunc_list));
while ((ifm= li++))
current_select->ftfunc_list->push_front(ifm);
}
@ -3645,7 +3628,7 @@ bool TABLE_LIST::setup_underlying(THD *thd)
/*
Prepare where expression of view
Prepare where expression of derived table/view
SYNOPSIS
TABLE_LIST::prep_where()
@ -3669,7 +3652,8 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds,
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
{
if (tbl->view && tbl->prep_where(thd, conds, no_where_clause))
if (tbl->is_view_or_derived() &&
tbl->prep_where(thd, conds, no_where_clause))
{
DBUG_RETURN(TRUE);
}
@ -3677,6 +3661,8 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds,
if (where)
{
if (where->fixed)
where->update_used_tables();
if (!where->fixed && where->fix_fields(thd, &where))
{
DBUG_RETURN(TRUE);
@ -3709,7 +3695,13 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds,
}
}
if (tbl == 0)
{
if (*conds && !(*conds)->fixed)
(*conds)->fix_fields(thd, conds);
*conds= and_conds(*conds, where->copy_andor_structure(thd));
if (*conds && !(*conds)->fixed)
(*conds)->fix_fields(thd, conds);
}
if (arena)
thd->restore_active_arena(arena, &backup);
where_processed= TRUE;
@ -3748,10 +3740,11 @@ merge_on_conds(THD *thd, TABLE_LIST *table, bool is_cascaded)
DBUG_PRINT("info", ("alias: %s", table->alias));
if (table->on_expr)
cond= table->on_expr->copy_andor_structure(thd);
if (!table->nested_join)
if (!table->view)
DBUG_RETURN(cond);
List_iterator<TABLE_LIST> li(table->nested_join->join_list);
while (TABLE_LIST *tbl= li++)
for (TABLE_LIST *tbl= (TABLE_LIST*)table->view->select_lex.table_list.first;
tbl;
tbl= tbl->next_local)
{
if (tbl->view && !is_cascaded)
continue;
@ -3791,7 +3784,7 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type)
{
DBUG_ENTER("TABLE_LIST::prep_check_option");
bool is_cascaded= check_opt_type == VIEW_CHECK_CASCADED;
TABLE_LIST *merge_underlying_list= view->select_lex.get_table_list();
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
{
/* see comment of check_opt_type parameter */
@ -3808,7 +3801,6 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type)
if (where)
{
DBUG_ASSERT(where->fixed);
check_option= where->copy_andor_structure(thd);
}
if (is_cascaded)
@ -3904,10 +3896,14 @@ void TABLE_LIST::hide_view_error(THD *thd)
TABLE_LIST *TABLE_LIST::find_underlying_table(TABLE *table_to_find)
{
/* is this real table and table which we are looking for? */
if (table == table_to_find && merge_underlying_list == 0)
if (table == table_to_find && view == 0)
return this;
if (!view)
return 0;
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
for (TABLE_LIST *tbl= view->select_lex.get_table_list();
tbl;
tbl= tbl->next_local)
{
TABLE_LIST *result;
if ((result= tbl->find_underlying_table(table_to_find)))
@ -3989,7 +3985,12 @@ bool TABLE_LIST::check_single_table(TABLE_LIST **table_arg,
table_map map,
TABLE_LIST *view_arg)
{
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
if (!select_lex)
return FALSE;
DBUG_ASSERT(is_merged_derived());
for (TABLE_LIST *tbl= get_single_select()->get_table_list();
tbl;
tbl= tbl->next_local)
{
if (tbl->table)
{
@ -4031,8 +4032,10 @@ bool TABLE_LIST::set_insert_values(MEM_ROOT *mem_root)
}
else
{
DBUG_ASSERT(view && merge_underlying_list);
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
DBUG_ASSERT(is_view_or_derived() && is_merged_derived());
for (TABLE_LIST *tbl= (TABLE_LIST*)view->select_lex.table_list.first;
tbl;
tbl= tbl->next_local)
if (tbl->set_insert_values(mem_root))
return TRUE;
}
@ -4058,7 +4061,7 @@ bool TABLE_LIST::set_insert_values(MEM_ROOT *mem_root)
*/
bool TABLE_LIST::is_leaf_for_name_resolution()
{
return (view || is_natural_join || is_join_columns_complete ||
return (is_merged_derived() || is_natural_join || is_join_columns_complete ||
!nested_join);
}
@ -4196,7 +4199,11 @@ void TABLE_LIST::register_want_access(ulong want_access)
if (table)
table->grant.want_privilege= want_access;
}
for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local)
if (!view)
return;
for (TABLE_LIST *tbl= view->select_lex.get_table_list();
tbl;
tbl= tbl->next_local)
tbl->register_want_access(want_access);
}
@ -4426,14 +4433,23 @@ const char *Natural_join_column::db_name()
DBUG_ASSERT(!strcmp(table_ref->db,
table_ref->table->s->db.str) ||
(table_ref->schema_table &&
table_ref->table->s->db.str[0] == 0));
table_ref->table->s->db.str[0] == 0) ||
table_ref->is_materialized_derived());
return table_ref->db;
}
GRANT_INFO *Natural_join_column::grant()
{
if (view_field)
/* if (view_field)
return &(table_ref->grant);
return &(table_ref->table->grant);*/
/*
Have to check algorithm because merged derived also has
field_translation.
*/
//if (table_ref->effective_algorithm == DTYPE_ALGORITHM_MERGE)
if (table_ref->is_merged_derived())
return &(table_ref->grant);
return &(table_ref->table->grant);
}
@ -4514,7 +4530,17 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
{
DBUG_RETURN(field);
}
Item *item= new Item_direct_view_ref(view, field_ref, name);
Item *item= new Item_direct_view_ref(&view->view->select_lex.context,
field_ref, view->alias,
name, view);
/*
Force creation of nullable item for the result tmp table for outer joined
views/derived tables.
*/
if (view->outer_join)
item->maybe_null= TRUE;
/* Save item in case we will need to fall back to materialization. */
view->used_items.push_back(item);
DBUG_RETURN(item);
}
@ -4568,8 +4594,7 @@ void Field_iterator_table_ref::set_field_iterator()
/* This is a merge view, so use field_translation. */
else if (table_ref->field_translation)
{
DBUG_ASSERT(table_ref->view &&
table_ref->effective_algorithm == VIEW_ALGORITHM_MERGE);
DBUG_ASSERT(table_ref->is_merged_derived());
field_it= &view_field_it;
DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_view",
table_ref->alias));
@ -5193,15 +5218,16 @@ void st_table::mark_virtual_columns_for_write(bool insert_fl)
/**
@brief
Allocate space for keys
@param key_count number of keys to allocate.
@param key_count number of keys to allocate
@details
Allocates space enough to fit 'key_count' keys for this table.
The function allocates memory to fit 'key_count' keys for this table.
@return FALSE space was successfully allocated.
@return TRUE an error occur.
@return FALSE space was successfully allocated
@return TRUE an error occur
*/
bool TABLE::alloc_keys(uint key_count)
@ -5260,22 +5286,24 @@ void TABLE::create_key_part_by_field(KEY *keyinfo,
/**
Add a key to a temporary table
@brief
Add one key to a temporary table
@param key the number of the key
@param key_parts number of components of the key
@param next_field_no the call-back function that returns the number of
the field used as the next component of the key
@param arg the argument for the above function
@param unique Is it unique index
@param unique TRUE <=> it is a unique index
@details
The function adds a new key to the table that is assumed to be
temprary table. The call-back function must at each call must return
the number of the field that used as next component of this key
The function adds a new key to the table that is assumed to be a temporary
table. At each its invocation the call-back function must return
the number of the field that is used as the next component of this key.
@return FALSE is a success
@return TRUE if a failure
*/
bool TABLE::add_tmp_key(uint key, uint key_parts,
@ -5326,6 +5354,31 @@ bool TABLE::add_tmp_key(uint key, uint key_parts,
return FALSE;
}
/*
@brief
Drop all indexes except specified one.
@param key_to_save the key to save
@details
Drop all indexes on this table except 'key_to_save'. The saved key becomes
key #0. Memory occupied by key parts of dropped keys are freed.
If the 'key_to_save' is negative then all keys are freed.
*/
void TABLE::use_index(int key_to_save)
{
uint i= 1;
DBUG_ASSERT(!created && key_to_save < (int)s->keys);
if (key_to_save >= 0)
/* Save the given key. */
memcpy(key_info, key_info + key_to_save, sizeof(KEY));
else
/* Drop all keys; */
i= 0;
s->keys= (key_to_save < 0) ? 0 : 1;
}
/**
@brief Check if this is part of a MERGE table with attached children.
@ -5388,6 +5441,7 @@ void TABLE_LIST::reinit_before_use(THD *thd)
parent_embedding->nested_join->join_list.head() == embedded);
}
/*
Return subselect that contains the FROM list this table is taken from
@ -5659,6 +5713,296 @@ int update_virtual_fields(THD *thd, TABLE *table, bool for_write)
DBUG_RETURN(0);
}
/*
@brief Reset const_table flag
@detail
Reset const_table flag for this table. If this table is a merged derived
table/view the flag is recursively reseted for all tables of the underlying
select.
*/
void TABLE_LIST::reset_const_table()
{
table->const_table= 0;
if (is_merged_derived())
{
SELECT_LEX *select_lex= get_unit()->first_select();
TABLE_LIST *tl;
List_iterator<TABLE_LIST> ti(select_lex->leaf_tables);
while ((tl= ti++))
tl->reset_const_table();
}
}
/*
@brief Run derived tables/view handling phases on underlying select_lex.
@param lex LEX for this thread
@param phases derived tables/views handling phases to run
(set of DT_XXX constants)
@details
This function runs this derived table through specified 'phases'.
Underlying tables of this select are handled prior to this derived.
'lex' is passed as an argument to called functions.
@return TRUE on error
@return FALSE ok
*/
bool TABLE_LIST::handle_derived(struct st_lex *lex, uint phases)
{
SELECT_LEX_UNIT *unit= get_unit();
if (unit)
{
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
if (sl->handle_derived(lex, phases))
return TRUE;
return mysql_handle_single_derived(lex, this, phases);
}
return FALSE;
}
/**
@brief
Return unit of this derived table/view
@return reference to a unit if it's a derived table/view.
@return 0 when it's not a derived table/view.
*/
st_select_lex_unit *TABLE_LIST::get_unit()
{
return (view ? &view->unit : derived);
}
/**
@brief
Return select_lex of this derived table/view
@return select_lex of this derived table/view.
@return 0 when it's not a derived table.
*/
st_select_lex *TABLE_LIST::get_single_select()
{
SELECT_LEX_UNIT *unit= get_unit();
return (unit ? unit->first_select() : 0);
}
/**
@brief
Attach a join table list as a nested join to this TABLE_LIST.
@param join_list join table list to attach
@details
This function wraps 'join_list' into a nested_join of this table, thus
turning it to a nested join leaf.
*/
void TABLE_LIST::wrap_into_nested_join(List<TABLE_LIST> &join_list)
{
TABLE_LIST *tl;
/*
Walk through derived table top list and set 'embedding' to point to
the nesting table.
*/
nested_join->join_list.empty();
List_iterator_fast<TABLE_LIST> li(join_list);
nested_join->join_list= join_list;
while ((tl= li++))
{
tl->embedding= this;
tl->join_list= &nested_join->join_list;
}
}
/**
@brief
Initialize this derived table/view
@param thd Thread handle
@details
This function makes initial preparations of this derived table/view for
further processing:
if it's a derived table this function marks it either as mergeable or
materializable
creates temporary table for name resolution purposes
creates field translation for mergeable derived table/view
@return TRUE an error occur
@return FALSE ok
*/
bool TABLE_LIST::init_derived(THD *thd, bool init_view)
{
SELECT_LEX *first_select= get_single_select();
SELECT_LEX_UNIT *unit= get_unit();
if (!unit)
return FALSE;
/*
Check whether we can merge this derived table into main select.
Depending on the result field translation will or will not
be created.
*/
TABLE_LIST *first_table= (TABLE_LIST *) first_select->table_list.first;
if (first_select->table_list.elements > 1 ||
(first_table && first_table->is_multitable()))
set_multitable();
unit->derived= this;
if (init_view && !view)
{
/* This is all what we can do for a derived table for now. */
set_derived();
}
if (!is_view())
{
/* A subquery might be forced to be materialized due to a side-effect. */
if (!is_materialized_derived() && first_select->is_mergeable() &&
!(thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
thd->lex->sql_command == SQLCOM_UPDATE))
set_merged_derived();
else
set_materialized_derived();
}
/*
Derived tables/view are materialized prior to UPDATE, thus we can skip
them from table uniqueness check
*/
if (is_materialized_derived())
{
unit->master_unit()->set_unique_exclude();
}
/*
Create field translation for mergeable derived tables/views.
For derived tables field translation can be created only after
unit is prepared so all '*' are get unrolled.
*/
if (is_merged_derived())
{
if (is_view() || unit->prepared)
create_field_translation(thd);
}
return FALSE;
}
/**
@brief
Retrieve number of rows in the table
@details
Retrieve number of rows in the table referred by this TABLE_LIST and
store it in the table's stats.records variable. If this TABLE_LIST refers
to a materialized derived table/view then the estimated number of rows of
the derived table/view is used instead.
@return 0 ok
@return non zero error
*/
int TABLE_LIST::fetch_number_of_rows()
{
int error= 0;
if (is_materialized_derived() && !fill_me)
{
table->file->stats.records= ((select_union*)derived->result)->records;
set_if_bigger(table->file->stats.records, 2);
}
else
error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return error;
}
/*
Procedure of keys generation for result tables of materialized derived
tables/views.
A key is generated for each equi-join pair derived table-another table.
Each generated key consists of fields of derived table used in equi-join.
Example:
SELECT * FROM (SELECT * FROM t1 GROUP BY 1) tt JOIN
t1 ON tt.f1=t1.f3 and tt.f2.=t1.f4;
In this case for the derived table tt one key will be generated. It will
consist of two parts f1 and f2.
Example:
SELECT * FROM (SELECT * FROM t1 GROUP BY 1) tt JOIN
t1 ON tt.f1=t1.f3 JOIN
t2 ON tt.f2=t2.f4;
In this case for the derived table tt two keys will be generated.
One key over f1 field, and another key over f2 field.
Currently optimizer may choose to use only one such key, thus the second
one will be dropped after range optimizer is finished.
See also JOIN::drop_unused_derived_keys function.
Example:
SELECT * FROM (SELECT * FROM t1 GROUP BY 1) tt JOIN
t1 ON tt.f1=a_function(t1.f3);
In this case for the derived table tt one key will be generated. It will
consist of one field - f1.
*/
/*
@brief
Change references to underlying items of a merged derived table/view
for fields in derived table's result table.
@return FALSE ok
@return TRUE Out of memory
*/
bool TABLE_LIST::change_refs_to_fields()
{
List_iterator<Item> li(used_items);
Item_direct_ref *ref;
Field_iterator_view field_it;
THD *thd= table->in_use;
DBUG_ASSERT(is_merged_derived());
if (!used_items.elements)
return FALSE;
materialized_items= (Item**)thd->calloc(sizeof(void*) * table->s->fields);
while ((ref= (Item_direct_ref*)li++))
{
uint idx;
Item *orig_item= *ref->ref;
field_it.set(this);
for (idx= 0; !field_it.end_of_fields(); field_it.next(), idx++)
{
if (field_it.item() == orig_item)
break;
}
DBUG_ASSERT(!field_it.end_of_fields());
if (!materialized_items[idx])
{
materialized_items[idx]= new Item_field(table->field[idx]);
if (!materialized_items[idx])
return TRUE;
}
ref->ref= materialized_items + idx;
}
return FALSE;
}
/*****************************************************************************
** Instansiate templates
*****************************************************************************/

View file

@ -791,7 +791,6 @@ struct st_table {
uint temp_pool_slot; /* Used by intern temp tables */
uint status; /* What's in record[0] */
uint db_stat; /* mode of file as in handler.h */
uint max_keys; /* Size of allocated key_info array. */
/* number of select if it is derived table */
uint derived_select_number;
int current_lock; /* Type of lock on table */
@ -867,8 +866,10 @@ struct st_table {
*/
bool auto_increment_field_not_null;
bool insert_or_update; /* Can be used by the handler */
bool alias_name_used; /* true if table_name is alias */
bool alias_name_used; /* true if table_name is alias */
bool get_fields_in_item_tree; /* Signal to fix_field */
bool created; /* For tmp tables. TRUE <=> tmp table was actually created.*/
/* If MERGE children attached to parent. See top comment in ha_myisammrg.cc */
bool children_attached;
@ -889,6 +890,7 @@ struct st_table {
bool no_partitions_used; /* If true, all partitions have been pruned away */
#endif
uint max_keys; /* Size of allocated key_info array. */
bool fill_item_list(List<Item> *item_list) const;
void reset_item_list(List<Item> *item_list) const;
void clear_column_bitmaps(void);
@ -958,6 +960,12 @@ struct st_table {
bool unique);
void create_key_part_by_field(KEY *keyinfo, KEY_PART_INFO *key_part_info,
Field *field);
void use_index(int key_to_save);
void set_table_map(table_map map_arg, uint tablenr_arg)
{
map= map_arg;
tablenr= tablenr_arg;
}
bool is_children_attached(void);
inline void enable_keyread()
{
@ -1115,13 +1123,52 @@ typedef struct st_schema_table
} ST_SCHEMA_TABLE;
/*
Types of derived tables. The ending part is a bitmap of phases that are
applicable to a derived table of the type.
* /
#define VIEW_ALGORITHM_UNDEFINED 0
#define VIEW_ALGORITHM_MERGE 1 + DT_COMMON + DT_MERGE
#define DERIVED_ALGORITHM_MERGE 2 + DT_COMMON + DT_MERGE
#define VIEW_ALGORITHM_TMPTABLE 3 + DT_COMMON + DT_MATERIALIZE
#define DERIVED_ALGORITHM_MATERIALIZE 4 + DT_COMMON + DT_MATERIALIZE
*/
#define DTYPE_ALGORITHM_UNDEFINED 0
#define DTYPE_VIEW 1
#define DTYPE_TABLE 2
#define DTYPE_MERGE 4
#define DTYPE_MATERIALIZE 8
#define DTYPE_MULTITABLE 16
#define DTYPE_MASK 19
/*
Phases of derived tables/views handling, see sql_derived.cc
Values are used as parts of a bitmap attached to derived table types.
*/
#define DT_INIT 1
#define DT_PREPARE 2
#define DT_OPTIMIZE 4
#define DT_MERGE 8
#define DT_MERGE_FOR_INSERT 16
#define DT_CREATE 32
#define DT_FILL 64
#define DT_REINIT 128
#define DT_PHASES 8
/* Phases that are applicable to all derived tables. */
#define DT_COMMON (DT_INIT + DT_PREPARE + DT_REINIT + DT_OPTIMIZE)
/* Phases that are applicable only to materialized derived tables. */
#define DT_MATERIALIZE (DT_CREATE + DT_FILL)
#define DT_PHASES_MERGE (DT_COMMON | DT_MERGE | DT_MERGE_FOR_INSERT)
#define DT_PHASES_MATERIALIZE (DT_COMMON | DT_MATERIALIZE)
#define VIEW_ALGORITHM_UNDEFINED 0
#define VIEW_ALGORITHM_MERGE (DTYPE_VIEW | DTYPE_MERGE)
#define VIEW_ALGORITHM_TMPTABLE (DTYPE_VIEW + DTYPE_MATERIALIZE )
#define JOIN_TYPE_LEFT 1
#define JOIN_TYPE_RIGHT 2
#define VIEW_ALGORITHM_UNDEFINED 0
#define VIEW_ALGORITHM_TMPTABLE 1
#define VIEW_ALGORITHM_MERGE 2
#define VIEW_SUID_INVOKER 0
#define VIEW_SUID_DEFINER 1
#define VIEW_SUID_DEFAULT 2
@ -1211,6 +1258,7 @@ class Item_in_subselect;
also (TABLE_LIST::field_translation != NULL)
- tmptable (TABLE_LIST::effective_algorithm == VIEW_ALGORITHM_TMPTABLE)
also (TABLE_LIST::field_translation == NULL)
2.5) TODO: Add derived tables description here
3) nested table reference (TABLE_LIST::nested_join != NULL)
- table sequence - e.g. (t1, t2, t3)
TODO: how to distinguish from a JOIN?
@ -1225,6 +1273,7 @@ class Item_in_subselect;
*/
class Index_hint;
struct st_lex;
struct TABLE_LIST
{
TABLE_LIST() {} /* Remove gcc warning */
@ -1325,6 +1374,8 @@ struct TABLE_LIST
filling procedure
*/
select_union *derived_result;
/* Stub used for materialized derived tables. */
table_map map; /* ID bit of table (1,2,4,8,16...) */
/*
Reference from aux_tables to local list entry of main select of
multi-delete statement:
@ -1369,6 +1420,7 @@ struct TABLE_LIST
Field_translator *field_translation; /* array of VIEW fields */
/* pointer to element after last one in translation table above */
Field_translator *field_translation_end;
bool field_translation_updated;
/*
List (based on next_local) of underlying tables of this view. I.e. it
does not include the tables of subqueries used in the view. Is set only
@ -1383,11 +1435,18 @@ struct TABLE_LIST
List<TABLE_LIST> *view_tables;
/* most upper view this table belongs to */
TABLE_LIST *belong_to_view;
/* A derived table this table belongs to */
TABLE_LIST *belong_to_derived;
/*
The view directly referencing this table
(non-zero only for merged underlying tables of a view).
*/
TABLE_LIST *referencing_view;
table_map view_used_tables;
table_map map_exec;
uint tablenr_exec;
/* Ptr to parent MERGE table list item. See top comment in ha_myisammrg.cc */
TABLE_LIST *parent_l;
/*
@ -1400,13 +1459,7 @@ struct TABLE_LIST
SQL SECURITY DEFINER)
*/
Security_context *view_sctx;
/*
List of all base tables local to a subquery including all view
tables. Unlike 'next_local', this in this list views are *not*
leaves. Created in setup_tables() -> make_leaves_list().
*/
bool allowed_show;
TABLE_LIST *next_leaf;
Item *where; /* VIEW WHERE clause condition */
Item *check_option; /* WITH CHECK OPTION condition */
LEX_STRING select_stmt; /* text of (CREATE/SELECT) statement */
@ -1442,7 +1495,7 @@ struct TABLE_LIST
- VIEW_ALGORITHM_MERGE
@to do Replace with an enum
*/
uint8 effective_algorithm;
uint8 derived_type;
GRANT_INFO grant;
/* data need by some engines in query cache*/
ulonglong engine_data;
@ -1469,7 +1522,6 @@ struct TABLE_LIST
bool skip_temporary; /* this table shouldn't be temporary */
/* TRUE if this merged view contain auto_increment field */
bool contain_auto_increment;
bool multitable_view; /* TRUE iff this is multitable view */
bool compact_view_format; /* Use compact format for SHOW CREATE VIEW */
/* view where processed */
bool where_processed;
@ -1493,6 +1545,17 @@ struct TABLE_LIST
bool internal_tmp_table;
bool deleting; /* going to delete this table */
/* TRUE <=> derived table should be filled right after optimization. */
bool fill_me;
/* TRUE <=> view/DT is merged. */
bool merged;
bool merged_for_insert;
/* TRUE <=> don't prepare this derived table/view as it should be merged.*/
bool skip_prepare_derived;
List<Item> used_items;
Item **materialized_items;
/* View creation context. */
View_creation_ctx *view_creation_ctx;
@ -1530,9 +1593,10 @@ struct TABLE_LIST
bool has_table_lookup_value;
uint table_open_method;
enum enum_schema_table_state schema_table_state;
void calc_md5(char *buffer);
void set_underlying_merge();
int view_check_option(THD *thd, bool ignore_failure);
bool create_field_translation(THD *thd);
bool setup_underlying(THD *thd);
void cleanup_items();
bool placeholder()
@ -1562,7 +1626,7 @@ struct TABLE_LIST
inline bool prepare_where(THD *thd, Item **conds,
bool no_where_clause)
{
if (effective_algorithm == VIEW_ALGORITHM_MERGE)
if (!view || is_merged_derived())
return prep_where(thd, conds, no_where_clause);
return FALSE;
}
@ -1628,6 +1692,60 @@ struct TABLE_LIST
m_table_ref_version= s->get_table_ref_version();
}
/* Set of functions returning/setting state of a derived table/view. */
inline bool is_non_derived()
{
return (!derived_type);
}
inline bool is_view_or_derived()
{
return (derived_type);
}
inline bool is_view()
{
return (derived_type & DTYPE_VIEW);
}
inline bool is_derived()
{
return (derived_type & DTYPE_TABLE);
}
inline void set_view()
{
derived_type= DTYPE_VIEW;
}
inline void set_derived()
{
derived_type= DTYPE_TABLE;
}
inline bool is_merged_derived()
{
return (derived_type & DTYPE_MERGE);
}
inline void set_merged_derived()
{
derived_type= ((derived_type & DTYPE_MASK) |
DTYPE_TABLE | DTYPE_MERGE);
}
inline bool is_materialized_derived()
{
return (derived_type & DTYPE_MATERIALIZE);
}
inline void set_materialized_derived()
{
derived_type= ((derived_type & DTYPE_MASK) |
DTYPE_TABLE | DTYPE_MATERIALIZE);
}
inline bool is_multitable()
{
return (derived_type & DTYPE_MULTITABLE);
}
inline void set_multitable()
{
derived_type|= DTYPE_MULTITABLE;
}
void reset_const_table();
bool handle_derived(struct st_lex *lex, uint phases);
/**
@brief True if this TABLE_LIST represents an anonymous derived table,
i.e. the result of a subquery.
@ -1647,6 +1765,12 @@ struct TABLE_LIST
respectively.
*/
char *get_table_name() { return view != NULL ? view_name.str : table_name; }
st_select_lex_unit *get_unit();
st_select_lex *get_single_select();
void wrap_into_nested_join(List<TABLE_LIST> &join_list);
bool init_derived(THD *thd, bool init_view);
int fetch_number_of_rows();
bool change_refs_to_fields();
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);

View file

@ -383,6 +383,10 @@ void ha_heap::position(const uchar *record)
int ha_heap::info(uint flag)
{
HEAPINFO hp_info;
if (!table)
return 1;
(void) heap_info(file,&hp_info,flag);
errkey= hp_info.errkey;

View file

@ -2357,7 +2357,7 @@ void ha_maria::position(const uchar *record)
int ha_maria::info(uint flag)
{
return info(flag, table->s->tmp_table == NO_TMP_TABLE);
return (!table ? 1 : info(flag, table->s->tmp_table == NO_TMP_TABLE));
}
int ha_maria::info(uint flag, my_bool lock_table_share)

View file

@ -1867,6 +1867,9 @@ int ha_myisam::info(uint flag)
MI_ISAMINFO misam_info;
char name_buff[FN_REFLEN];
if (!table)
return 1;
(void) mi_status(file,&misam_info,flag);
if (flag & HA_STATUS_VARIABLE)
{