set optimizer_trace_max_mem_size=10000000,@@session.optimizer_trace="enabled=on"; # WL#461: allow outer references in derived tables and CTEs create table t1(a int, b int); insert into t1 (a) values(1),(2); create table t2 select * from t1; analyze table t1,t2; Table Op Msg_type Msg_text test.t1 analyze status OK test.t2 analyze status OK set optimizer_switch='derived_merge=on'; # Deep nesting: all intermediate subqueries are marked DEPENDENT explain select * from t1 where (select count(*) from (select * from (select * from t1 t2 where 2=(select 2 from (select t1.a) dt1))dt3)dt4); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 5 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 6 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #6 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (0 <> (/* select#2 */ select count(0) from `test`.`t1` `t2` where true)) select * from t1 where (select count(*) from (select * from (select * from t1 t2 where 2=(select 2 from (select t1.a) dt1))dt3)dt4); a b 1 NULL 2 NULL # If reference is removed, not DEPENDENT explain select * from t1 where (select count(*) from (select * from (select * from t1 t2 where 2=(select 2 from (select 42) dt1))dt3)dt4); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 SUBQUERY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 5 SUBQUERY NULL system NULL NULL NULL NULL 1 100.00 NULL 6 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where true select * from t1 where (select count(*) from (select * from (select * from t1 t2 where 2=(select 2 from (select 42) dt1))dt3)dt4); a b 1 NULL 2 NULL # Outer ref is in SELECT list of derived table's definition explain select (select dt.a from (select t1.a as a, t2.a as b from t2) dt where dt.b=t1.a) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 2 50.00 Using where Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t1`.`a` from `test`.`t2` where (`test`.`t2`.`a` = `test`.`t1`.`a`)) AS `subq` from `test`.`t1` select (select dt.a from (select t1.a as a, t2.a as b from t2) dt where dt.b=t1.a) as subq from t1; subq 1 2 # In WHERE explain select (select dt.b from (select t2.a as b from t2 where t1.a=t2.a) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 2 50.00 Using where Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t2`.`a` from `test`.`t2` where (`test`.`t1`.`a` = `test`.`t2`.`a`)) AS `subq` from `test`.`t1` select (select dt.b from (select t2.a as b from t2 where t1.a=t2.a) dt) as subq from t1; subq 1 2 # In GROUP BY explain select (select dt.b from (select sum(t2.a) as b from t2 group by t1.a) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using temporary Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select sum(`test`.`t2`.`a`) AS `b` from `test`.`t2` group by `test`.`t1`.`a`) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select sum(t2.a) as b from t2 group by t1.a) dt) as subq from t1; subq 3 3 # In HAVING explain select (select dt.b from (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-1) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 't1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select sum(`test`.`t2`.`a`) AS `b` from `test`.`t2` having (`test`.`t1`.`a` = (sum(`test`.`t2`.`a`) - 1))) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-1) dt) as subq from t1; subq NULL 3 explain select (select dt.b from (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-2) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 't1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select sum(`test`.`t2`.`a`) AS `b` from `test`.`t2` having (`test`.`t1`.`a` = (sum(`test`.`t2`.`a`) - 2))) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-2) dt) as subq from t1; subq 3 NULL # In ORDER BY explain select (select dt.b from (select t2.a as b from t2 order by if(t1.a=1,t2.a,-t2.a) limit 1) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select `test`.`t2`.`a` AS `b` from `test`.`t2` order by if((`test`.`t1`.`a` = 1),`test`.`t2`.`a`,-(`test`.`t2`.`a`)) limit 1) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select t2.a as b from t2 order by if(t1.a=1,t2.a,-t2.a) limit 1) dt) as subq from t1; subq 1 2 # In window functions explain select (select dt.b from (select t2.a, sum(t1.a*10+t2.a) over (order by if(t1.a=1,t2.a,-t2.a)) as b from t2) dt where dt.a=1) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 const 1 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using filesort Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 3598 To get information about window functions use EXPLAIN FORMAT=JSON Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select `test`.`t2`.`a` AS `a`,sum(((`test`.`t1`.`a` * 10) + `test`.`t2`.`a`)) OVER (ORDER BY if((`test`.`t1`.`a` = 1),`test`.`t2`.`a`,-(`test`.`t2`.`a`)) ) AS `b` from `test`.`t2`) `dt` where (`dt`.`a` = 1)) AS `subq` from `test`.`t1` select (select dt.b from (select t2.a, sum(t1.a*10+t2.a) over (order by if(t1.a=1,t2.a,-t2.a)) as b from t2) dt where dt.a=1) as subq from t1; subq 11 43 # CTE referenced twice explain select (with dt as (select t1.a as a, t2.a as b from t2) select dt2.a from dt dt1, dt dt2 where dt1.b=t1.a and dt2.b=dt1.b) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 2 50.00 Using where 2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 2 50.00 Using where; Using join buffer (Block Nested Loop) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #4 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `test`.`t1`.`a` from `test`.`t2` join `test`.`t2` where ((`test`.`t2`.`a` = `test`.`t2`.`a`) and (`test`.`t2`.`a` = `test`.`t1`.`a`))) AS `subq` from `test`.`t1` select (with dt as (select t1.a as a, t2.a as b from t2) select dt2.a from dt dt1, dt dt2 where dt1.b=t1.a and dt2.b=dt1.b) as subq from t1; subq 1 2 Recursive CTE select (with recursive dt as (select t1.a as a union select a+1 from dt where a<10) select dt1.a from dt dt1 where dt1.a=t1.a ) as subq from t1; subq 1 2 select (with recursive dt as (select t1.a as a union select a+1 from dt where a<10) select concat(count(*), ' - ', avg(dt.a)) from dt ) as subq from t1; subq 10 - 5.5000 9 - 6.0000 select (with recursive dt as (select t1.a as a union all select a+1 from dt where a<10) select concat(count(*), ' - ', avg(dt.a)) from dt ) as subq from t1; subq 10 - 5.5000 9 - 6.0000 select (with dt as (select t1.a as a, t2.a as b from t2) select dt2.a from dt dt1, dt dt2 where dt1.b=t1.a and dt2.b=dt1.b) as subq from t1; subq 1 2 # Two references to same CTE at different levels of nesting. explain select (with dt as (select t1.a as a from t2 limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 func 2 100.00 Using where; Using index 4 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #5 was resolved in SELECT #1 Note 1003 /* select#1 */ select (with `dt` as (/* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t2` limit 1) /* select#2 */ select `dt1`.`a` from `dt` `dt1` where (`dt1`.`a` = (/* select#4 */ select `dt2`.`a` from `dt` `dt2`))) AS `subq` from `test`.`t1` explain format=tree select (with dt as (select t1.a as a from t2 limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; EXPLAIN -> Table scan on t1 (cost=0.45 rows=2) -> Select #2 (subquery in projection; dependent) -> Filter: (dt1.a = (select #4)) -> Index lookup on dt1 using (a=(select #4)) -> Materialize CTE dt if needed -> Limit: 1 row(s) -> Table scan on t2 (cost=0.45 rows=2) -> Select #4 (subquery in condition; dependent) -> Table scan on dt2 -> Materialize CTE dt if needed (query plan printed elsewhere) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #5 was resolved in SELECT #1 select (with dt as (select t1.a as a from t2 limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; subq 1 2 explain select (with dt as (select t2.a as a from t2 having t1.a=t2.a limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 func 2 100.00 Using where; Using index 4 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 't1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 't1.a' of SELECT #5 was resolved in SELECT #1 Note 1003 /* select#1 */ select (with `dt` as (/* select#3 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` having (`test`.`t1`.`a` = `test`.`t2`.`a`) limit 1) /* select#2 */ select `dt1`.`a` from `dt` `dt1` where (`dt1`.`a` = (/* select#4 */ select `dt2`.`a` from `dt` `dt2`))) AS `subq` from `test`.`t1` select (with dt as (select t2.a as a from t2 having t1.a=t2.a limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; subq 1 2 # Scope of outer ref in CTE select (select * from (select t1.a) cte) from t1; (select * from (select t1.a) cte) 1 2 select (with cte as (select t1.a) select * from cte) from t1; (with cte as (select t1.a) select * from cte) 1 2 with cte as (select t1.a) select (select * from cte) from t1; ERROR 42S02: Unknown table 't1' in field list # NOT IN(subquery using derived), handled with subquery materialization explain select * from t1 where a not in (select dt.f+1 from (select t2.a as f from t2) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a`,(/* select#2 */ select 1 from `test`.`t2` where (outer_field_is_not_null, (((`test`.`t1`.`a`) = (`test`.`t2`.`a` + 1)) or ((`test`.`t2`.`a` + 1) is null)), true) having (outer_field_is_not_null, ((`test`.`t2`.`a` + 1)), true)) is false) select * from t1 where a not in (select dt.f+1 from (select t2.a as f from t2) dt); a b 1 NULL # Now put an outer reference inside derived table: # subquery is properly seen as correlated and subquery # materialization is thus not used. explain select * from t1 where a not in (select dt.f+1 from (select 0*t1.a+t2.a as f from t2) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using where Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a`,(/* select#2 */ select 1 from `test`.`t2` where (outer_field_is_not_null, (((`test`.`t1`.`a`) = (((0 * `test`.`t1`.`a`) + `test`.`t2`.`a`) + 1)) or ((((0 * `test`.`t1`.`a`) + `test`.`t2`.`a`) + 1) is null)), true) having (outer_field_is_not_null, ((((0 * `test`.`t1`.`a`) + `test`.`t2`.`a`) + 1)), true)) is false) select * from t1 where a not in (select dt.f+1 from (select 0*t1.a+t2.a as f from t2) dt); a b 1 NULL # Verify that a non-lateral derived table with an outer # reference makes the semijoin be correlated and thus blocks # semijoin-materialization-scan. create table t11 (a int); insert into t11 with recursive cte as (select 1 as a union all select a+1 from cte where a<124) select * from cte; alter table t11 add index(a); create table t12 like t11; analyze table t11,t12; Table Op Msg_type Msg_text test.t11 analyze status OK test.t12 analyze status OK # No outer ref: mat-scan chosen explain select /*+ NO_SEMIJOIN(@subq1 FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) */ * from t11 where a in (select /*+ QB_NAME(subq1) NO_MERGE(dt) */ * from (select t12.a from t12) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY NULL ALL NULL NULL NULL NULL NULL 100.00 Using where 1 PRIMARY t11 NULL ref a a 5 .a 1 100.00 Using index 2 MATERIALIZED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DERIVED t12 NULL index NULL a 5 NULL 1 100.00 Using index Warnings: Note 1003 /* select#1 */ select /*+ NO_SEMIJOIN(@`subq1` FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) NO_MERGE(`dt`@`subq1`) */ `test`.`t11`.`a` AS `a` from `test`.`t11` semi join ((/* select#3 */ select `test`.`t12`.`a` AS `a` from `test`.`t12`) `dt`) where (`test`.`t11`.`a` = ``.`a`) # outer ref: mat-scan not chosen explain select /*+ NO_SEMIJOIN(@subq1 FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) */ * from t11 where a in (select /*+ QB_NAME(subq1) NO_MERGE(dt) */ * from (select t12.a+0*t11.a from t12) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t11 NULL index a a 5 NULL 124 100.00 Using where; Using index; Rematerialize () 1 PRIMARY NULL ref 9 test.t11.a 2 100.00 Using where; Using index; Start temporary; End temporary 3 DEPENDENT DERIVED t12 NULL index NULL a 5 NULL 1 100.00 Using index Warnings: Note 1276 Field or reference 'test.t11.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select /*+ NO_SEMIJOIN(@`subq1` FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) NO_MERGE(`dt`@`subq1`) */ `test`.`t11`.`a` AS `a` from `test`.`t11` semi join (lateral (/* select#3 */ select (`test`.`t12`.`a` + (0 * `test`.`t11`.`a`)) AS `t12.a+0*t11.a` from `test`.`t12`) `dt`) where (`test`.`t11`.`a` = `dt`.`t12.a+0*t11.a`) DROP TABLE t11,t12; LATERAL # prevents join buffer if materialized (but not if merged) explain select dt.a from t1, lateral (select t1.a from t2) dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 SIMPLE t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` join `test`.`t2` # no right join explain select dt.a from t1 right join lateral (select t1.a from t2) dt on 1; ERROR HY000: INNER or LEFT JOIN must be used for LATERAL references made by 'dt' # no bad left join either explain select dt.a from lateral (select t1.a from t2) dt left join t1 on 1; ERROR 42S22: Unknown column 't1.a' in 'field list' # more complex case explain SELECT * FROM t1 LEFT JOIN lateral (select t1.a) as dt ON t1.a=dt.a RIGHT JOIN lateral (select dt.a) as dt1 ON dt.a=dt1.a; ERROR HY000: INNER or LEFT JOIN must be used for LATERAL references made by 'dt1' # LATERAL DT depending on LATERAL DT explain SELECT * FROM t1 JOIN lateral (select t1.a) as dt ON t1.a=dt.a JOIN lateral (select dt.a) as dt1 ON dt.a=dt1.a; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where; Rematerialize () 1 PRIMARY NULL ref 5 test.t1.a 2 100.00 Using index; Rematerialize () 1 PRIMARY NULL ref 5 test.t1.a 2 100.00 Using index 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'dt.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`dt1`.`a` AS `a` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join lateral (/* select#3 */ select `dt`.`a` AS `a`) `dt1` where ((`dt`.`a` = `test`.`t1`.`a`) and (`dt1`.`a` = `test`.`t1`.`a`)) # Placing lateral outer ref in SELECT list then HAVING select t1.a, dt.a from t1, lateral (select t1.a+t2.a as a from t2) dt; a a 1 2 1 3 2 3 2 4 select t1.a, dt.a from t1, lateral (select t2.a as a from t2 having t1.a) dt; a a 1 1 1 2 2 1 2 2 # Inside view create view v1 as select t1.a as f1, dt.a as f2 from t1, lateral (select t1.a+t2.a as a from t2) dt; show create view v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `f1`,`dt`.`a` AS `f2` from (`t1` join lateral (select (`t1`.`a` + `t2`.`a`) AS `a` from `t2`) `dt`) utf8mb4 utf8mb4_0900_ai_ci select * from v1; f1 f2 1 2 1 3 2 3 2 4 drop view v1; # Coverage for various branches in Item_ref::fix_fields SELECT COUNT(*) FROM t1 GROUP BY t1.a HAVING t1.a IN (SELECT t3.a FROM t1 AS t3 WHERE t3.b IN (SELECT b FROM t2, lateral (select t1.a) dt)); COUNT(*) create view v1 as select a, b from t1; select vq1.b,dt.b from v1 vq1, lateral (select vq1.b) dt; b b NULL NULL NULL NULL select b from v1 vq1, lateral (select count(*) from v1 vq2 having vq1.b = 3) dt; b drop view v1; SELECT /*+ SET_VAR(optimizer_switch = 'materialization=off,semijoin=off') */ * FROM t1 AS ta, lateral (select 1 WHERE ta.a IN (SELECT b FROM t2 AS tb WHERE tb.b >= SOME(SELECT SUM(tc.a) as sg FROM t1 as tc GROUP BY tc.b HAVING ta.a=tc.b))) dt; a b 1 select (select dt.a from (select 1 as a, t2.a as b from t2 having t1.a) dt where dt.b=t1.a) as subq from t1; subq 1 1 select (select dt.a from (select 1 as a, 3 as b from t2 having t1.a) dt where dt.b=t1.a) as subq from t1; subq NULL NULL # Aggregation in outer context select (select f from (select max(t1.a) as f) as dt) as g from t1; g 2 select (select f from lateral (select max(t1.a) as f) as dt) as g from t1; g 2 # LATERAL doesn't allow an aggregate to resolve to the # immediate parent (because reading of FROM tables happens # before aggregation). So it resolves in the derived table, so # the outer query doesn't produce a single-row result. select t1.a, f from t1, lateral (select max(t1.a) as f) as dt; a f 1 1 2 2 # We support CTE inside derived table select * from t1, lateral (with qn as (select t1.a) select (select max(a) from qn)) as dt; a b (select max(a) from qn) 1 NULL 1 2 NULL 2 # Coverage for crash in Item_ident::fix_after_pullout: # when we merge a derived table contained in a derived table, # and the merged one contains an outer ref to the top query. select (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) from t1; (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) 1 2 # Semijoin containing a correlated derived table, DT must # become LATERAL explain select a from t1 where a in (select a from (select t1.a) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where; Rematerialize () 1 PRIMARY NULL ref 5 test.t1.a 2 100.00 Using index; FirstMatch(t1) 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (lateral (/* select#3 */ select `test`.`t1`.`a` AS `a`) `dt`) where (`dt`.`a` = `test`.`t1`.`a`) select a from t1 where a in (select a from (select t1.a) dt); a 1 2 create table t3 as with recursive cte as (select 1 as a union select a+1 from cte where a<20) select * from cte; analyze table t3; Table Op Msg_type Msg_text test.t3 analyze status OK explain select min(a),max(a) from t3 where a in (select /*+ no_merge() */ a from (select t3.a from t1) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 NULL ALL NULL NULL NULL NULL 20 100.00 Using where; Rematerialize () 1 PRIMARY NULL ref 9 test.t3.a 2 100.00 Using index; FirstMatch(t3) 3 DEPENDENT DERIVED t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t3.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select /*+ NO_MERGE(@`select#2`) */ min(`test`.`t3`.`a`) AS `min(a)`,max(`test`.`t3`.`a`) AS `max(a)` from `test`.`t3` semi join (lateral (/* select#3 */ select `test`.`t3`.`a` AS `a` from `test`.`t1`) `dt`) where (`dt`.`a` = `test`.`t3`.`a`) select min(a),max(a) from t3 where a in (select /*+ no_merge() */ a from (select t3.a from t1) dt); min(a) max(a) 1 20 drop table t3; # DT containing a correlated DT which must become LATERAL explain format=tree select * from t1, lateral (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) dt3; EXPLAIN -> Nested loop inner join -> Invalidate materialized tables (row from t1) (cost=0.45 rows=2) -> Table scan on t1 (cost=0.45 rows=2) -> Table scan on dt2 -> Materialize (invalidate on row from t1) -> Limit: 1 row(s) -> Table scan on t2 (cost=0.45 rows=2) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #4 was resolved in SELECT #1 explain select * from t1, lateral (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) dt3; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #4 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt2`.`a` AS `a` from `test`.`t1` join lateral (/* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t2` limit 1) `dt2` select * from t1, lateral (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) dt3; a b a 1 NULL 1 2 NULL 2 explain select * from t1 as t0, lateral (select dt3.* from t1, lateral (select * from (select * from (select t0.a from t2) as dt limit 1) dt2) dt3) dt4; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t0 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 4 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t0.a' of SELECT #5 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`dt2`.`a` AS `a` from `test`.`t1` `t0` join `test`.`t1` join lateral (/* select#4 */ select `test`.`t0`.`a` AS `a` from `test`.`t2` limit 1) `dt2` select * from t1 as t0, lateral (select dt3.* from t1, lateral (select * from (select * from (select t0.a from t2) as dt limit 1) dt2) dt3) dt4; a b a 1 NULL 1 1 NULL 1 2 NULL 2 2 NULL 2 explain select /*+ no_merge() */ * from t1 as t0, lateral (select dt3.* from t1, lateral (select * from (select * from (select t0.a from t2) as dt limit 1) dt2) dt3) dt4; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t0 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 4 100.00 NULL 2 DEPENDENT DERIVED t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 4 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t0.a' of SELECT #5 was resolved in SELECT #1 Note 1003 /* select#1 */ select /*+ NO_MERGE(@`select#1`) */ `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`dt4`.`a` AS `a` from `test`.`t1` `t0` join lateral (/* select#2 */ select `dt2`.`a` AS `a` from `test`.`t1` join (/* select#4 */ select `test`.`t0`.`a` AS `a` from `test`.`t2` limit 1) `dt2`) `dt4` select /*+ no_merge() */ * from t1 as t0, lateral (select dt3.* from t1, lateral (select * from (select * from (select t0.a from t2) as dt limit 1) dt2) dt3) dt4; a b a 1 NULL 1 1 NULL 1 2 NULL 2 2 NULL 2 explain select * from t1, lateral (select * from (select 42) t1, (select t1.a) dt2) dt3; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY NULL system NULL NULL NULL NULL 1 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 4 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #4 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,'42' AS `42`,`dt2`.`a` AS `a` from `test`.`t1` join lateral (/* select#4 */ select `test`.`t1`.`a` AS `a`) `dt2` select * from t1, lateral (select * from (select 42) t1, (select t1.a) dt2) dt3; a b 42 a 1 NULL 42 1 2 NULL 42 2 without semijoin: index_subquery needs to re-materialize explain select a from t1 where a in (select /*+ no_semijoin() */ a from (select t1.a) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 2 DEPENDENT SUBQUERY NULL index_subquery 5 func 2 100.00 Using index 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select /*+ NO_SEMIJOIN(@`select#2`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a`,(((`test`.`t1`.`a`) in dt on ))) select a from t1 where a in (select /*+ no_semijoin() */ a from (select t1.a) dt); a 1 2 select a from t1 where a in (with cte as (select t1.a) select /*+ no_semijoin() */ a from cte); a 1 2 # Count rematerializations # In all three plans, handler_write is 2, showing that we # rematerialize only when necessary (when row of t1 changes) explain select straight_join * from t1, t2, lateral (select t1.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`dt`.`a` AS `a` from `test`.`t1` join `test`.`t2` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` flush status; select straight_join * from t1, t2, lateral (select t1.a) as dt; a b a b a 1 NULL 1 NULL 1 1 NULL 2 NULL 1 2 NULL 1 NULL 2 2 NULL 2 NULL 2 # when a row of t1 produces two rows of t2 passed to "dt", # it still makes one materialization. show status like "handler_write"; Variable_name Value Handler_write 2 explain select straight_join * from t1, lateral (select t1.a) as dt, t2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join `test`.`t2` flush status; select straight_join * from t1, lateral (select t1.a) as dt, t2; a b a a b 1 NULL 1 1 NULL 1 NULL 1 2 NULL 2 NULL 2 1 NULL 2 NULL 2 2 NULL show status like "handler_write"; Variable_name Value Handler_write 2 explain select straight_join * from t2, t1, lateral (select t1.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize (); Using join buffer (Block Nested Loop) 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select straight_join `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` flush status; select straight_join * from t2, t1, lateral (select t1.a) as dt; a b a b a 1 NULL 1 NULL 1 1 NULL 2 NULL 2 2 NULL 1 NULL 1 2 NULL 2 NULL 2 # Due to join buffer, order t2-t1 produces rows as a # non-buffered t1-t2 plan: t1 buffers all rows of t2, then for # each row of t1 it's joined to all rows of t2 and passed to t2; # when a row of t1 produces two rows of t2 passed to "dt", # it still makes one materialization. show status like "handler_write"; Variable_name Value Handler_write 2 # Let the planner find the best plan. # It doesn't work so well, because of # optimizer_prune_level=1 (see bug#28629788): order specified by # the user is sorted by number of rows, which leaves it # unchanged (Card(t1)=Card(t2)=Card(dt)); then it is the first # explored plan so it's explored in full, and later t1-dt is rejected as # more expensive than t1-t2. Whereas if t1-dt had been explored # deeper, we'd see t1-dt-t2 is actually the cheapest, because # it reads dt the least number of times (and dt has a high read # cost because Temptable::scan_time() is incredibly high but # that's another issue; see bug#28631100). # t2 cannot use join buffering as between "dt" and its # dependency t1: join buffering would interlace rows of t1 # thus cause more rematerializations. explain select * from t1, t2, lateral (select t1.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`dt`.`a` AS `a` from `test`.`t1` join `test`.`t2` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` flush status; select * from t1, t2, lateral (select t1.a) as dt; a b a b a 1 NULL 1 NULL 1 1 NULL 2 NULL 1 2 NULL 1 NULL 2 2 NULL 2 NULL 2 show status like "handler_write"; Variable_name Value Handler_write 2 # This one finds the best plan. Yes we simply swapped tables in the query, # and it yields a different plan. This is because the order specified by # the user is sorted by number of rows, which leaves it # unchanged (Card(t1)=Card(t2)=Card(dt), then it is the first # explored plan so it's explored in full and so is never pruned by # prune_level=1, and it is the best plan. Best as: it reads # "dt" less, and t2 uses join buffering (which is ok as it's # after "dt"). # If prune_level=0, all 3 variants here produce this plan. explain select * from t1, lateral (select t1.a) as dt, t2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join `test`.`t2` flush status; select * from t1, lateral (select t1.a) as dt, t2; a b a a b 1 NULL 1 1 NULL 1 NULL 1 2 NULL 2 NULL 2 1 NULL 2 NULL 2 2 NULL show status like "handler_write"; Variable_name Value Handler_write 2 # This one is intermediate: t1 uses join buffer (good), but # "dt" is last (bad, as it has high scan cost). explain select * from t2, t1, lateral (select t1.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize (); Using join buffer (Block Nested Loop) 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` flush status; select * from t2, t1, lateral (select t1.a) as dt; a b a b a 1 NULL 1 NULL 1 1 NULL 2 NULL 2 2 NULL 1 NULL 1 2 NULL 2 NULL 2 show status like "handler_write"; Variable_name Value Handler_write 2 # Show the trace of planning of lateral derived tables explain select * from t1, lateral (select t1.a from t2 as t3, t2 as t4) as dt, t2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 SIMPLE t3 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 1 SIMPLE t4 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 1 SIMPLE t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join `test`.`t2` `t3` join `test`.`t2` `t4` join `test`.`t2` select trace from information_schema.optimizer_trace; trace { "steps": [ { "join_preparation": { "select#": 1, "steps": [ { "join_preparation": { "select#": 2, "steps": [ { "expanded_query": "/* select#2 */ select `t1`.`a` AS `a` from `t2` `t3` join `t2` `t4`" } ] } }, { "derived": { "table": "``.`` `dt`", "select#": 2, "merged": true } }, { "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`a` AS `a`,`t2`.`a` AS `a`,`t2`.`b` AS `b` from `t1` join (`t2` `t3` join `t2` `t4`) join `t2`" }, { "transformations_to_nested_joins": { "transformations": [ "parenthesis_removal" ], "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`a` AS `a`,`t2`.`a` AS `a`,`t2`.`b` AS `b` from `t1` join `t2` `t3` join `t2` `t4` join `t2`" } } ] } }, { "join_optimization": { "select#": 1, "steps": [ { "table_dependencies": [ { "table": "`t1`", "row_may_be_null": false, "map_bit": 0, "depends_on_map_bits": [ ] }, { "table": "`t2` `t3`", "row_may_be_null": false, "map_bit": 1, "depends_on_map_bits": [ ] }, { "table": "`t2` `t4`", "row_may_be_null": false, "map_bit": 2, "depends_on_map_bits": [ ] }, { "table": "`t2`", "row_may_be_null": false, "map_bit": 3, "depends_on_map_bits": [ ] } ] }, { "rows_estimation": [ { "table": "`t1`", "table_scan": { "rows": 2, "cost": 0.25 } }, { "table": "`t2` `t3`", "table_scan": { "rows": 2, "cost": 0.25 } }, { "table": "`t2` `t4`", "table_scan": { "rows": 2, "cost": 0.25 } }, { "table": "`t2`", "table_scan": { "rows": 2, "cost": 0.25 } } ] }, { "considered_execution_plans": [ { "plan_prefix": [ ], "table": "`t1`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "resulting_rows": 2, "cost": 0.45, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 2, "cost_for_plan": 0.45, "rest_of_plan": [ { "plan_prefix": [ "`t1`" ], "table": "`t2` `t3`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "using_join_cache": true, "buffers_needed": 1, "resulting_rows": 2, "cost": 0.65, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 4, "cost_for_plan": 1.1, "rest_of_plan": [ { "plan_prefix": [ "`t1`", "`t2` `t3`" ], "table": "`t2` `t4`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "using_join_cache": true, "buffers_needed": 1, "resulting_rows": 2, "cost": 1.05, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 8, "cost_for_plan": 2.1501, "rest_of_plan": [ { "plan_prefix": [ "`t1`", "`t2` `t3`", "`t2` `t4`" ], "table": "`t2`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "access_type": "scan", "using_join_cache": true, "buffers_needed": 1, "resulting_rows": 2, "cost": 1.8501, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 16, "cost_for_plan": 4.0001, "chosen": true } ] }, { "plan_prefix": [ "`t1`", "`t2` `t3`" ], "table": "`t2`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "access_type": "scan", "using_join_cache": true, "buffers_needed": 1, "resulting_rows": 2, "cost": 1.05, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 8, "cost_for_plan": 2.1501, "pruned_by_heuristic": true } ] }, { "plan_prefix": [ "`t1`" ], "table": "`t2` `t4`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "using_join_cache": true, "buffers_needed": 1, "resulting_rows": 2, "cost": 0.65, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 4, "cost_for_plan": 1.1, "pruned_by_heuristic": true }, { "plan_prefix": [ "`t1`" ], "table": "`t2`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "access_type": "scan", "using_join_cache": true, "buffers_needed": 1, "resulting_rows": 2, "cost": 0.65, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 4, "cost_for_plan": 1.1, "pruned_by_heuristic": true } ] }, { "plan_prefix": [ ], "table": "`t2` `t3`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "resulting_rows": 2, "cost": 0.45, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 2, "cost_for_plan": 0.45, "pruned_by_heuristic": true }, { "plan_prefix": [ ], "table": "`t2` `t4`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "resulting_rows": 2, "cost": 0.45, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 2, "cost_for_plan": 0.45, "pruned_by_heuristic": true }, { "plan_prefix": [ ], "table": "`t2`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "access_type": "scan", "resulting_rows": 2, "cost": 0.45, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 2, "cost_for_plan": 0.45, "pruned_by_heuristic": true } ] }, { "attaching_conditions_to_tables": { "original_condition": null, "attached_conditions_computation": [ ], "attached_conditions_summary": [ { "table": "`t1`", "attached": null }, { "table": "`t2` `t3`", "attached": null }, { "table": "`t2` `t4`", "attached": null }, { "table": "`t2`", "attached": null } ] } }, { "finalizing_table_conditions": [ ] }, { "refine_plan": [ { "table": "`t1`" }, { "table": "`t2` `t3`" }, { "table": "`t2` `t4`" }, { "table": "`t2`" } ] } ] } }, { "join_explain": { "select#": 1, "steps": [ ] } } ] } # LDT depending on const table only create table t3(a int) engine=innodb; insert into t3 values(3); analyze table t3; Table Op Msg_type Msg_text test.t3 analyze status OK explain select * from t3, lateral (select t3.a+1) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 NULL ALL NULL NULL NULL NULL 1 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t3.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`dt`.`t3.a+1` AS `t3.a+1` from `test`.`t3` join lateral (/* select#2 */ select (`test`.`t3`.`a` + 1) AS `t3.a+1`) `dt` select * from t3, lateral (select t3.a+1) as dt; a t3.a+1 3 4 drop table t3; # Two LDTs depending on different tables explain select * from t2, t1, lateral (select t1.a) as dt, lateral (select t2.a) as dt2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`dt2`.`a` AS `a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join lateral (/* select#3 */ select `test`.`t2`.`a` AS `a`) `dt2` select * from t2, t1, lateral (select t1.a) as dt, lateral (select t2.a) as dt2; a b a b a a 1 NULL 1 NULL 1 1 1 NULL 2 NULL 2 1 2 NULL 1 NULL 1 2 2 NULL 2 NULL 2 2 # Two LDTs depending on one same table explain select * from t2, t1, lateral (select t1.a) as dt, lateral (select t1.a+1) as dt2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize (,); Using join buffer (Block Nested Loop) 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`dt2`.`t1.a+1` AS `t1.a+1` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join lateral (/* select#3 */ select (`test`.`t1`.`a` + 1) AS `t1.a+1`) `dt2` explain format=json select * from t2, t1, lateral (select t1.a) as dt, lateral (select t1.a+1) as dt2; EXPLAIN { "query_block": { "select_id": 1, "cost_info": { "query_cost": "34.10" }, "nested_loop": [ { "table": { "table_name": "t2", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 2, "filtered": "100.00", "cost_info": { "read_cost": "0.25", "eval_cost": "0.20", "prefix_cost": "0.45", "data_read_per_join": "32" }, "used_columns": [ "a", "b" ] } }, { "table": { "table_name": "t1", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 4, "filtered": "100.00", "rematerialize": "dt,dt2", "using_join_buffer": "Block Nested Loop", "cost_info": { "read_cost": "0.25", "eval_cost": "0.40", "prefix_cost": "1.10", "data_read_per_join": "64" }, "used_columns": [ "a", "b" ] } }, { "table": { "table_name": "dt", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 8, "filtered": "100.00", "cost_info": { "read_cost": "10.30", "eval_cost": "0.80", "prefix_cost": "12.20", "data_read_per_join": "128" }, "used_columns": [ "a" ], "materialized_from_subquery": { "using_temporary_table": true, "dependent": true, "cacheable": true, "query_block": { "select_id": 2, "message": "No tables used" } } } }, { "table": { "table_name": "dt2", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 16, "filtered": "100.00", "cost_info": { "read_cost": "20.30", "eval_cost": "1.60", "prefix_cost": "34.10", "data_read_per_join": "256" }, "used_columns": [ "t1.a+1" ], "materialized_from_subquery": { "using_temporary_table": true, "dependent": true, "cacheable": true, "query_block": { "select_id": 3, "message": "No tables used" } } } } ] } } Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`dt2`.`t1.a+1` AS `t1.a+1` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join lateral (/* select#3 */ select (`test`.`t1`.`a` + 1) AS `t1.a+1`) `dt2` select * from t2, t1, lateral (select t1.a) as dt, lateral (select t1.a+1) as dt2; a b a b a t1.a+1 1 NULL 1 NULL 1 2 1 NULL 2 NULL 2 3 2 NULL 1 NULL 1 2 2 NULL 2 NULL 2 3 # One LDT depending on two tables. The "rematerialize" tag is # properly added to the 2nd dependency only. explain select * from t2, t1, lateral (select t1.a+t2.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`t1.a+t2.a` AS `t1.a+t2.a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select (`test`.`t1`.`a` + `test`.`t2`.`a`) AS `t1.a+t2.a`) `dt` explain format=json select * from t2, t1, lateral (select t1.a+t2.a) as dt; EXPLAIN { "query_block": { "select_id": 1, "cost_info": { "query_cost": "12.45" }, "nested_loop": [ { "table": { "table_name": "t2", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 2, "filtered": "100.00", "cost_info": { "read_cost": "0.25", "eval_cost": "0.20", "prefix_cost": "0.45", "data_read_per_join": "32" }, "used_columns": [ "a", "b" ] } }, { "table": { "table_name": "t1", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 4, "filtered": "100.00", "rematerialize": "dt", "cost_info": { "read_cost": "0.50", "eval_cost": "0.40", "prefix_cost": "1.35", "data_read_per_join": "64" }, "used_columns": [ "a", "b" ] } }, { "table": { "table_name": "dt", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 8, "filtered": "100.00", "cost_info": { "read_cost": "10.30", "eval_cost": "0.80", "prefix_cost": "12.45", "data_read_per_join": "128" }, "used_columns": [ "t1.a+t2.a" ], "materialized_from_subquery": { "using_temporary_table": true, "dependent": true, "cacheable": true, "query_block": { "select_id": 2, "message": "No tables used" } } } } ] } } Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`t1.a+t2.a` AS `t1.a+t2.a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select (`test`.`t1`.`a` + `test`.`t2`.`a`) AS `t1.a+t2.a`) `dt` select * from t2, t1, lateral (select t1.a+t2.a) as dt; a b a b t1.a+t2.a 1 NULL 1 NULL 2 1 NULL 2 NULL 3 2 NULL 1 NULL 3 2 NULL 2 NULL 4 select json_extract(trace,"$.steps[*].join_optimization.steps[*].refine_plan") from information_schema.optimizer_trace; json_extract(trace,"$.steps[*].join_optimization.steps[*].refine_plan") [[{"table": "`t2`"}, {"table": "`t1`"}, {"table": " `dt`", "rematerialized_for_each_row_of": "t1"}]] # Test when a dependency of LDT uses BKA: BKA code must # refresh LDT's content when it provides a row. set @old_opt_switch=@@optimizer_switch; set @@optimizer_switch="batched_key_access=on,mrr_cost_based=off"; CREATE TABLE t11 (t11a int, t11b int); INSERT INTO t11 VALUES (99, NULL),(99, 3),(99,0); CREATE TABLE t12 (t12a int, t12b int, KEY idx (t12b)); INSERT INTO t12 VALUES (100,0),(150,200),(999, 0),(999, NULL); ANALYZE TABLE t11,t12; Table Op Msg_type Msg_text test.t11 analyze status OK test.t12 analyze status OK explain SELECT * FROM t11 LEFT JOIN t12 force index (idx) ON t12.t12b = t11.t11b JOIN LATERAL (SELECT t12a) dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t11 NULL ALL NULL NULL NULL NULL 3 100.00 NULL 1 PRIMARY t12 NULL ref idx idx 5 test.t11.t11b 1 100.00 Rematerialize (); Using join buffer (Batched Key Access) 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t12.t12a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t11`.`t11a` AS `t11a`,`test`.`t11`.`t11b` AS `t11b`,`test`.`t12`.`t12a` AS `t12a`,`test`.`t12`.`t12b` AS `t12b`,`dt`.`t12a` AS `t12a` from `test`.`t11` left join `test`.`t12` FORCE INDEX (`idx`) on((`test`.`t12`.`t12b` = `test`.`t11`.`t11b`)) join lateral (/* select#2 */ select `test`.`t12`.`t12a` AS `t12a`) `dt` where true flush status; SELECT * FROM t11 LEFT JOIN t12 force index (idx) ON t12.t12b = t11.t11b JOIN LATERAL (SELECT t12a) dt; t11a t11b t12a t12b t12a 99 0 100 0 100 99 0 999 0 999 99 NULL NULL NULL NULL 99 3 NULL NULL NULL show status like "handler_write"; Variable_name Value Handler_write 3 DROP TABLE t11,t12; set @@optimizer_switch=@old_opt_switch; # Test that with an auto_key on the lateral DT, the index is # properly emptied and re-filled when re-materializing. # If index weren't emptied, we'd see too many "11" matches for 2nd # row of t1; and if not re-filled, we'd see no matches for that. create table t3 (a int, b int); insert into t3 values(1, 10), (1, 11), (2, 10), (2, 11); analyze table t3; Table Op Msg_type Msg_text test.t3 analyze status OK # Note the auto_key with "Using index", to test the index as # much as possible. explain select * from t1, lateral (select t3.b from t3 where t3.a=t1.a) dt where dt.b=t1.a+9; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 SIMPLE t3 NULL ALL NULL NULL NULL NULL 4 25.00 Using where; Using join buffer (Block Nested Loop) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t3`.`b` AS `b` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`a`) and (`test`.`t3`.`b` = (`test`.`t1`.`a` + 9))) select * from t1, lateral (select t3.b from t3 where t3.a=t1.a) dt where dt.b=t1.a+9; a b b 1 NULL 10 2 NULL 11 drop table t3; set optimizer_switch='derived_merge=off'; # Deep nesting: all intermediate subqueries are marked DEPENDENT explain select * from t1 where (select count(*) from (select * from (select * from t1 t2 where 2=(select 2 from (select t1.a) dt1))dt3)dt4); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 4 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 5 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 6 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #6 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (0 <> (/* select#2 */ select count(0) from (/* select#3 */ select `dt3`.`a` AS `a`,`dt3`.`b` AS `b` from (/* select#4 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` `t2` where (2 = (/* select#5 */ select 2 from (/* select#6 */ select `test`.`t1`.`a` AS `a`) `dt1`))) `dt3`) `dt4`)) select * from t1 where (select count(*) from (select * from (select * from t1 t2 where 2=(select 2 from (select t1.a) dt1))dt3)dt4); a b 1 NULL 2 NULL # If reference is removed, not DEPENDENT explain select * from t1 where (select count(*) from (select * from (select * from t1 t2 where 2=(select 2 from (select 42) dt1))dt3)dt4); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 4 DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 5 SUBQUERY NULL system NULL NULL NULL NULL 1 100.00 NULL 6 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where true select * from t1 where (select count(*) from (select * from (select * from t1 t2 where 2=(select 2 from (select 42) dt1))dt3)dt4); a b 1 NULL 2 NULL # Outer ref is in SELECT list of derived table's definition explain select (select dt.a from (select t1.a as a, t2.a as b from t2) dt where dt.b=t1.a) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 test.t1.a 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`a` from (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t2`) `dt` where (`dt`.`b` = `test`.`t1`.`a`)) AS `subq` from `test`.`t1` select (select dt.a from (select t1.a as a, t2.a as b from t2) dt where dt.b=t1.a) as subq from t1; subq 1 2 # In WHERE explain select (select dt.b from (select t2.a as b from t2 where t1.a=t2.a) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 50.00 Using where Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select `test`.`t2`.`a` AS `b` from `test`.`t2` where (`test`.`t1`.`a` = `test`.`t2`.`a`)) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select t2.a as b from t2 where t1.a=t2.a) dt) as subq from t1; subq 1 2 # In GROUP BY explain select (select dt.b from (select sum(t2.a) as b from t2 group by t1.a) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using temporary Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select sum(`test`.`t2`.`a`) AS `b` from `test`.`t2` group by `test`.`t1`.`a`) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select sum(t2.a) as b from t2 group by t1.a) dt) as subq from t1; subq 3 3 # In HAVING explain select (select dt.b from (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-1) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 't1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select sum(`test`.`t2`.`a`) AS `b` from `test`.`t2` having (`test`.`t1`.`a` = (sum(`test`.`t2`.`a`) - 1))) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-1) dt) as subq from t1; subq NULL 3 explain select (select dt.b from (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-2) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 't1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select sum(`test`.`t2`.`a`) AS `b` from `test`.`t2` having (`test`.`t1`.`a` = (sum(`test`.`t2`.`a`) - 2))) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-2) dt) as subq from t1; subq 3 NULL # In ORDER BY explain select (select dt.b from (select t2.a as b from t2 order by if(t1.a=1,t2.a,-t2.a) limit 1) dt) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select `test`.`t2`.`a` AS `b` from `test`.`t2` order by if((`test`.`t1`.`a` = 1),`test`.`t2`.`a`,-(`test`.`t2`.`a`)) limit 1) `dt`) AS `subq` from `test`.`t1` select (select dt.b from (select t2.a as b from t2 order by if(t1.a=1,t2.a,-t2.a) limit 1) dt) as subq from t1; subq 1 2 # In window functions explain select (select dt.b from (select t2.a, sum(t1.a*10+t2.a) over (order by if(t1.a=1,t2.a,-t2.a)) as b from t2) dt where dt.a=1) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 const 1 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using filesort Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 3598 To get information about window functions use EXPLAIN FORMAT=JSON Note 1003 /* select#1 */ select (/* select#2 */ select `dt`.`b` from (/* select#3 */ select `test`.`t2`.`a` AS `a`,sum(((`test`.`t1`.`a` * 10) + `test`.`t2`.`a`)) OVER (ORDER BY if((`test`.`t1`.`a` = 1),`test`.`t2`.`a`,-(`test`.`t2`.`a`)) ) AS `b` from `test`.`t2`) `dt` where (`dt`.`a` = 1)) AS `subq` from `test`.`t1` select (select dt.b from (select t2.a, sum(t1.a*10+t2.a) over (order by if(t1.a=1,t2.a,-t2.a)) as b from t2) dt where dt.a=1) as subq from t1; subq 11 43 # CTE referenced twice explain select (with dt as (select t1.a as a, t2.a as b from t2) select dt2.a from dt dt1, dt dt2 where dt1.b=t1.a and dt2.b=dt1.b) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 test.t1.a 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 test.t1.a 2 100.00 Using where 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #4 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select (with `dt` as (/* select#3 */ select `test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t2`) /* select#2 */ select `dt2`.`a` from `dt` `dt1` join `dt` `dt2` where ((`dt2`.`b` = `dt1`.`b`) and (`dt1`.`b` = `test`.`t1`.`a`))) AS `subq` from `test`.`t1` select (with dt as (select t1.a as a, t2.a as b from t2) select dt2.a from dt dt1, dt dt2 where dt1.b=t1.a and dt2.b=dt1.b) as subq from t1; subq 1 2 Recursive CTE select (with recursive dt as (select t1.a as a union select a+1 from dt where a<10) select dt1.a from dt dt1 where dt1.a=t1.a ) as subq from t1; subq 1 2 select (with recursive dt as (select t1.a as a union select a+1 from dt where a<10) select concat(count(*), ' - ', avg(dt.a)) from dt ) as subq from t1; subq 10 - 5.5000 9 - 6.0000 select (with recursive dt as (select t1.a as a union all select a+1 from dt where a<10) select concat(count(*), ' - ', avg(dt.a)) from dt ) as subq from t1; subq 10 - 5.5000 9 - 6.0000 select (with dt as (select t1.a as a, t2.a as b from t2) select dt2.a from dt dt1, dt dt2 where dt1.b=t1.a and dt2.b=dt1.b) as subq from t1; subq 1 2 # Two references to same CTE at different levels of nesting. explain select (with dt as (select t1.a as a from t2 limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 func 2 100.00 Using where; Using index 4 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #5 was resolved in SELECT #1 Note 1003 /* select#1 */ select (with `dt` as (/* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t2` limit 1) /* select#2 */ select `dt1`.`a` from `dt` `dt1` where (`dt1`.`a` = (/* select#4 */ select `dt2`.`a` from `dt` `dt2`))) AS `subq` from `test`.`t1` explain format=tree select (with dt as (select t1.a as a from t2 limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; EXPLAIN -> Table scan on t1 (cost=0.45 rows=2) -> Select #2 (subquery in projection; dependent) -> Filter: (dt1.a = (select #4)) -> Index lookup on dt1 using (a=(select #4)) -> Materialize CTE dt if needed -> Limit: 1 row(s) -> Table scan on t2 (cost=0.45 rows=2) -> Select #4 (subquery in condition; dependent) -> Table scan on dt2 -> Materialize CTE dt if needed (query plan printed elsewhere) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #5 was resolved in SELECT #1 select (with dt as (select t1.a as a from t2 limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; subq 1 2 explain select (with dt as (select t2.a as a from t2 having t1.a=t2.a limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT SUBQUERY NULL ref 5 func 2 100.00 Using where; Using index 4 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 't1.a' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 't1.a' of SELECT #5 was resolved in SELECT #1 Note 1003 /* select#1 */ select (with `dt` as (/* select#3 */ select `test`.`t2`.`a` AS `a` from `test`.`t2` having (`test`.`t1`.`a` = `test`.`t2`.`a`) limit 1) /* select#2 */ select `dt1`.`a` from `dt` `dt1` where (`dt1`.`a` = (/* select#4 */ select `dt2`.`a` from `dt` `dt2`))) AS `subq` from `test`.`t1` select (with dt as (select t2.a as a from t2 having t1.a=t2.a limit 1) select * from dt dt1 where dt1.a=(select * from dt as dt2)) as subq from t1; subq 1 2 # Scope of outer ref in CTE select (select * from (select t1.a) cte) from t1; (select * from (select t1.a) cte) 1 2 select (with cte as (select t1.a) select * from cte) from t1; (with cte as (select t1.a) select * from cte) 1 2 with cte as (select t1.a) select (select * from cte) from t1; ERROR 42S02: Unknown table 't1' in field list # NOT IN(subquery using derived), handled with subquery materialization explain select * from t1 where a not in (select dt.f+1 from (select t2.a as f from t2) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 2 SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a`,`test`.`t1`.`a` in ( (/* select#2 */ select (`dt`.`f` + 1) from (/* select#3 */ select `test`.`t2`.`a` AS `f` from `test`.`t2`) `dt` where true having true ), (`test`.`t1`.`a` in on where ((`test`.`t1`.`a` = `materialized-subquery`.`dt.f+1`)))) is false) select * from t1 where a not in (select dt.f+1 from (select t2.a as f from t2) dt); a b 1 NULL # Now put an outer reference inside derived table: # subquery is properly seen as correlated and subquery # materialization is thus not used. explain select * from t1 where a not in (select dt.f+1 from (select 0*t1.a+t2.a as f from t2) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 2 DEPENDENT SUBQUERY NULL ALL NULL NULL NULL NULL 2 100.00 Using where 3 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a`,(/* select#2 */ select 1 from (/* select#3 */ select ((0 * `test`.`t1`.`a`) + `test`.`t2`.`a`) AS `f` from `test`.`t2`) `dt` where (outer_field_is_not_null, (((`test`.`t1`.`a`) = (`dt`.`f` + 1)) or ((`dt`.`f` + 1) is null)), true) having (outer_field_is_not_null, ((`dt`.`f` + 1)), true)) is false) select * from t1 where a not in (select dt.f+1 from (select 0*t1.a+t2.a as f from t2) dt); a b 1 NULL # Verify that a non-lateral derived table with an outer # reference makes the semijoin be correlated and thus blocks # semijoin-materialization-scan. create table t11 (a int); insert into t11 with recursive cte as (select 1 as a union all select a+1 from cte where a<124) select * from cte; alter table t11 add index(a); create table t12 like t11; analyze table t11,t12; Table Op Msg_type Msg_text test.t11 analyze status OK test.t12 analyze status OK # No outer ref: mat-scan chosen explain select /*+ NO_SEMIJOIN(@subq1 FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) */ * from t11 where a in (select /*+ QB_NAME(subq1) NO_MERGE(dt) */ * from (select t12.a from t12) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY NULL ALL NULL NULL NULL NULL NULL 100.00 Using where 1 PRIMARY t11 NULL ref a a 5 .a 1 100.00 Using index 2 MATERIALIZED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DERIVED t12 NULL index NULL a 5 NULL 1 100.00 Using index Warnings: Note 1003 /* select#1 */ select /*+ NO_SEMIJOIN(@`subq1` FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) NO_MERGE(`dt`@`subq1`) */ `test`.`t11`.`a` AS `a` from `test`.`t11` semi join ((/* select#3 */ select `test`.`t12`.`a` AS `a` from `test`.`t12`) `dt`) where (`test`.`t11`.`a` = ``.`a`) # outer ref: mat-scan not chosen explain select /*+ NO_SEMIJOIN(@subq1 FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) */ * from t11 where a in (select /*+ QB_NAME(subq1) NO_MERGE(dt) */ * from (select t12.a+0*t11.a from t12) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t11 NULL index a a 5 NULL 124 100.00 Using where; Using index; Rematerialize () 1 PRIMARY NULL ref 9 test.t11.a 2 100.00 Using where; Using index; Start temporary; End temporary 3 DEPENDENT DERIVED t12 NULL index NULL a 5 NULL 1 100.00 Using index Warnings: Note 1276 Field or reference 'test.t11.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select /*+ NO_SEMIJOIN(@`subq1` FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) NO_MERGE(`dt`@`subq1`) */ `test`.`t11`.`a` AS `a` from `test`.`t11` semi join (lateral (/* select#3 */ select (`test`.`t12`.`a` + (0 * `test`.`t11`.`a`)) AS `t12.a+0*t11.a` from `test`.`t12`) `dt`) where (`test`.`t11`.`a` = `dt`.`t12.a+0*t11.a`) DROP TABLE t11,t12; LATERAL # prevents join buffer if materialized (but not if merged) explain select dt.a from t1, lateral (select t1.a from t2) dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `dt`.`a` AS `a` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t2`) `dt` # no right join explain select dt.a from t1 right join lateral (select t1.a from t2) dt on 1; ERROR HY000: INNER or LEFT JOIN must be used for LATERAL references made by 'dt' # no bad left join either explain select dt.a from lateral (select t1.a from t2) dt left join t1 on 1; ERROR 42S22: Unknown column 't1.a' in 'field list' # more complex case explain SELECT * FROM t1 LEFT JOIN lateral (select t1.a) as dt ON t1.a=dt.a RIGHT JOIN lateral (select dt.a) as dt1 ON dt.a=dt1.a; ERROR HY000: INNER or LEFT JOIN must be used for LATERAL references made by 'dt1' # LATERAL DT depending on LATERAL DT explain SELECT * FROM t1 JOIN lateral (select t1.a) as dt ON t1.a=dt.a JOIN lateral (select dt.a) as dt1 ON dt.a=dt1.a; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where; Rematerialize () 1 PRIMARY NULL ref 5 test.t1.a 2 100.00 Using index; Rematerialize () 1 PRIMARY NULL ref 5 test.t1.a 2 100.00 Using index 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'dt.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`dt1`.`a` AS `a` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join lateral (/* select#3 */ select `dt`.`a` AS `a`) `dt1` where ((`dt`.`a` = `test`.`t1`.`a`) and (`dt1`.`a` = `test`.`t1`.`a`)) # Placing lateral outer ref in SELECT list then HAVING select t1.a, dt.a from t1, lateral (select t1.a+t2.a as a from t2) dt; a a 1 2 1 3 2 3 2 4 select t1.a, dt.a from t1, lateral (select t2.a as a from t2 having t1.a) dt; a a 1 1 1 2 2 1 2 2 # Inside view create view v1 as select t1.a as f1, dt.a as f2 from t1, lateral (select t1.a+t2.a as a from t2) dt; show create view v1; View Create View character_set_client collation_connection v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `f1`,`dt`.`a` AS `f2` from (`t1` join lateral (select (`t1`.`a` + `t2`.`a`) AS `a` from `t2`) `dt`) utf8mb4 utf8mb4_0900_ai_ci select * from v1; f1 f2 1 2 1 3 2 3 2 4 drop view v1; # Coverage for various branches in Item_ref::fix_fields SELECT COUNT(*) FROM t1 GROUP BY t1.a HAVING t1.a IN (SELECT t3.a FROM t1 AS t3 WHERE t3.b IN (SELECT b FROM t2, lateral (select t1.a) dt)); COUNT(*) create view v1 as select a, b from t1; select vq1.b,dt.b from v1 vq1, lateral (select vq1.b) dt; b b NULL NULL NULL NULL select b from v1 vq1, lateral (select count(*) from v1 vq2 having vq1.b = 3) dt; b drop view v1; SELECT /*+ SET_VAR(optimizer_switch = 'materialization=off,semijoin=off') */ * FROM t1 AS ta, lateral (select 1 WHERE ta.a IN (SELECT b FROM t2 AS tb WHERE tb.b >= SOME(SELECT SUM(tc.a) as sg FROM t1 as tc GROUP BY tc.b HAVING ta.a=tc.b))) dt; a b 1 select (select dt.a from (select 1 as a, t2.a as b from t2 having t1.a) dt where dt.b=t1.a) as subq from t1; subq 1 1 select (select dt.a from (select 1 as a, 3 as b from t2 having t1.a) dt where dt.b=t1.a) as subq from t1; subq NULL NULL # Aggregation in outer context select (select f from (select max(t1.a) as f) as dt) as g from t1; g 2 select (select f from lateral (select max(t1.a) as f) as dt) as g from t1; g 2 # LATERAL doesn't allow an aggregate to resolve to the # immediate parent (because reading of FROM tables happens # before aggregation). So it resolves in the derived table, so # the outer query doesn't produce a single-row result. select t1.a, f from t1, lateral (select max(t1.a) as f) as dt; a f 1 1 2 2 # We support CTE inside derived table select * from t1, lateral (with qn as (select t1.a) select (select max(a) from qn)) as dt; a b (select max(a) from qn) 1 NULL 1 2 NULL 2 # Coverage for crash in Item_ident::fix_after_pullout: # when we merge a derived table contained in a derived table, # and the merged one contains an outer ref to the top query. select (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) from t1; (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) 1 2 # Semijoin containing a correlated derived table, DT must # become LATERAL explain select a from t1 where a in (select a from (select t1.a) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where; Rematerialize () 1 PRIMARY NULL ref 5 test.t1.a 2 100.00 Using index; FirstMatch(t1) 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (lateral (/* select#3 */ select `test`.`t1`.`a` AS `a`) `dt`) where (`dt`.`a` = `test`.`t1`.`a`) select a from t1 where a in (select a from (select t1.a) dt); a 1 2 create table t3 as with recursive cte as (select 1 as a union select a+1 from cte where a<20) select * from cte; analyze table t3; Table Op Msg_type Msg_text test.t3 analyze status OK explain select min(a),max(a) from t3 where a in (select /*+ no_merge() */ a from (select t3.a from t1) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 NULL ALL NULL NULL NULL NULL 20 100.00 Using where; Rematerialize () 1 PRIMARY NULL ref 9 test.t3.a 2 100.00 Using index; FirstMatch(t3) 3 DEPENDENT DERIVED t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t3.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select /*+ NO_MERGE(@`select#2`) */ min(`test`.`t3`.`a`) AS `min(a)`,max(`test`.`t3`.`a`) AS `max(a)` from `test`.`t3` semi join (lateral (/* select#3 */ select `test`.`t3`.`a` AS `a` from `test`.`t1`) `dt`) where (`dt`.`a` = `test`.`t3`.`a`) select min(a),max(a) from t3 where a in (select /*+ no_merge() */ a from (select t3.a from t1) dt); min(a) max(a) 1 20 drop table t3; # DT containing a correlated DT which must become LATERAL explain format=tree select * from t1, lateral (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) dt3; EXPLAIN -> Nested loop inner join -> Invalidate materialized tables (row from t1) (cost=0.45 rows=2) -> Table scan on t1 (cost=0.45 rows=2) -> Table scan on dt3 -> Materialize (invalidate on row from t1) -> Table scan on dt2 -> Materialize -> Limit: 1 row(s) -> Table scan on dt -> Materialize -> Table scan on t2 (cost=0.45 rows=2) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #4 was resolved in SELECT #1 explain select * from t1, lateral (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) dt3; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 4 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #4 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt3`.`a` AS `a` from `test`.`t1` join lateral (/* select#2 */ select `dt2`.`a` AS `a` from (/* select#3 */ select `dt`.`a` AS `a` from (/* select#4 */ select `test`.`t1`.`a` AS `a` from `test`.`t2`) `dt` limit 1) `dt2`) `dt3` select * from t1, lateral (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) dt3; a b a 1 NULL 1 2 NULL 2 explain select * from t1 as t0, lateral (select dt3.* from t1, lateral (select * from (select * from (select t0.a from t2) as dt limit 1) dt2) dt3) dt4; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t0 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 4 100.00 NULL 2 DEPENDENT DERIVED t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 3 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 4 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 5 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t0.a' of SELECT #5 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`dt4`.`a` AS `a` from `test`.`t1` `t0` join lateral (/* select#2 */ select `dt3`.`a` AS `a` from `test`.`t1` join (/* select#3 */ select `dt2`.`a` AS `a` from (/* select#4 */ select `dt`.`a` AS `a` from (/* select#5 */ select `test`.`t0`.`a` AS `a` from `test`.`t2`) `dt` limit 1) `dt2`) `dt3`) `dt4` select * from t1 as t0, lateral (select dt3.* from t1, lateral (select * from (select * from (select t0.a from t2) as dt limit 1) dt2) dt3) dt4; a b a 1 NULL 1 1 NULL 1 2 NULL 2 2 NULL 2 explain select /*+ no_merge() */ * from t1 as t0, lateral (select dt3.* from t1, lateral (select * from (select * from (select t0.a from t2) as dt limit 1) dt2) dt3) dt4; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t0 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 4 100.00 NULL 2 DEPENDENT DERIVED t1 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 3 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 4 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 5 DEPENDENT DERIVED t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL Warnings: Note 1276 Field or reference 'test.t0.a' of SELECT #5 was resolved in SELECT #1 Note 1003 /* select#1 */ select /*+ NO_MERGE(@`select#1`) */ `test`.`t0`.`a` AS `a`,`test`.`t0`.`b` AS `b`,`dt4`.`a` AS `a` from `test`.`t1` `t0` join lateral (/* select#2 */ select `dt3`.`a` AS `a` from `test`.`t1` join (/* select#3 */ select `dt2`.`a` AS `a` from (/* select#4 */ select `dt`.`a` AS `a` from (/* select#5 */ select `test`.`t0`.`a` AS `a` from `test`.`t2`) `dt` limit 1) `dt2`) `dt3`) `dt4` select /*+ no_merge() */ * from t1 as t0, lateral (select dt3.* from t1, lateral (select * from (select * from (select t0.a from t2) as dt limit 1) dt2) dt3) dt4; a b a 1 NULL 1 1 NULL 1 2 NULL 2 2 NULL 2 explain select * from t1, lateral (select * from (select 42) t1, (select t1.a) dt2) dt3; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL system NULL NULL NULL NULL 1 100.00 NULL 2 DEPENDENT DERIVED NULL ALL NULL NULL NULL NULL 2 100.00 NULL 4 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used 3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #4 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt3`.`42` AS `42`,`dt3`.`a` AS `a` from `test`.`t1` join lateral (/* select#2 */ select '42' AS `42`,`dt2`.`a` AS `a` from (/* select#4 */ select `test`.`t1`.`a` AS `a`) `dt2`) `dt3` select * from t1, lateral (select * from (select 42) t1, (select t1.a) dt2) dt3; a b 42 a 1 NULL 42 1 2 NULL 42 2 without semijoin: index_subquery needs to re-materialize explain select a from t1 where a in (select /*+ no_semijoin() */ a from (select t1.a) dt); id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Using where 2 DEPENDENT SUBQUERY NULL index_subquery 5 func 2 100.00 Using index 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select /*+ NO_SEMIJOIN(@`select#2`) */ `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a`,(((`test`.`t1`.`a`) in dt on ))) select a from t1 where a in (select /*+ no_semijoin() */ a from (select t1.a) dt); a 1 2 select a from t1 where a in (with cte as (select t1.a) select /*+ no_semijoin() */ a from cte); a 1 2 # Count rematerializations # In all three plans, handler_write is 2, showing that we # rematerialize only when necessary (when row of t1 changes) explain select straight_join * from t1, t2, lateral (select t1.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`dt`.`a` AS `a` from `test`.`t1` join `test`.`t2` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` flush status; select straight_join * from t1, t2, lateral (select t1.a) as dt; a b a b a 1 NULL 1 NULL 1 1 NULL 2 NULL 1 2 NULL 1 NULL 2 2 NULL 2 NULL 2 # when a row of t1 produces two rows of t2 passed to "dt", # it still makes one materialization. show status like "handler_write"; Variable_name Value Handler_write 2 explain select straight_join * from t1, lateral (select t1.a) as dt, t2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join `test`.`t2` flush status; select straight_join * from t1, lateral (select t1.a) as dt, t2; a b a a b 1 NULL 1 1 NULL 1 NULL 1 2 NULL 2 NULL 2 1 NULL 2 NULL 2 2 NULL show status like "handler_write"; Variable_name Value Handler_write 2 explain select straight_join * from t2, t1, lateral (select t1.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize (); Using join buffer (Block Nested Loop) 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select straight_join `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` flush status; select straight_join * from t2, t1, lateral (select t1.a) as dt; a b a b a 1 NULL 1 NULL 1 1 NULL 2 NULL 2 2 NULL 1 NULL 1 2 NULL 2 NULL 2 # Due to join buffer, order t2-t1 produces rows as a # non-buffered t1-t2 plan: t1 buffers all rows of t2, then for # each row of t1 it's joined to all rows of t2 and passed to t2; # when a row of t1 produces two rows of t2 passed to "dt", # it still makes one materialization. show status like "handler_write"; Variable_name Value Handler_write 2 # Let the planner find the best plan. # It doesn't work so well, because of # optimizer_prune_level=1 (see bug#28629788): order specified by # the user is sorted by number of rows, which leaves it # unchanged (Card(t1)=Card(t2)=Card(dt)); then it is the first # explored plan so it's explored in full, and later t1-dt is rejected as # more expensive than t1-t2. Whereas if t1-dt had been explored # deeper, we'd see t1-dt-t2 is actually the cheapest, because # it reads dt the least number of times (and dt has a high read # cost because Temptable::scan_time() is incredibly high but # that's another issue; see bug#28631100). # t2 cannot use join buffering as between "dt" and its # dependency t1: join buffering would interlace rows of t1 # thus cause more rematerializations. explain select * from t1, t2, lateral (select t1.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`dt`.`a` AS `a` from `test`.`t1` join `test`.`t2` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` flush status; select * from t1, t2, lateral (select t1.a) as dt; a b a b a 1 NULL 1 NULL 1 1 NULL 2 NULL 1 2 NULL 1 NULL 2 2 NULL 2 NULL 2 show status like "handler_write"; Variable_name Value Handler_write 2 # This one finds the best plan. Yes we simply swapped tables in the query, # and it yields a different plan. This is because the order specified by # the user is sorted by number of rows, which leaves it # unchanged (Card(t1)=Card(t2)=Card(dt), then it is the first # explored plan so it's explored in full and so is never pruned by # prune_level=1, and it is the best plan. Best as: it reads # "dt" less, and t2 uses join buffering (which is ok as it's # after "dt"). # If prune_level=0, all 3 variants here produce this plan. explain select * from t1, lateral (select t1.a) as dt, t2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join `test`.`t2` flush status; select * from t1, lateral (select t1.a) as dt, t2; a b a a b 1 NULL 1 1 NULL 1 NULL 1 2 NULL 2 NULL 2 1 NULL 2 NULL 2 2 NULL show status like "handler_write"; Variable_name Value Handler_write 2 # This one is intermediate: t1 uses join buffer (good), but # "dt" is last (bad, as it has high scan cost). explain select * from t2, t1, lateral (select t1.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize (); Using join buffer (Block Nested Loop) 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` flush status; select * from t2, t1, lateral (select t1.a) as dt; a b a b a 1 NULL 1 NULL 1 1 NULL 2 NULL 2 2 NULL 1 NULL 1 2 NULL 2 NULL 2 show status like "handler_write"; Variable_name Value Handler_write 2 # Show the trace of planning of lateral derived tables explain select * from t1, lateral (select t1.a from t2 as t3, t2 as t4) as dt, t2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 4 100.00 NULL 2 DEPENDENT DERIVED t3 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED t4 NULL ALL NULL NULL NULL NULL 2 100.00 Using join buffer (Block Nested Loop) Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t2` `t3` join `test`.`t2` `t4`) `dt` join `test`.`t2` select trace from information_schema.optimizer_trace; trace { "steps": [ { "join_preparation": { "select#": 1, "steps": [ { "join_preparation": { "select#": 2, "steps": [ { "expanded_query": "/* select#2 */ select `t1`.`a` AS `a` from `t2` `t3` join `t2` `t4`" } ] } }, { "derived": { "table": " `dt`", "select#": 2, "materialized": true } }, { "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`dt`.`a` AS `a`,`t2`.`a` AS `a`,`t2`.`b` AS `b` from `t1` join lateral (/* select#2 */ select `t1`.`a` AS `a` from `t2` `t3` join `t2` `t4`) `dt` join `t2`" } ] } }, { "join_optimization": { "select#": 1, "steps": [ { "join_optimization": { "select#": 2, "steps": [ { "table_dependencies": [ { "table": "`t2` `t3`", "row_may_be_null": false, "map_bit": 0, "depends_on_map_bits": [ ] }, { "table": "`t2` `t4`", "row_may_be_null": false, "map_bit": 1, "depends_on_map_bits": [ ] } ] }, { "rows_estimation": [ { "table": "`t2` `t3`", "table_scan": { "rows": 2, "cost": 0.25 } }, { "table": "`t2` `t4`", "table_scan": { "rows": 2, "cost": 0.25 } } ] }, { "considered_execution_plans": [ { "plan_prefix": [ ], "table": "`t2` `t3`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "resulting_rows": 2, "cost": 0.45, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 2, "cost_for_plan": 0.45, "rest_of_plan": [ { "plan_prefix": [ "`t2` `t3`" ], "table": "`t2` `t4`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "using_join_cache": true, "buffers_needed": 1, "resulting_rows": 2, "cost": 0.65, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 4, "cost_for_plan": 1.1, "chosen": true } ] }, { "plan_prefix": [ ], "table": "`t2` `t4`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "resulting_rows": 2, "cost": 0.45, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 2, "cost_for_plan": 0.45, "pruned_by_heuristic": true } ] }, { "attaching_conditions_to_tables": { "original_condition": null, "attached_conditions_computation": [ ], "attached_conditions_summary": [ { "table": "`t2` `t3`", "attached": null }, { "table": "`t2` `t4`", "attached": null } ] } }, { "finalizing_table_conditions": [ ] }, { "refine_plan": [ { "table": "`t2` `t3`" }, { "table": "`t2` `t4`" } ] } ] } }, { "table_dependencies": [ { "table": "`t1`", "row_may_be_null": false, "map_bit": 0, "depends_on_map_bits": [ ] }, { "table": " `dt`", "row_may_be_null": false, "map_bit": 1, "depends_on_map_bits": [ 0 ] }, { "table": "`t2`", "row_may_be_null": false, "map_bit": 2, "depends_on_map_bits": [ ] } ] }, { "rows_estimation": [ { "table": "`t1`", "table_scan": { "rows": 2, "cost": 0.25 } }, { "table": " `dt`", "table_scan": { "rows": 4, "cost": 2.55 } }, { "table": "`t2`", "table_scan": { "rows": 2, "cost": 0.25 } } ] }, { "considered_execution_plans": [ { "plan_prefix": [ ], "table": "`t1`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "filtering_effect": [ ], "final_filtering_effect": 1, "access_type": "scan", "resulting_rows": 2, "cost": 0.45, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 2, "cost_for_plan": 0.45, "rest_of_plan": [ { "plan_prefix": [ "`t1`" ], "table": "`t2`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "access_type": "scan", "resulting_rows": 2, "cost": 0.9, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 4, "cost_for_plan": 1.35, "rest_of_plan": [ { "plan_prefix": [ "`t1`", "`t2`" ], "table": " `dt`", "best_access_path": { "considered_access_paths": [ { "lateral_materialization": { "cost_for_one_run_of_inner_query": 1.099, "cost_for_writing_to_tmp_table": 0.4, "count_of_runs": 2, "total_cost": 2.998, "cost_per_read": 0.7495 } }, { "rows_to_scan": 4, "access_type": "scan", "resulting_rows": 4, "cost": 11.8, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 16, "cost_for_plan": 13.899, "chosen": true } ] }, { "plan_prefix": [ "`t1`" ], "table": " `dt`", "best_access_path": { "considered_access_paths": [ { "lateral_materialization": { "cost_for_one_run_of_inner_query": 1.099, "cost_for_writing_to_tmp_table": 0.4, "count_of_runs": 2, "total_cost": 2.998, "cost_per_read": 1.499 } }, { "rows_to_scan": 4, "access_type": "scan", "resulting_rows": 4, "cost": 5.9, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 8, "cost_for_plan": 7.849, "pruned_by_heuristic": true } ] }, { "plan_prefix": [ ], "table": "`t2`", "best_access_path": { "considered_access_paths": [ { "rows_to_scan": 2, "access_type": "scan", "resulting_rows": 2, "cost": 0.45, "chosen": true } ] }, "condition_filtering_pct": 100, "rows_for_plan": 2, "cost_for_plan": 0.45, "pruned_by_heuristic": true } ] }, { "attaching_conditions_to_tables": { "original_condition": null, "attached_conditions_computation": [ ], "attached_conditions_summary": [ { "table": "`t1`", "attached": null }, { "table": "`t2`", "attached": null }, { "table": " `dt`", "attached": null } ] } }, { "finalizing_table_conditions": [ ] }, { "refine_plan": [ { "table": "`t1`" }, { "table": "`t2`" }, { "table": " `dt`", "rematerialized_for_each_row_of": "t1" } ] } ] } }, { "join_explain": { "select#": 1, "steps": [ { "creating_tmp_table": { "tmp_table_info": { "table": " `dt`", "in_plan_at_position": 2, "columns": 1, "row_length": 5, "key_length": 0, "unique_constraint": false, "makes_grouped_rows": false, "cannot_insert_duplicates": false, "location": "TempTable" } } }, { "join_explain": { "select#": 2, "steps": [ ] } } ] } } ] } # LDT depending on const table only create table t3(a int) engine=innodb; insert into t3 values(3); analyze table t3; Table Op Msg_type Msg_text test.t3 analyze status OK explain select * from t3, lateral (select t3.a+1) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 NULL ALL NULL NULL NULL NULL 1 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t3.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t3`.`a` AS `a`,`dt`.`t3.a+1` AS `t3.a+1` from `test`.`t3` join lateral (/* select#2 */ select (`test`.`t3`.`a` + 1) AS `t3.a+1`) `dt` select * from t3, lateral (select t3.a+1) as dt; a t3.a+1 3 4 drop table t3; # Two LDTs depending on different tables explain select * from t2, t1, lateral (select t1.a) as dt, lateral (select t2.a) as dt2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`dt2`.`a` AS `a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join lateral (/* select#3 */ select `test`.`t2`.`a` AS `a`) `dt2` select * from t2, t1, lateral (select t1.a) as dt, lateral (select t2.a) as dt2; a b a b a a 1 NULL 1 NULL 1 1 1 NULL 2 NULL 2 1 2 NULL 1 NULL 1 2 2 NULL 2 NULL 2 2 # Two LDTs depending on one same table explain select * from t2, t1, lateral (select t1.a) as dt, lateral (select t1.a+1) as dt2; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize (,); Using join buffer (Block Nested Loop) 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 3 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`dt2`.`t1.a+1` AS `t1.a+1` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join lateral (/* select#3 */ select (`test`.`t1`.`a` + 1) AS `t1.a+1`) `dt2` explain format=json select * from t2, t1, lateral (select t1.a) as dt, lateral (select t1.a+1) as dt2; EXPLAIN { "query_block": { "select_id": 1, "cost_info": { "query_cost": "34.10" }, "nested_loop": [ { "table": { "table_name": "t2", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 2, "filtered": "100.00", "cost_info": { "read_cost": "0.25", "eval_cost": "0.20", "prefix_cost": "0.45", "data_read_per_join": "32" }, "used_columns": [ "a", "b" ] } }, { "table": { "table_name": "t1", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 4, "filtered": "100.00", "rematerialize": "dt,dt2", "using_join_buffer": "Block Nested Loop", "cost_info": { "read_cost": "0.25", "eval_cost": "0.40", "prefix_cost": "1.10", "data_read_per_join": "64" }, "used_columns": [ "a", "b" ] } }, { "table": { "table_name": "dt", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 8, "filtered": "100.00", "cost_info": { "read_cost": "10.30", "eval_cost": "0.80", "prefix_cost": "12.20", "data_read_per_join": "128" }, "used_columns": [ "a" ], "materialized_from_subquery": { "using_temporary_table": true, "dependent": true, "cacheable": true, "query_block": { "select_id": 2, "message": "No tables used" } } } }, { "table": { "table_name": "dt2", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 16, "filtered": "100.00", "cost_info": { "read_cost": "20.30", "eval_cost": "1.60", "prefix_cost": "34.10", "data_read_per_join": "256" }, "used_columns": [ "t1.a+1" ], "materialized_from_subquery": { "using_temporary_table": true, "dependent": true, "cacheable": true, "query_block": { "select_id": 3, "message": "No tables used" } } } } ] } } Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t1.a' of SELECT #3 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`a` AS `a`,`dt2`.`t1.a+1` AS `t1.a+1` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select `test`.`t1`.`a` AS `a`) `dt` join lateral (/* select#3 */ select (`test`.`t1`.`a` + 1) AS `t1.a+1`) `dt2` select * from t2, t1, lateral (select t1.a) as dt, lateral (select t1.a+1) as dt2; a b a b a t1.a+1 1 NULL 1 NULL 1 2 1 NULL 2 NULL 2 3 2 NULL 1 NULL 1 2 2 NULL 2 NULL 2 3 # One LDT depending on two tables. The "rematerialize" tag is # properly added to the 2nd dependency only. explain select * from t2, t1, lateral (select t1.a+t2.a) as dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t2 NULL ALL NULL NULL NULL NULL 2 100.00 NULL 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`t1.a+t2.a` AS `t1.a+t2.a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select (`test`.`t1`.`a` + `test`.`t2`.`a`) AS `t1.a+t2.a`) `dt` explain format=json select * from t2, t1, lateral (select t1.a+t2.a) as dt; EXPLAIN { "query_block": { "select_id": 1, "cost_info": { "query_cost": "12.45" }, "nested_loop": [ { "table": { "table_name": "t2", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 2, "filtered": "100.00", "cost_info": { "read_cost": "0.25", "eval_cost": "0.20", "prefix_cost": "0.45", "data_read_per_join": "32" }, "used_columns": [ "a", "b" ] } }, { "table": { "table_name": "t1", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 4, "filtered": "100.00", "rematerialize": "dt", "cost_info": { "read_cost": "0.50", "eval_cost": "0.40", "prefix_cost": "1.35", "data_read_per_join": "64" }, "used_columns": [ "a", "b" ] } }, { "table": { "table_name": "dt", "access_type": "ALL", "rows_examined_per_scan": 2, "rows_produced_per_join": 8, "filtered": "100.00", "cost_info": { "read_cost": "10.30", "eval_cost": "0.80", "prefix_cost": "12.45", "data_read_per_join": "128" }, "used_columns": [ "t1.a+t2.a" ], "materialized_from_subquery": { "using_temporary_table": true, "dependent": true, "cacheable": true, "query_block": { "select_id": 2, "message": "No tables used" } } } } ] } } Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`t1.a+t2.a` AS `t1.a+t2.a` from `test`.`t2` join `test`.`t1` join lateral (/* select#2 */ select (`test`.`t1`.`a` + `test`.`t2`.`a`) AS `t1.a+t2.a`) `dt` select * from t2, t1, lateral (select t1.a+t2.a) as dt; a b a b t1.a+t2.a 1 NULL 1 NULL 2 1 NULL 2 NULL 3 2 NULL 1 NULL 3 2 NULL 2 NULL 4 select json_extract(trace,"$.steps[*].join_optimization.steps[*].refine_plan") from information_schema.optimizer_trace; json_extract(trace,"$.steps[*].join_optimization.steps[*].refine_plan") [[{"table": "`t2`"}, {"table": "`t1`"}, {"table": " `dt`", "rematerialized_for_each_row_of": "t1"}]] # Test when a dependency of LDT uses BKA: BKA code must # refresh LDT's content when it provides a row. set @old_opt_switch=@@optimizer_switch; set @@optimizer_switch="batched_key_access=on,mrr_cost_based=off"; CREATE TABLE t11 (t11a int, t11b int); INSERT INTO t11 VALUES (99, NULL),(99, 3),(99,0); CREATE TABLE t12 (t12a int, t12b int, KEY idx (t12b)); INSERT INTO t12 VALUES (100,0),(150,200),(999, 0),(999, NULL); ANALYZE TABLE t11,t12; Table Op Msg_type Msg_text test.t11 analyze status OK test.t12 analyze status OK explain SELECT * FROM t11 LEFT JOIN t12 force index (idx) ON t12.t12b = t11.t11b JOIN LATERAL (SELECT t12a) dt; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t11 NULL ALL NULL NULL NULL NULL 3 100.00 NULL 1 PRIMARY t12 NULL ref idx idx 5 test.t11.t11b 1 100.00 Rematerialize (); Using join buffer (Batched Key Access) 1 PRIMARY NULL ALL NULL NULL NULL NULL 2 100.00 NULL 2 DEPENDENT DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: Note 1276 Field or reference 'test.t12.t12a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t11`.`t11a` AS `t11a`,`test`.`t11`.`t11b` AS `t11b`,`test`.`t12`.`t12a` AS `t12a`,`test`.`t12`.`t12b` AS `t12b`,`dt`.`t12a` AS `t12a` from `test`.`t11` left join `test`.`t12` FORCE INDEX (`idx`) on((`test`.`t12`.`t12b` = `test`.`t11`.`t11b`)) join lateral (/* select#2 */ select `test`.`t12`.`t12a` AS `t12a`) `dt` where true flush status; SELECT * FROM t11 LEFT JOIN t12 force index (idx) ON t12.t12b = t11.t11b JOIN LATERAL (SELECT t12a) dt; t11a t11b t12a t12b t12a 99 0 100 0 100 99 0 999 0 999 99 NULL NULL NULL NULL 99 3 NULL NULL NULL show status like "handler_write"; Variable_name Value Handler_write 3 DROP TABLE t11,t12; set @@optimizer_switch=@old_opt_switch; # Test that with an auto_key on the lateral DT, the index is # properly emptied and re-filled when re-materializing. # If index weren't emptied, we'd see too many "11" matches for 2nd # row of t1; and if not re-filled, we'd see no matches for that. create table t3 (a int, b int); insert into t3 values(1, 10), (1, 11), (2, 10), (2, 11); analyze table t3; Table Op Msg_type Msg_text test.t3 analyze status OK # Note the auto_key with "Using index", to test the index as # much as possible. explain select * from t1, lateral (select t3.b from t3 where t3.a=t1.a) dt where dt.b=t1.a+9; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 NULL ALL NULL NULL NULL NULL 2 100.00 Rematerialize () 1 PRIMARY NULL ref 5 func 2 100.00 Using where; Using index 2 DEPENDENT DERIVED t3 NULL ALL NULL NULL NULL NULL 4 25.00 Using where Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`dt`.`b` AS `b` from `test`.`t1` join lateral (/* select#2 */ select `test`.`t3`.`b` AS `b` from `test`.`t3` where (`test`.`t3`.`a` = `test`.`t1`.`a`)) `dt` where (`dt`.`b` = (`test`.`t1`.`a` + 9)) select * from t1, lateral (select t3.b from t3 where t3.a=t1.a) dt where dt.b=t1.a+9; a b b 1 NULL 10 2 NULL 11 drop table t3; set optimizer_switch='derived_merge=off'; # Reserved word create table lateral(a int); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'lateral(a int)' at line 1 drop table t1,t2; # # Bug#28723670 RECENT REGRESSION: CRASH/ASSERTION IN FIND_FIELD_IN_TABLE_REF # CREATE TABLE t(x INT); # Don't search for 'y' in top SELECT SELECT 1 FROM (SELECT 1 FROM (SELECT (SELECT y FROM t) FROM t) AS a) AS b; ERROR 42S22: Unknown column 'y' in 'field list' DROP TABLE t; # # Bug#28976533 ASSERTION `JOIN->BEST_READ < DOUBLE(1.79769313486231570814527423731704357E+308L) # CREATE TABLE bb ( pk INTEGER AUTO_INCREMENT, col_int INTEGER , col_int_key INTEGER , col_time_key TIME , col_time TIME , col_datetime_key DATETIME , col_datetime DATETIME , col_varchar_key VARCHAR(20) , col_varchar VARCHAR(20) , PRIMARY KEY (pk DESC), KEY (col_time_key), KEY (col_time_key DESC) ); SET SQL_MODE=''; EXPLAIN SELECT grandparent1.col_varchar_key AS g1 FROM bb AS grandparent1 LEFT JOIN bb AS grandparent2 USING ( col_time ) WHERE grandparent1.col_int_key IN ( WITH qn AS ( SELECT parent1.col_int AS p1 FROM bb AS parent1 LEFT JOIN bb AS parent2 USING ( col_varchar ) WHERE parent1.col_varchar_key IN ( WITH qn1 AS ( SELECT DISTINCT child1.col_varchar_key AS C1 FROM bb AS child1 LEFT JOIN bb AS child2 ON child1.col_varchar_key <= child2.col_varchar WHERE child1.col_time > grandparent1.col_datetime ) SELECT * FROM qn1 ) AND parent1.col_time_key BETWEEN '2008-03-18' AND '2004-11-14' ) SELECT /*+ MERGE(qn) */ * FROM qn ) GROUP BY grandparent1.col_int; id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 5 DEPENDENT DERIVED child1 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using temporary 5 DEPENDENT DERIVED child2 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Distinct; Using join buffer (Block Nested Loop) Warnings: Note 1276 Field or reference 'test.grandparent1.col_datetime' of SELECT #5 was resolved in SELECT #1 Warning 1292 Incorrect time value: '2008-03-18' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2004-11-14' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2008-03-18' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2008-03-18' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2004-11-14' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2004-11-14' for column 'col_time_key' at row 1 Note 1003 /* select#1 */ select /*+ MERGE(`qn`@`select#2`) */ `test`.`grandparent1`.`col_varchar_key` AS `g1` from `test`.`bb` `grandparent1` left join `test`.`bb` `grandparent2` on(multiple equal(`test`.`grandparent1`.`col_time`, `test`.`grandparent2`.`col_time`)) semi join (`test`.`bb` `parent1` left join `test`.`bb` `parent2` on((`test`.`parent1`.`col_varchar` = `test`.`parent2`.`col_varchar`)) join `qn1`) where ((`test`.`parent1`.`col_time_key` between '2008-03-18' and '2004-11-14') and multiple equal(`test`.`grandparent1`.`col_int_key`, `test`.`parent1`.`col_int`) and multiple equal(`test`.`parent1`.`col_varchar_key`, `qn1`.`C1`)) group by `test`.`grandparent1`.`col_int` SELECT grandparent1.col_varchar_key AS g1 FROM bb AS grandparent1 LEFT JOIN bb AS grandparent2 USING ( col_time ) WHERE grandparent1.col_int_key IN ( WITH qn AS ( SELECT parent1.col_int AS p1 FROM bb AS parent1 LEFT JOIN bb AS parent2 USING ( col_varchar ) WHERE parent1.col_varchar_key IN ( WITH qn1 AS ( SELECT DISTINCT child1.col_varchar_key AS C1 FROM bb AS child1 LEFT JOIN bb AS child2 ON child1.col_varchar_key <= child2.col_varchar WHERE child1.col_time > grandparent1.col_datetime ) SELECT * FROM qn1 ) AND parent1.col_time_key BETWEEN '2008-03-18' AND '2004-11-14' ) SELECT /*+ MERGE(qn) */ * FROM qn ) GROUP BY grandparent1.col_int; g1 Warnings: Warning 1292 Incorrect time value: '2008-03-18' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2004-11-14' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2008-03-18' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2008-03-18' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2004-11-14' for column 'col_time_key' at row 1 Warning 1292 Incorrect time value: '2004-11-14' for column 'col_time_key' at row 1 DROP TABLE bb; SET SQL_MODE=DEFAULT; # # Bug #29268512: ASSERTION FAILED: INITED == NONE INTERMITTENTLY # CREATE TABLE t1 ( f1 integer ); INSERT INTO t1 VALUES (0),(1); CREATE TABLE t2 ( f2 integer ); SELECT * FROM t1, LATERAL ( SELECT MAX(1) FROM t2 GROUP BY t1.f1 ) AS l1; f1 MAX(1) DROP TABLE t1, t2; # # Bug #29334082: Still crashing in actual_key_parts() / assert inited == INDEX # CREATE TABLE t1 ( f1 INTEGER ); CREATE TABLE t2 ( f2 LONGBLOB ); INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES ('abc'),('def'); SELECT STD(0) FROM t2, LATERAL ( SELECT f1 FROM t1 GROUP BY f2,f1 ) AS d1; STD(0) 0 DROP TABLE t1, t2; # # Bug#28954838 ASSERTION `(REMAINING_TABLES_AFTER != 0) || ((CUR_EMBEDDING_MAP == 0) && (JOIN-> # CREATE TABLE t1 ( pk INTEGER, col_int INT not null, col_int_key INT not null, col_time_gckey TIME, col_varchar VARCHAR(20) not null, col_varchar_key VARCHAR(15) not null ); CREATE TABLE t2 ( pk INTEGER, col_int INT not null, col_varchar VARCHAR(20) not null, col_varchar_key VARCHAR(15) not null ); SET OPTIMIZER_SWITCH='derived_merge=off'; SELECT table1.col_varchar_key AS field1, table2.col_time_gckey AS field2 FROM t2 AS table1 STRAIGHT_JOIN t1 AS table2 ON table2.col_varchar_key = table1.col_varchar_key WHERE table2.col_int_key IN (WITH qn AS (SELECT sq1_t1.col_int AS sq1_field1 FROM t2 AS sq1_t1 WHERE sq1_t1.col_varchar_key = table2.col_varchar OR EXISTS (WITH qn1 AS (SELECT c_sq1_t1.col_int_key AS c_sq1_field1 FROM t1 AS c_sq1_t1 WHERE c_sq1_t1.col_varchar_key > sq1_t1.col_varchar OR c_sq1_t1.col_int <> c_sq1_t1.pk ) SELECT * FROM qn1 ) ) SELECT * FROM qn ) AND EXISTS (WITH qn AS (SELECT sq2_t1.col_varchar AS sq2_field1 FROM t1 AS sq2_t1 STRAIGHT_JOIN t2 AS sq2_t2 INNER JOIN t1 AS sq2_t3 ON sq2_t3.col_varchar = sq2_t2.col_varchar_key ON sq2_t3.col_int = sq2_t2.pk ) SELECT * FROM qn ) AND table2.col_varchar_key <> 'j'; field1 field2 SET OPTIMIZER_SWITCH=DEFAULT; DROP TABLE t1,t2; # # Bug#28955358 VIRTUAL LONGLONG FIELD_NEWDATE::VAL_DATE_TEMPORAL(): ASSERTION `!TABLE || (!TAB # CREATE TABLE t1 ( pk INTEGER, col_int_key INTEGER NOT NULL, col_date_key DATE NOT NULL, col_datetime DATETIME NOT NULL ); INSERT INTO t1 VALUES (0, 0, '2006-07-18', '2001-09-06 02:13:59.021506'); SELECT /*+ no_merge() */ outr.pk AS x FROM ( SELECT * FROM t1 ) AS outr WHERE outr.col_int_key IN ( SELECT /*+ no_merge() no_semijoin() */ 2 FROM (SELECT 1 AS x FROM t1 AS innr WHERE outr.col_date_key ) AS qn ) ORDER BY outr.col_datetime; x SELECT /*+ no_merge() */ outr.pk AS x FROM ( SELECT * FROM t1 ) AS outr WHERE outr.col_int_key IN ( SELECT /*+ no_merge() no_semijoin() */ id FROM JSON_TABLE( IF(outr.col_date_key<>NOW(), '[{"a":"3"},{"a":2},{"b":1},{"a":0}]', '') , '$[*]' columns (id for ordinality, jpath varchar(100) path '$.a', jexst int exists path '$.b') ) AS qn ) ORDER BY outr.col_datetime; x DROP TABLE t1; CREATE TABLE t1(pk INT PRIMARY KEY, a INT); EXPLAIN SELECT pk FROM t1 GROUP BY a; ERROR 42000: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.t1.pk' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by EXPLAIN SELECT (SELECT pk FROM (SELECT t1.pk) dt) FROM t1 GROUP BY a; ERROR 42000: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.t1.pk' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by DROP TABLE t1; # # Bug#28960857 ASSERTION FAILED: !TR->DERIVED_WHERE_COND || TR->DERIVED_WHERE_COND->FIXED # Bug#28960789 ASSERTION FAILED: TRANSL->ITEM->FIXED, # CREATE TABLE t0007 ( c0008 date NOT NULL, c0009 char(234) NOT NULL ); CREATE TABLE t0008 ( c0005 tinytext NOT NULL ); CREATE TABLE t0009 ( c0000 time NOT NULL ); SET SQL_MODE=0; SELECT (SELECT t0007.c0009 FROM (SELECT t0007.c0008 AS c0003 FROM t0009 ) AS t0005 ) FROM t0007 GROUP BY -23; (SELECT t0007.c0009 FROM (SELECT t0007.c0008 AS c0003 FROM t0009 ) AS t0005 ) SELECT (SELECT c0009 FROM (SELECT 1 AS c0003 FROM t0009 INNER JOIN t0008 ON t0008.c0005 WHERE t0007.c0008 ) AS t0005 GROUP BY c0008 ), COUNT(c0009) FROM t0007 GROUP BY 1, 1; (SELECT c0009 FROM (SELECT 1 AS c0003 FROM t0009 INNER JOIN t0008 ON t0008.c0005 WHERE t0007.c0008 ) AS t0005 GROUP BY c0008 ) COUNT(c0009) DROP TABLE t0007, t0008, t0009; SET SQL_MODE=DEFAULT; # # Bug #29514504: WRONG RESULT WITH CORRELATED LATERAL JOIN # CREATE TABLE t1 (id INTEGER); CREATE TABLE t2 (id INTEGER); INSERT INTO t1 VALUES (10), (20), (30); INSERT INTO t2 VALUES (20), (20); SELECT * FROM t1 JOIN LATERAL ( SELECT GROUP_CONCAT(t.id) AS c FROM t2 t WHERE (t.id = t1.id) ) d0 ON (1); id c 10 NULL 20 20,20 30 NULL DROP TABLE t1, t2; # # Bug #30110851: SUBQUERY INVOLVES COUNT() AGGREGATE FUNCTION PERFORMANCE REGRESSION # CREATE TABLE t1 ( f1 INTEGER NOT NULL, f2 INTEGER NOT NULL ); CREATE TABLE t2 ( f1 INTEGER NOT NULL, f2 INTEGER NOT NULL ); CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; CREATE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT ( SELECT f2 FROM v1 WHERE v1.f1 = t2.f1 ) AS f3 FROM t2; EXPLAIN FORMAT=TREE SELECT * FROM v2 WHERE f3 = 3; EXPLAIN -> Index lookup on v2 using (f3=3) -> Materialize -> Table scan on t2 (cost=0.35 rows=1) -> Select #3 (subquery in projection; dependent) -> Index lookup on v1 using (f1=t2.f1) -> Materialize -> Table scan on t1 (cost=0.35 rows=1) Warnings: Note 1276 Field or reference 'test.t2.f1' of SELECT #3 was resolved in SELECT #2 DROP TABLE t1, t2; DROP VIEW v1, v2;