1--source include/have_optimizer_trace.inc
2set optimizer_trace_max_mem_size=10000000,@@session.optimizer_trace="enabled=on";
3let $show_trace=
4select json_extract(trace,"$.steps[*].join_optimization.steps[*].refine_plan") from information_schema.optimizer_trace;
5
6--echo # WL#461: allow outer references in derived tables and CTEs
7
8create table t1(a int, b int);
9insert into t1 (a) values(1),(2);
10create table t2 select * from t1;
11analyze table t1,t2;
12
13set optimizer_switch='derived_merge=on';
14
15let $c=2;
16while ($c)
17{
18dec $c;
19
20--echo # Deep nesting: all intermediate subqueries are marked DEPENDENT
21
22let $query=
23select * from t1 where
24 (select count(*) from (select * from (select * from t1 t2
25    where 2=(select 2 from (select t1.a) dt1))dt3)dt4);
26eval explain $query;
27eval $query;
28
29--echo # If reference is removed, not DEPENDENT
30
31let $query=
32select * from t1 where
33 (select count(*) from (select * from (select * from t1 t2
34    where 2=(select 2 from (select 42) dt1))dt3)dt4);
35eval explain $query;
36eval $query;
37
38--echo # Outer ref is in SELECT list of derived table's definition
39
40# Justifies delete-all-rows in clear_corr_derived_etc
41
42let $query=
43select
44(select dt.a from
45  (select t1.a as a, t2.a as b from t2) dt where dt.b=t1.a)
46as subq
47from t1;
48
49eval explain $query;
50eval $query;
51
52--echo # In WHERE
53
54let $query=
55select
56(select dt.b from
57  (select t2.a as b from t2 where t1.a=t2.a) dt)
58as subq
59from t1;
60
61eval explain $query;
62eval $query;
63
64--echo # In GROUP BY
65
66# Justifies calling unit->execute() in
67# TABLE_LIST::materialized_derived(), instead of
68# first_select()->join->exec(), so that we get delete_all_rows on
69# group-by tmp table
70
71let $query=
72select
73(select dt.b from
74  (select sum(t2.a) as b from t2 group by t1.a) dt)
75as subq
76from t1;
77
78eval explain $query;
79eval $query;
80
81--echo # In HAVING
82
83# Justifies not marking derived table as const (even if it has one
84# row, as here), in SELECT_LEX_UNIT::optimize:
85# if const it's substituted during optimization and
86# thus const over all executions.
87
88let $query=
89select
90(select dt.b from
91  (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-1) dt)
92as subq
93from t1;
94
95eval explain $query;
96eval $query;
97
98let $query=
99select
100(select dt.b from
101  (select sum(t2.a) as b from t2 having t1.a=sum(t2.a)-2) dt)
102as subq
103from t1;
104
105eval explain $query;
106eval $query;
107
108--echo # In ORDER BY
109
110let $query=
111select
112(select dt.b from
113  (select t2.a as b from t2 order by if(t1.a=1,t2.a,-t2.a) limit 1) dt)
114as subq
115from t1;
116
117eval explain $query;
118eval $query;
119
120--echo # In window functions
121
122let $query=
123select
124(select dt.b from
125  (select t2.a, sum(t1.a*10+t2.a) over (order by if(t1.a=1,t2.a,-t2.a)) as b
126   from t2) dt where dt.a=1)
127as subq
128from t1;
129
130eval explain $query;
131eval $query;
132
133--echo # CTE referenced twice
134
135let $query=
136select
137(with dt as (select t1.a as a, t2.a as b from t2)
138 select dt2.a from dt dt1, dt dt2 where dt1.b=t1.a and dt2.b=dt1.b)
139as subq
140from t1;
141
142eval explain $query;
143eval $query;
144
145--echo Recursive CTE
146# Justifies:
147# - else if (tl->is_recursive_reference())
148# branch in clear_corr...
149# - !tl->table->is_created() &&
150# added before open_tmp_table(rec ref) in unit's execution
151# - removed empty() of fake_select_lex's table list at end of unit's
152# execution
153# - the said empty() should be done only if (full) in cleanup; same
154# for nullifying fake_select_lex->recursive_reference.
155
156select
157  (with recursive dt as
158    (select t1.a as a union select a+1 from dt where a<10)
159   select dt1.a from dt dt1 where dt1.a=t1.a
160  ) as subq
161from t1;
162
163select
164  (with recursive dt as
165    (select t1.a as a union select a+1 from dt where a<10)
166   select concat(count(*), ' - ', avg(dt.a)) from dt
167  ) as subq
168from t1;
169
170# Same with UNION ALL
171select
172  (with recursive dt as
173    (select t1.a as a union all select a+1 from dt where a<10)
174   select concat(count(*), ' - ', avg(dt.a)) from dt
175  ) as subq
176from t1;
177
178# cte-2-ref
179
180select
181(with dt as (select t1.a as a, t2.a as b from t2)
182 select dt2.a from dt dt1, dt dt2 where dt1.b=t1.a and dt2.b=dt1.b)
183as subq
184from t1;
185
186--echo # Two references to same CTE at different levels of nesting.
187# Justifies:
188# - clearing the CTE's tmp table at the right point of execution: when
189# executing the unit which owns the WITH clause, instead of when
190# executing the query block which owns the CTE reference (otherwise
191# deeper nested CTE user would empty table under feet of less nested
192# CTE user)
193# - adding OUTER_REF_TABLE_BIT in fix_outer_field() (this is
194# due to the added loop in that function, which assumed
195# mark_as_dependent adds the bit, but it doesn't). So it's a post-fix
196# for previous revision, but was discovered only after implementing
197# the first item. Without this BIT, subq to the right of "=" is
198# considered constant, so all execs of =() use the same value of the
199# subq (in a ref access).
200
201let $query=
202select (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;
203
204eval explain $query;
205eval explain format=tree $query;  # Demonstrates printing of CTEs printed multiple times.
206eval $query;
207
208# Same with HAVING to test similar change in Item_ref::fix_fields
209let $query=
210select (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;
211
212eval explain $query;
213eval $query;
214
215--echo # Scope of outer ref in CTE
216select (select * from (select t1.a) cte) from t1;
217# Equivalent query with CTE.
218# Per the std, when we evaluate a query expression, we start with
219# evaluation of its WITH clause elements (CTEs).
220# Evaluate subquery, so evaluate CTE, t1.a is available: ok
221select (with cte as (select t1.a) select * from cte) from t1;
222# Now same CTE is defined in top query.
223# Evaluate top query, so evaluate CTE, t1.a is not yet available:
224# error. Justifies the push_context in find_common_table_expr() which
225# itself implies the new "complex" loop in fix_outer_field()
226--error ER_UNKNOWN_TABLE
227with cte as (select t1.a) select (select * from cte) from t1;
228
229--echo # NOT IN(subquery using derived), handled with subquery materialization
230
231let $query=
232select * from t1
233where a not in (select dt.f+1 from (select t2.a as f from t2) dt);
234
235eval explain $query;
236eval $query;
237
238--echo # Now put an outer reference inside derived table:
239--echo # subquery is properly seen as correlated and subquery
240--echo # materialization is thus not used.
241
242let $query=
243select * from t1
244where a not in (select dt.f+1 from (select 0*t1.a+t2.a as f from t2) dt);
245
246eval explain $query;
247eval $query;
248
249--echo # Verify that a non-lateral derived table with an outer
250--echo # reference makes the semijoin be correlated and thus blocks
251--echo # semijoin-materialization-scan.
252create table t11 (a int);
253insert into t11
254 with recursive cte as (select 1 as a union all select a+1 from cte where a<124)
255 select * from cte;
256alter table t11 add index(a);
257create table t12 like t11;
258analyze table t11,t12;
259--echo # No outer ref: mat-scan chosen
260explain select
261 /*+ NO_SEMIJOIN(@subq1 FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) */
262 * from t11 where a in (select /*+ QB_NAME(subq1) NO_MERGE(dt) */ *
263                       from (select t12.a from t12) dt);
264--echo # outer ref: mat-scan not chosen
265explain select
266 /*+ NO_SEMIJOIN(@subq1 FIRSTMATCH, LOOSESCAN, DUPSWEEDOUT) */
267 * from t11 where a in (select /*+ QB_NAME(subq1) NO_MERGE(dt) */ *
268                       from (select t12.a+0*t11.a from t12) dt);
269DROP TABLE t11,t12;
270
271--echo LATERAL
272
273--echo # prevents join buffer if materialized (but not if merged)
274explain select dt.a from t1, lateral (select t1.a from t2) dt;
275
276--echo # no right join
277--error ER_TF_FORBIDDEN_JOIN_TYPE
278explain select dt.a from t1 right join lateral (select t1.a from t2) dt on 1;
279
280--echo # no bad left join either
281--error ER_BAD_FIELD_ERROR
282explain select dt.a from lateral (select t1.a from t2) dt left join t1 on 1;
283
284--echo # more complex case
285
286# Justifies call to propagate_table_maps() in
287#  TABLE_LIST::resolve_derived()
288
289--error ER_TF_FORBIDDEN_JOIN_TYPE
290explain SELECT * FROM t1
291LEFT JOIN
292lateral (select t1.a) as dt ON t1.a=dt.a
293RIGHT JOIN
294lateral (select dt.a) as dt1 ON dt.a=dt1.a;
295
296--echo # LATERAL DT depending on LATERAL DT
297
298# Justifies resolving _and_ materializing dt before resolving dt1,
299# i.e. changing the order in SELECT_LEX::resolve_derived().
300
301explain SELECT * FROM t1
302JOIN
303lateral (select t1.a) as dt ON t1.a=dt.a
304JOIN
305lateral (select dt.a) as dt1 ON dt.a=dt1.a;
306
307--echo # Placing lateral outer ref in SELECT list then HAVING
308
309--sorted_result
310select t1.a, dt.a from t1, lateral (select t1.a+t2.a as a from t2) dt;
311
312select t1.a, dt.a from t1, lateral (select t2.a as a from t2 having t1.a) dt;
313
314--echo # Inside view
315create view v1 as
316 select t1.a as f1, dt.a as f2
317 from t1, lateral (select t1.a+t2.a as a from t2) dt;
318show create view v1;
319--sorted_result
320select * from v1;
321drop view v1;
322
323--echo # Coverage for various branches in Item_ref::fix_fields
324
325# I took obscure queries copied from various existing tests, which
326# cover the interested code lines, and modified them to include
327# derived tables.
328
329SELECT COUNT(*) FROM t1 GROUP BY t1.a  HAVING t1.a IN (SELECT t3.a
330FROM t1 AS t3 WHERE t3.b IN (SELECT b FROM t2, lateral (select t1.a) dt));
331
332create view v1 as select a, b from t1;
333
334# used to crash;
335# as LATERAL table looks into the table to the left, which may be
336# view, it uses find_table_in_table_ref(), which expects a view
337# to be either merged or materialized at this stage; this justifies
338# resolving the LATERAL table a bit later than ordinary derived table:
339# i.e. at the same time as table function, in
340# SELECT_LEX::resolve_derived. See bug#27152428
341
342select vq1.b,dt.b from v1 vq1, lateral (select vq1.b) dt;
343
344# still coverage for item_ref::fix_fields
345select b from v1 vq1, lateral (select count(*) from v1 vq2 having vq1.b = 3) dt;
346
347drop view v1;
348
349SELECT
350/*+ SET_VAR(optimizer_switch = 'materialization=off,semijoin=off') */
351* 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;
352
353# Justifies that "sut" may be NULL, so use if(sut) when adding
354# OUTER_REF_TABLE_BIT in Item_ref::fix_fields, fix_outer_field
355
356select (select dt.a from   (select 1 as a, t2.a as b from t2 having
357t1.a) dt where dt.b=t1.a) as subq from t1;
358
359select (select dt.a from   (select 1 as a, 3 as b from t2 having t1.a)
360dt where dt.b=t1.a) as subq from t1;
361
362--echo # Aggregation in outer context
363
364# Justifies that check_sum_func(), when it calls set_aggregation(),
365# doesn't stop as soon as unit->item is nullptr: otherwise we wouldn't
366# mark the scalar subquery, leading to wrong results.
367# Also justifies not resetting allow_sum_func to 0 when resolving a
368# derived table: we want to allow aggregated outer references.
369select (select f from (select max(t1.a) as f) as dt) as g from t1;
370
371select (select f from lateral (select max(t1.a) as f) as dt) as g from t1;
372
373--echo # LATERAL doesn't allow an aggregate to resolve to the
374--echo # immediate parent (because reading of FROM tables happens
375--echo # before aggregation). So it resolves in the derived table, so
376--echo # the outer query doesn't produce a single-row result.
377# This was the simplest behaviour to implement.
378# SQL Server and PG reject such query. SQL2015 does not really
379# describe this case.
380
381select t1.a, f from t1, lateral (select max(t1.a) as f) as dt;
382
383--echo # We support CTE inside derived table
384
385select * from t1,
386lateral (with qn as (select t1.a) select (select max(a) from qn)) as dt;
387
388--echo # Coverage for crash in Item_ident::fix_after_pullout:
389--echo # when we merge a derived table contained in a derived table,
390--echo # and the merged one contains an outer ref to the top query.
391
392select (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) from t1;
393
394--echo # Semijoin containing a correlated derived table, DT must
395--echo # become LATERAL
396
397# Justifies making a non-lateral DT become a lateral one in
398# fix_tables_after_pullout.
399# Indeed, before semijoin merging "dt" has
400# an outer non-lateral ref to t1 so just needs to be materialized
401# when its owner (the IN subquery) starts execution.
402# But after semijoin merging 'dt' changes owner and we have:
403# /* select#1 */ select `test`.`t1`.`a` AS `a` from `test`.`t1`
404# semi join ((/* select#3 */ select `test`.`t1`.`a` AS `a`) `dt`)
405# where (`dt`.`a` = `test`.`t1`.`a`)
406# so 'dt' now has "lateral" refs (to t1), so we give it the LATERAL
407# word so that it is rematerialized every time and not only when its
408# owner (top query) starts execution.
409
410let $query=
411select a from t1 where a in (select a from (select t1.a) dt);
412eval explain $query;
413eval $query;
414
415# Justifies adding bits to dep_tables in fix_tables_after_pullout
416
417create table t3 as with recursive cte as (select 1 as a union select a+1 from cte where a<20) select * from cte;
418analyze table t3;
419
420# Before semijoin merging, dt has a non-lateral outer ref (to t3), so
421# its dep_tables is 0.
422# After merging, t3 has 20 rows, so optimizer would put 'dt' first in
423# plan, then t3, if dep_tables were left to 0, and this would give a
424# wrong result (20,20), as actually 'dt' depends on t3 and must be
425# after t3 in plan.
426
427let $query=
428select min(a),max(a) from t3 where a in (select /*+ no_merge() */ a from (select t3.a from t1) dt);
429eval explain $query;
430eval $query;
431
432drop table t3;
433
434--echo # DT containing a correlated DT which must become LATERAL
435
436# Justifies making a non-lateral DT become a lateral one in
437# fix_tables_after_pullout, see the "semijoin" text above.
438
439let $query=
440select * from t1, lateral (select * from (select * from (select t1.a from t2) as dt limit 1) dt2) dt3;
441
442eval explain format=tree $query;  # Demonstrates Materialize -> Temporary table (forced rematerialization always).
443eval explain $query;
444eval $query;
445
446# Here "dt2" must be made lateral, as its referenced table t0 will be
447# a neighbour in FROM after merging
448
449let $query=
450select * from t1 as t0,
451lateral
452(select dt3.* from t1, lateral (select * from (select * from (select t0.a
453from t2) as dt limit 1) dt2) dt3) dt4;
454
455eval explain $query;
456eval $query;
457
458# and here "dt2" needn't be made lateral, as t0 remains in outer
459# query.
460
461let $query=
462select /*+ no_merge() */ * from t1 as t0,
463lateral
464(select dt3.* from t1, lateral (select * from (select * from (select t0.a
465from t2) as dt limit 1) dt2) dt3) dt4;
466
467eval explain $query;
468eval $query;
469
470# In the second execution of this test, with all merging disabled,
471# we observe that dt3 loses its LATERAL in the EXPLAIN warning,
472# because it doesn't actually reference neighbour tables of the same
473# FROM clause.
474
475# Note that by adding LATERAL where it was not, we change a bit the
476# meaning of the query, fortunately name resolution in execution of a
477# prepared stmt uses cached_table. If it didn't, the last column would
478# contain 42 instead of 1 or 2, if in a prepared stmt.
479
480let $query=
481select * from t1, lateral (select * from (select 42) t1, (select t1.a) dt2) dt3;
482eval explain $query;
483eval $query;
484
485--echo without semijoin: index_subquery needs to re-materialize
486
487# Justifies clear_corr_derived_tmp_tables in subselect_indexsubquery_engine::exec
488
489let $query=
490select a from t1 where a in (select /*+ no_semijoin() */ a from (select t1.a) dt);
491eval explain $query;
492eval $query;
493
494# Justifies clear_corr_ctes in subselect_indexsubquery_engine::exec
495
496select a from t1 where a in (with cte as (select t1.a)
497                             select /*+ no_semijoin() */ a from cte);
498
499--echo # Count rematerializations
500
501--echo # In all three plans, handler_write is 2, showing that we
502--echo # rematerialize only when necessary (when row of t1 changes)
503let $query=
504select straight_join * from t1, t2, lateral (select t1.a) as dt;
505eval explain $query;
506flush status;
507eval $query;
508--echo # when a row of t1 produces two rows of t2 passed to "dt",
509--echo # it still makes one materialization.
510show status like "handler_write";
511
512let $query=
513select straight_join * from t1, lateral (select t1.a) as dt, t2;
514eval explain $query;
515flush status;
516--sorted_result
517eval $query;
518show status like "handler_write";
519
520let $query=
521select straight_join * from t2, t1, lateral (select t1.a) as dt;
522eval explain $query;
523flush status;
524--sorted_result
525eval $query;
526--echo # Due to join buffer, order t2-t1 produces rows as a
527--echo # non-buffered t1-t2 plan: t1 buffers all rows of t2, then for
528--echo # each row of t1 it's joined to all rows of t2 and passed to t2;
529--echo # when a row of t1 produces two rows of t2 passed to "dt",
530--echo # it still makes one materialization.
531show status like "handler_write";
532
533--echo # Let the planner find the best plan.
534--echo # It doesn't work so well, because of
535--echo # optimizer_prune_level=1 (see bug#28629788): order specified by
536--echo # the user is sorted by number of rows, which leaves it
537--echo # unchanged (Card(t1)=Card(t2)=Card(dt)); then it is the first
538--echo # explored plan so it's explored in full, and later t1-dt is rejected as
539--echo # more expensive than t1-t2. Whereas if t1-dt had been explored
540--echo # deeper, we'd see t1-dt-t2 is actually the cheapest, because
541--echo # it reads dt the least number of times (and dt has a high read
542--echo # cost because Temptable::scan_time() is incredibly high but
543--echo # that's another issue; see bug#28631100).
544--echo # t2 cannot use join buffering as between "dt" and its
545--echo # dependency t1: join buffering would interlace rows of t1
546--echo # thus cause more rematerializations.
547
548let $query=
549select * from t1, t2, lateral (select t1.a) as dt;
550eval explain $query;
551flush status;
552eval $query;
553show status like "handler_write";
554
555--echo # This one finds the best plan. Yes we simply swapped tables in the query,
556--echo # and it yields a different plan. This is because the order specified by
557--echo # the user is sorted by number of rows, which leaves it
558--echo # unchanged (Card(t1)=Card(t2)=Card(dt), then it is the first
559--echo # explored plan so it's explored in full and so is never pruned by
560--echo # prune_level=1, and it is the best plan. Best as: it reads
561--echo # "dt" less, and t2 uses join buffering (which is ok as it's
562--echo # after "dt").
563--echo # If prune_level=0, all 3 variants here produce this plan.
564let $query=
565select * from t1, lateral (select t1.a) as dt, t2;
566eval explain $query;
567flush status;
568--sorted_result
569eval $query;
570show status like "handler_write";
571
572--echo # This one is intermediate: t1 uses join buffer (good), but
573--echo # "dt" is last (bad, as it has high scan cost).
574
575let $query=
576select * from t2, t1, lateral (select t1.a) as dt;
577eval explain $query;
578flush status;
579--sorted_result
580eval $query;
581show status like "handler_write";
582
583--echo # Show the trace of planning of lateral derived tables
584let $query=
585select * from t1, lateral (select t1.a from t2 as t3, t2 as t4) as dt, t2;
586eval explain $query;
587select trace from information_schema.optimizer_trace;
588
589--echo # LDT depending on const table only
590
591create table t3(a int) engine=innodb;
592insert into t3 values(3);
593analyze table t3;
594let $query=
595select * from t3, lateral (select t3.a+1) as dt;
596eval explain $query;
597eval $query;
598drop table t3;
599
600
601--echo # Two LDTs depending on different tables
602let $query=
603select * from t2, t1, lateral (select t1.a) as dt,
604                      lateral (select t2.a) as dt2;
605eval explain $query;
606eval $query;
607
608--echo # Two LDTs depending on one same table
609
610let $query=
611select * from t2, t1, lateral (select t1.a) as dt,
612                      lateral (select t1.a+1) as dt2;
613eval explain $query;
614eval explain format=json $query;
615--sorted_result
616eval $query;
617
618--echo # One LDT depending on two tables. The "rematerialize" tag is
619--echo # properly added to the 2nd dependency only.
620
621let $query=
622select * from t2, t1, lateral (select t1.a+t2.a) as dt;
623eval explain $query;
624eval explain format=json $query;
625eval $query;
626eval $show_trace;
627
628--echo # Test when a dependency of LDT uses BKA: BKA code must
629--echo # refresh LDT's content when it provides a row.
630set @old_opt_switch=@@optimizer_switch;
631set @@optimizer_switch="batched_key_access=on,mrr_cost_based=off";
632CREATE TABLE t11 (t11a int, t11b int);
633INSERT INTO t11 VALUES (99, NULL),(99, 3),(99,0);
634CREATE TABLE t12 (t12a int, t12b int, KEY idx (t12b));
635INSERT INTO t12 VALUES (100,0),(150,200),(999, 0),(999, NULL);
636ANALYZE TABLE t11,t12;
637let $query=
638SELECT * FROM t11 LEFT JOIN t12 force index (idx) ON t12.t12b = t11.t11b
639JOIN LATERAL (SELECT t12a) dt;
640eval explain $query;
641flush status;
642eval $query;
643show status like "handler_write";
644DROP TABLE t11,t12;
645set @@optimizer_switch=@old_opt_switch;
646
647--echo # Test that with an auto_key on the lateral DT, the index is
648--echo # properly emptied and re-filled when re-materializing.
649--echo # If index weren't emptied, we'd see too many "11" matches for 2nd
650--echo # row of t1; and if not re-filled, we'd see no matches for that.
651
652create table t3 (a int, b int);
653insert into t3 values(1, 10), (1, 11), (2, 10), (2, 11);
654analyze table t3;
655let $query=
656select * from t1, lateral (select t3.b from t3 where t3.a=t1.a) dt
657 where dt.b=t1.a+9;
658--echo # Note the auto_key with "Using index", to test the index as
659--echo # much as possible.
660eval explain $query;
661eval $query;
662drop table t3;
663
664set optimizer_switch='derived_merge=off';
665
666}
667
668--echo # Reserved word
669--error ER_PARSE_ERROR
670create table lateral(a int);
671
672drop table t1,t2;
673
674--echo #
675--echo # Bug#28723670 RECENT REGRESSION: CRASH/ASSERTION IN FIND_FIELD_IN_TABLE_REF
676--echo #
677
678CREATE TABLE t(x INT);
679--echo # Don't search for 'y' in top SELECT
680--error ER_BAD_FIELD_ERROR
681SELECT 1 FROM
682  (SELECT 1 FROM (SELECT (SELECT y FROM t) FROM t) AS a) AS b;
683DROP TABLE t;
684
685--echo #
686--echo # Bug#28976533 ASSERTION `JOIN->BEST_READ < DOUBLE(1.79769313486231570814527423731704357E+308L)
687--echo #
688
689CREATE TABLE bb (
690pk INTEGER AUTO_INCREMENT,
691col_int INTEGER ,
692col_int_key INTEGER ,
693col_time_key TIME ,
694col_time TIME ,
695col_datetime_key DATETIME ,
696col_datetime DATETIME ,
697col_varchar_key VARCHAR(20) ,
698col_varchar VARCHAR(20) ,
699PRIMARY KEY (pk DESC),
700KEY (col_time_key),
701KEY (col_time_key DESC)
702);
703
704SET SQL_MODE='';
705let $query=
706SELECT
707grandparent1.col_varchar_key AS g1 FROM bb AS grandparent1
708LEFT JOIN bb AS grandparent2 USING ( col_time )
709WHERE grandparent1.col_int_key IN
710(
711  WITH qn AS (
712               SELECT  parent1.col_int AS p1
713               FROM bb AS parent1 LEFT JOIN bb AS parent2 USING ( col_varchar )
714               WHERE parent1.col_varchar_key IN
715               (
716                 WITH qn1 AS (
717                               SELECT DISTINCT child1.col_varchar_key AS C1
718                               FROM bb AS child1 LEFT JOIN bb AS child2
719                               ON child1.col_varchar_key <= child2.col_varchar
720                               WHERE child1.col_time > grandparent1.col_datetime
721                             )
722                 SELECT  * FROM qn1
723               )
724               AND parent1.col_time_key BETWEEN '2008-03-18' AND
725               '2004-11-14'
726             )
727  SELECT /*+ MERGE(qn) */ * FROM qn
728)
729GROUP BY grandparent1.col_int;
730
731eval EXPLAIN $query;
732eval $query;
733
734DROP TABLE bb;
735SET SQL_MODE=DEFAULT;
736
737--echo #
738--echo # Bug #29268512: ASSERTION FAILED: INITED == NONE INTERMITTENTLY
739--echo #
740
741CREATE TABLE t1 (
742  f1 integer
743);
744
745INSERT INTO t1 VALUES (0),(1);
746
747CREATE TABLE t2 (
748  f2 integer
749);
750
751SELECT * FROM t1, LATERAL ( SELECT MAX(1) FROM t2 GROUP BY t1.f1 ) AS l1;
752
753DROP TABLE t1, t2;
754
755--echo #
756--echo # Bug #29334082: Still crashing in actual_key_parts() / assert inited == INDEX
757--echo #
758
759CREATE TABLE t1 ( f1 INTEGER );
760CREATE TABLE t2 ( f2 LONGBLOB );
761
762INSERT INTO t1 VALUES (1);
763INSERT INTO t2 VALUES ('abc'),('def');
764
765# The longblob requires deduplication by means of a hidden hash field,
766# which triggers a special path in MaterializeIterator that involves an index.
767SELECT STD(0) FROM t2, LATERAL ( SELECT f1 FROM t1 GROUP BY f2,f1 ) AS d1;
768
769DROP TABLE t1, t2;
770
771--echo #
772--echo # Bug#28954838 ASSERTION `(REMAINING_TABLES_AFTER != 0) || ((CUR_EMBEDDING_MAP == 0) && (JOIN->
773--echo #
774
775CREATE TABLE t1 (
776 pk INTEGER,
777 col_int INT not null,
778 col_int_key INT not null,
779 col_time_gckey TIME,
780 col_varchar VARCHAR(20) not null,
781 col_varchar_key VARCHAR(15)  not null
782);
783
784CREATE TABLE t2 (
785 pk INTEGER,
786 col_int INT not null,
787 col_varchar VARCHAR(20) not null,
788 col_varchar_key VARCHAR(15) not null
789);
790
791SET OPTIMIZER_SWITCH='derived_merge=off';
792
793SELECT table1.col_varchar_key AS field1,
794       table2.col_time_gckey AS field2
795FROM t2 AS table1 STRAIGHT_JOIN t1 AS table2
796     ON table2.col_varchar_key = table1.col_varchar_key
797WHERE table2.col_int_key IN
798   (WITH qn AS
799    (SELECT sq1_t1.col_int AS sq1_field1
800     FROM t2 AS sq1_t1
801     WHERE sq1_t1.col_varchar_key = table2.col_varchar OR
802           EXISTS (WITH qn1 AS
803                   (SELECT c_sq1_t1.col_int_key AS c_sq1_field1
804                    FROM t1 AS c_sq1_t1
805                    WHERE c_sq1_t1.col_varchar_key > sq1_t1.col_varchar OR
806                          c_sq1_t1.col_int <> c_sq1_t1.pk
807                   )
808                   SELECT * FROM qn1
809                  )
810    )
811    SELECT * FROM qn
812   ) AND
813   EXISTS (WITH qn AS
814           (SELECT sq2_t1.col_varchar AS sq2_field1
815            FROM t1 AS sq2_t1 STRAIGHT_JOIN
816                   t2 AS sq2_t2 INNER JOIN t1 AS sq2_t3
817                   ON sq2_t3.col_varchar = sq2_t2.col_varchar_key
818                 ON sq2_t3.col_int = sq2_t2.pk
819           )
820           SELECT * FROM qn
821          ) AND
822      table2.col_varchar_key <> 'j';
823
824SET OPTIMIZER_SWITCH=DEFAULT;
825DROP TABLE t1,t2;
826
827--echo #
828--echo # Bug#28955358 VIRTUAL LONGLONG FIELD_NEWDATE::VAL_DATE_TEMPORAL(): ASSERTION `!TABLE || (!TAB
829--echo #
830
831CREATE TABLE t1 (
832pk INTEGER, col_int_key INTEGER NOT NULL,
833col_date_key DATE NOT NULL, col_datetime DATETIME NOT NULL
834);
835
836INSERT INTO t1 VALUES (0, 0, '2006-07-18', '2001-09-06 02:13:59.021506');
837
838# outer reference inside derived table 'qn'
839
840SELECT /*+ no_merge() */  outr.pk AS x
841FROM ( SELECT * FROM  t1  ) AS  outr
842WHERE outr.col_int_key  IN
843( SELECT /*+ no_merge() no_semijoin() */ 2
844  FROM (SELECT 1 AS x FROM t1 AS  innr WHERE outr.col_date_key ) AS
845  qn )
846ORDER BY outr.col_datetime;
847
848# outer reference inside JSON_TABLE
849
850SELECT /*+ no_merge() */  outr.pk AS x
851FROM ( SELECT * FROM  t1  ) AS  outr
852WHERE outr.col_int_key  IN
853( SELECT /*+ no_merge() no_semijoin() */ id
854  FROM JSON_TABLE( IF(outr.col_date_key<>NOW(),
855                      '[{"a":"3"},{"a":2},{"b":1},{"a":0}]',
856                      '') ,
857                   '$[*]' columns (id for ordinality,
858                                   jpath varchar(100) path '$.a',
859                                   jexst int exists path '$.b')   ) AS
860                                   qn )
861ORDER BY outr.col_datetime;
862
863DROP TABLE t1;
864
865# This bug was also wrongly accepting a bad GROUP BY query
866# without functional dependency:
867
868CREATE TABLE t1(pk INT PRIMARY KEY, a INT);
869--error ER_WRONG_FIELD_WITH_GROUP
870EXPLAIN SELECT pk FROM t1 GROUP BY a;
871--error ER_WRONG_FIELD_WITH_GROUP
872EXPLAIN SELECT (SELECT pk FROM (SELECT t1.pk) dt) FROM t1 GROUP BY a;
873DROP TABLE t1;
874
875--echo #
876--echo # Bug#28960857 ASSERTION FAILED: !TR->DERIVED_WHERE_COND || TR->DERIVED_WHERE_COND->FIXED
877--echo # Bug#28960789 ASSERTION FAILED: TRANSL->ITEM->FIXED,
878--echo #
879
880CREATE TABLE t0007 (
881  c0008 date NOT NULL,
882  c0009 char(234) NOT NULL
883);
884
885CREATE TABLE t0008 (
886  c0005 tinytext NOT NULL
887);
888
889CREATE TABLE t0009 (
890  c0000 time NOT NULL
891);
892
893SET SQL_MODE=0;
894
895SELECT (SELECT t0007.c0009         FROM (SELECT t0007.c0008 AS c0003
896     FROM t0009                   ) AS t0005                 ) FROM t0007
897GROUP BY -23;
898
899SELECT (SELECT c0009
900        FROM (SELECT 1 AS c0003
901              FROM t0009 INNER JOIN t0008
902                   ON t0008.c0005
903              WHERE t0007.c0008
904             ) AS t0005
905        GROUP BY c0008
906       ),
907       COUNT(c0009)
908FROM t0007
909GROUP BY 1, 1;
910
911DROP TABLE t0007, t0008, t0009;
912SET SQL_MODE=DEFAULT;
913
914--echo #
915--echo # Bug #29514504: WRONG RESULT WITH CORRELATED LATERAL JOIN
916--echo #
917
918#
919# In this case, the derived table has an aggregation function that can get zero
920# input rows, _and_ is evaluated multiple times (due to LATERAL). If so,
921# we have to be careful to properly reset the value we write to the derived
922# table, or the value from the previous iteration would leak through.
923#
924CREATE TABLE t1 (id INTEGER);
925CREATE TABLE t2 (id INTEGER);
926INSERT INTO t1 VALUES (10), (20), (30);
927INSERT INTO t2 VALUES (20), (20);
928SELECT * FROM t1 JOIN LATERAL (
929  SELECT GROUP_CONCAT(t.id) AS c FROM t2 t WHERE (t.id = t1.id)
930) d0 ON (1);
931
932DROP TABLE t1, t2;
933
934--echo #
935--echo # Bug #30110851: SUBQUERY INVOLVES COUNT() AGGREGATE FUNCTION PERFORMANCE REGRESSION
936--echo #
937
938CREATE TABLE t1 ( f1 INTEGER NOT NULL, f2 INTEGER NOT NULL );
939CREATE TABLE t2 ( f1 INTEGER NOT NULL, f2 INTEGER NOT NULL );
940CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1;
941CREATE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT ( SELECT f2 FROM v1 WHERE v1.f1 = t2.f1 ) AS f3 FROM t2;
942
943#
944# Both materializations here should be marked as non-rematerialize
945# (ie., not “Temporary table”). In particular, the materialization
946# in the SELECT clause should be reused for each iteration, even though
947# the index lookup against it is outer-correlated, and it is part of
948# a query block which is also itself outer-correlated.
949#
950EXPLAIN FORMAT=TREE SELECT * FROM v2 WHERE f3 = 3;
951
952DROP TABLE t1, t2;
953DROP VIEW v1, v2;
954
955--echo #
956--echo # Bug#30627575 ASSERT: `INITED == NONE' IN HANDLER::HA_INDEX_INIT() AT SQL/HANDLER.CC
957--echo #
958
959CREATE TABLE t1(
960a INT,
961b INT NOT NULL,
962c INT NOT NULL,
963d INT,
964UNIQUE KEY (c,b)
965);
966INSERT INTO t1 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4);
967CREATE TABLE t2(
968a INT,
969b INT,
970UNIQUE KEY(a,b)
971);
972INSERT INTO t2 VALUES (NULL, NULL), (NULL, NULL), (NULL, 1), (1, NULL), (1, 1), (1,2);
973ANALYZE TABLE t1,t2;
974
975# Should show "using index for group-by"
976EXPLAIN SELECT * FROM t1 JOIN LATERAL (SELECT a+t1.a from t2 GROUP BY a) AS dt;
977
978SELECT * FROM t1 JOIN LATERAL (SELECT a+t1.a from t2 GROUP BY a) AS dt;
979
980DROP TABLE t1, t2;
981