mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
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:
commit
f03a3ee54f
99 changed files with 4331 additions and 1089 deletions
|
@ -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),
|
||||
|
|
570
mysql-test/r/derived_view.result
Normal file
570
mysql-test/r/derived_view.result
Normal 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;
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
###
|
||||
|
|
|
@ -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
|
||||
###
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
217
mysql-test/t/derived_view.test
Normal file
217
mysql-test/t/derived_view.test
Normal 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;
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
24
sql/field.cc
24
sql/field.cc
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
121
sql/item.cc
121
sql/item.cc
|
@ -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
|
||||
*****************************************************************************/
|
||||
|
|
70
sql/item.h
70
sql/item.h
|
@ -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:
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++))
|
||||
|
|
224
sql/sql_base.cc
224
sql/sql_base.cc
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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;
|
||||
|
|
444
sql/sql_lex.cc
444
sql/sql_lex.cc
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -265,6 +265,8 @@ public:
|
|||
prev= &node->next;
|
||||
node= node->next;
|
||||
elements++;
|
||||
if (node == &end_of_list)
|
||||
return;
|
||||
}
|
||||
*prev= *last;
|
||||
last= prev;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
133
sql/sql_union.cc
133
sql/sql_union.cc
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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> ¬_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> ¬_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> ¬_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> ¬_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> ¬_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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
580
sql/table.cc
580
sql/table.cc
|
@ -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
|
||||
*****************************************************************************/
|
||||
|
|
156
sql/table.h
156
sql/table.h
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue