1--source include/have_optimizer_trace.inc
2
3let $DEFAULT_TRACE_MEM_SIZE=1048576; # 1MB
4eval set optimizer_trace_max_mem_size=$DEFAULT_TRACE_MEM_SIZE;
5
6set end_markers_in_json=on;
7set optimizer_trace="enabled=on";
8
9SET @old_sql_mode = @@sql_mode;
10SET @@sql_mode='ONLY_FULL_GROUP_BY';
11
12--echo #
13--echo # Bug#16021396 ONLY_FULL_GROUP_BY REJECTS VALID QUERY USING VIEW
14--echo #
15create table t1(a int, b int, c int) engine=InnoDB;
16let $count=2;
17while($count)
18{
19if ($count == 2)
20{
21let $viewtype=merge;
22}
23if ($count == 1)
24{
25let $viewtype=temptable;
26}
27dec $count;
28eval create algorithm=$viewtype view v1 as select t1.a*2 as a, t1.b*2 as b, t1.c*2 as c from t1;
29show create view v1;
30select sin(b) as z from t1 group by sin(b);
31select sin(b) as z from v1 group by sin(b);
32select sin(b) as z from t1 group by b;
33select sin(b) as z from v1 group by b;
34select sin(b) as z from v1 group by z;
35drop view v1;
36}
37drop table t1;
38
39--echo # From testcase of Bug#16903135:
40
41CREATE TABLE group_by_test2 (
42 id int unsigned primary key,
43 cat int unsigned not null,
44 name varchar(10),
45 num int unsigned
46);
47
48INSERT INTO group_by_test2 (id,cat,name,num) VALUES
49(1,10,'foo',2),
50(2,11,'foo',1),
51(3,22,'bar',3),
52(4,23,'bar',7),
53(5,34,'test',7);
54
55let $query=
56SELECT
57 cat,
58 name,
59 SUM(num)
60FROM
61 group_by_test2
62GROUP BY
63 cat;
64
65--error ER_WRONG_FIELD_WITH_GROUP
66eval $query;
67
68ALTER TABLE group_by_test2 ADD UNIQUE INDEX (cat);
69eval $query;
70--error ER_WRONG_FIELD_WITH_GROUP
71eval $query WITH ROLLUP;
72--echo # Expressions of group columns are ok:
73SELECT
74 cat,
75length(cat),
76 SUM(num)
77FROM
78 group_by_test2
79GROUP BY
80 cat
81WITH ROLLUP;
82
83DROP TABLE group_by_test2;
84
85--echo # Test from Bug #18993257 SELECT AGGR + NON-AGGR FROM JOIN WITH VIEW IS NOT REJECTED BY ONLY_FULL_GROUP_BY
86
87CREATE TABLE t1 (
88  col_int_key INT,
89  col_varchar_key VARCHAR(1)
90);
91
92CREATE TABLE t2 (
93    pk INTEGER,
94    col_int_key INTEGER
95);
96
97CREATE VIEW view_b AS SELECT * FROM t2;
98
99--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
100SELECT MIN( alias2.col_int_key ),
101       alias2.col_int_key
102FROM t1 AS alias1, t2 AS alias2
103WHERE alias1.col_int_key IS NULL;
104
105--echo # Same with view:
106--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
107SELECT MIN( alias2.col_int_key ),
108       alias2.col_int_key
109FROM t1 AS alias1, view_b AS alias2
110WHERE alias1.col_int_key IS NULL;
111
112DROP TABLE t1, t2;
113DROP VIEW view_b;
114
115--echo #
116--echo # WL#2489; Recognizing some functional dependencies
117--echo #
118
119--source include/show_json_object.inc
120let $show_trace=
121SELECT show_json_object('"functional_dependencies_of_GROUP_columns": {', TRACE)
122FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
123
124create table t1(
125a int,
126b int not null,
127c int not null,
128d int,
129unique key(b,c),
130unique key(b,d)
131);
132
133--error ER_WRONG_FIELD_WITH_GROUP
134select sin(a) as z from t1 group by b;
135--error ER_WRONG_FIELD_WITH_GROUP
136select sin(a) as z from t1 group by d,b;
137
138--echo # {b,c} UNIQUE NOT NULL => {c,b}->a
139select sin(a) as z from t1 group by c,b;
140select sin(a+b*c) as z from t1 group by c,b;
141--echo # In PS mode, we see nothing below, because only_full_group_by
142--echo # checks are done at PREPARE, whereas trace below is from EXECUTE.
143eval $show_trace;
144
145--echo # With outer references:
146--error ER_WRONG_FIELD_WITH_GROUP
147select (select sin(a)) as z from t1 group by d,b;
148select (select sin(a)) as z from t1 group by c,b;
149--echo # If key columns are in function, functional dependency disappears
150--error ER_WRONG_FIELD_WITH_GROUP
151select sin(a) as z from t1 group by c*2,b*2;
152
153--echo # FDs are recognized, like in SQL standard:
154--echo # b=2 => c->{b,c} => c->a as (b,c) is unique not null.
155select sin(a) as z from t1 where b=2 group by c;
156eval $show_trace;
157
158--echo # t2.a=t1.a => {t1.b,t1.c}->t2.a
159select sin(t2.a) as z from t1, t1 as t2
160 where t2.a=t1.a group by t1.b,t1.c;
161eval $show_trace;
162
163--echo # t2.b=t1.b and t2.c=t1.c => {t1.b,t1.c}->{all cols of t2}
164select sin(t2.a) as z from t1, t1 as t2
165 where t2.b=t1.b and t2.c=t1.c group by t1.b,t1.c;
166eval $show_trace;
167
168--echo # t2.b=t1.b and t2.c=t1.c => {t1.b,t1.c}->{all cols of t2}
169--echo # Moreover, {t1.b,t1.c}->{t1.d}.
170--echo # So t3.b=t2.b and t3.c=t1.d => {t1.b,t1.c}->{all cols of t3}.
171select t3.a from t1, t1 as t2, t1 as t3
172where
173 t3.b=t2.b and t3.c=t1.d and
174 t2.b=t1.b and t2.c=t1.c
175group by t1.b,t1.c;
176eval $show_trace;
177
178--echo # 3 tables:
179--echo # {t1.b,t1.c}->{t1.*}->{t2.b,t2.c}->{t2.*}->{t3.pk}->{t3.b}
180create table t3(pk int primary key, b int);
181select t3.b from  t1,t1 as t2,t3
182  where t3.pk=t2.d and t2.b=t1.b and t2.c=t1.a
183  group by t1.b,t1.c;
184drop table t3;
185
186--echo # With subq
187select (select t1.b from t1
188  where t2.b=t1.b
189  group by t1.a) from t1 as t2;
190
191--echo # Outer join.
192create table t2 like t1;
193delete from t1;
194insert into t1 (a,b) values(1,10),(2,20);
195insert into t2 (a,b) values(1,-10);
196--echo # In result, t2.a is NULL for both rows, values of t1.a are 1 and 2
197select t1.a,t2.a from t1 left join t2 on t2.a=t1.a and t2.b=t1.b;
198--echo # So this query would choose one arbitrary value of t1.a - wrong:
199--error ER_WRONG_FIELD_WITH_GROUP
200select t1.a from t1 left join t2 on t2.a=t1.a and t2.b=t1.b group by t2.a;
201
202--echo # Also problem for FD with constant:
203select t1.a,t2.a from t1 left join t2 on 42=t1.a and t2.b=t1.b;
204--error ER_WRONG_FIELD_WITH_GROUP
205select t1.a from t1 left join t2 on 42=t1.a and t2.b=t1.b group by t2.a;
206
207--error ER_WRONG_FIELD_WITH_GROUP
208select t1.a from t1 left join t2 on t2.b=t1.a group by t2.b;
209--error ER_WRONG_FIELD_WITH_GROUP
210select t1.a from t1 left join t2 on 42=t1.a group by t2.a;
211
212--error ER_WRONG_FIELD_WITH_GROUP
213select t1.c from t1 left join t2 on t1.a=t1.c group by t1.a;
214--error ER_WRONG_FIELD_WITH_GROUP
215select t1.b from t1 left join t2 on t1.c=t1.b and t1.a=t1.c group by t1.a;
216select t1.a,t2.c from t1 left join t2 on t1.a=t2.c
217and cos(t2.c+t2.b)>0.5 and sin(t1.a+t2.d)<0.9 group by t1.a;
218
219--echo # with keys:
220select t1.a,t2.d from t1 left join t2 on t1.a=t2.c and t1.d=t2.b
221and cos(t2.c+t2.b)>0.5 and sin(t1.a+t2.d)<0.9 group by t1.a,t1.d;
222
223--echo # with non-determinism:
224--error ER_WRONG_FIELD_WITH_GROUP
225select t1.a,t2.c from t1 left join t2 on t1.a=t2.c
226and cos(t2.c+rand())>0.5 group by t1.a;
227select t1.a, ANY_VALUE(t2.c) from t1 left join t2 on t1.a=t2.c
228and cos(t2.c+rand())>0.5 group by t1.a;
229
230--echo # with parameter:
231prepare s from 'select t1.a,t2.c from t1 left join t2 on t1.a=t2.c
232and cos(t2.c+ ? )>0.5 group by t1.a';
233execute s using @dummy;
234
235--echo # No OR
236--error ER_WRONG_FIELD_WITH_GROUP
237select t1.a,t2.c from t1 left join t2 on t1.a=t2.c
238and cos(t2.c+t2.b)>0.5 OR sin(t2.d)<0.9 group by t1.a;
239
240--echo # With subq
241--error ER_WRONG_FIELD_WITH_GROUP
242select t2.b from t1 left join t1 as t2 on t1.a=t2.b and t1.b group by t1.a;
243--error ER_WRONG_FIELD_WITH_GROUP
244select t2.b from t1 left join t1 as t2 on t1.a=t2.b and (select t1.b) group by t1.a;
245
246--echo # Test ANY_VALUE:
247select ANY_VALUE(t1.b) from t1 left join t2 on t1.c=t1.b and t1.a=t1.c group by t1.a;
248--error ER_WRONG_FIELD_WITH_GROUP
249select 3+(5*t1.b) from t1 left join t2 on t1.c=t1.b and t1.a=t1.c group by t1.a;
250select 3+(5*ANY_VALUE(t1.b)) from t1 left join t2 on t1.c=t1.b and t1.a=t1.c group by t1.a;
251delete from t1;
252insert into t1 (a,b) values(1,10),(1,20),(2,30),(2,40);
253--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
254select a, sum(b) from t1;
255select any_value(a), sum(b) from t1;
256--echo # different order of input rows, different "any_value":
257select any_value(a), sum(b) from (select * from t1 order by a desc) as d;
258--error ER_WRONG_FIELD_WITH_GROUP
259select a,b,sum(c) from t1 group by a;
260select a,any_value(b),sum(c) from t1 group by a;
261select a,any_value(b),sum(c)
262from (select * from t1 order by a desc, b desc) as d
263group by a;
264
265--echo # With view.
266
267let $count=3;
268while($count)
269{
270set @optimizer_switch_saved=@@optimizer_switch;
271let $source_query=select t1.a*2 as a, t1.b as b, t1.c as c, t1.d as d, t1.a as e from t1;
272if ($count == 3)
273{
274--echo # Merged view
275eval create algorithm=merge view v1 as $source_query;
276show create view v1;
277let $source=v1;
278let $source_no_alias=v1;
279}
280if ($count == 2)
281{
282--echo # Materialized view
283eval create algorithm=temptable view v1 as $source_query;
284show create view v1;
285let $source=v1;
286let $source_no_alias=v1;
287}
288if ($count == 1)
289{
290--echo # Materialized derived table
291set optimizer_switch='derived_merge=off';
292let $source=($source_query) as v1;
293let $source_no_alias=($source_query);
294}
295
296--error ER_WRONG_FIELD_WITH_GROUP
297eval select sin(a) as z from $source group by b;
298--error ER_WRONG_FIELD_WITH_GROUP
299eval select sin(a) as z from $source group by d,b;
300eval select sin(a) as z from $source group by c,b;
301--error ER_WRONG_FIELD_WITH_GROUP
302eval select (select sin(a)) as z from $source group by d,b;
303eval select (select sin(a)) as z from $source group by c,b;
304--error ER_WRONG_FIELD_WITH_GROUP
305eval select sin(a) as z from t1 group by c*2,b*2;
306eval select sin(a+b*c) as z from $source group by c,b;
307eval $show_trace;
308
309eval select sin(a) as z from $source where b=2 group by c;
310
311--echo # {v1.b,v1.c}->v1.a->t2.a
312eval select sin(t2.a) as z from $source, $source_no_alias as t2
313 where t2.a=v1.a group by v1.b,v1.c;
314eval $show_trace;
315
316eval select sin(t2.a) as z from $source, $source_no_alias as t2
317 where t2.b=v1.b and t2.c=v1.c group by v1.b,v1.c;
318
319--echo # With materialized view we get more dependencies than needed, due to implementation.
320eval select t3.a from $source, $source_no_alias as t2, $source_no_alias as t3
321where
322 t3.b=t2.b and t3.c=v1.d and
323 t2.b=v1.b and t2.c=v1.c
324group by v1.b,v1.c;
325eval $show_trace;
326
327--echo # If we simply went to real_item(), we would have WHERE 2*a=b, or
328--echo # GROUP BY 2*t1.a, so we would not find FDs. The original item
329--echo # (direct_view_ref here) must also be considered!
330eval select a from $source where a=b group by b;
331eval $show_trace;
332eval select b from $source where a=b group by a;
333eval $show_trace;
334
335eval select v1.c from $source where v1.c=v1.a group by v1.a;
336eval $show_trace;
337eval select v1.a from $source group by v1.e;
338eval $show_trace;
339eval select v1.c from $source where v1.c=v1.a group by v1.e;
340eval $show_trace;
341--echo # View appears only in WHERE
342eval select t2.d from $source, t1 as t2 where v1.a=t2.d and v1.e=t2.a group by t2.a;
343eval $show_trace;
344
345drop view if exists v1;
346
347--echo # FD due to view's WHERE:
348
349let $source_query=select t1.a*2 as a, t1.b as b from t1;
350if ($count == 3)
351{
352eval create algorithm=merge view v1 as $source_query;
353}
354if ($count == 2)
355{
356eval create algorithm=temptable view v1 as $source_query;
357}
358if ($count == 1)
359{
360let $source=($source_query) as v1;
361let $source_no_alias=($source_query);
362}
363
364--error ER_WRONG_FIELD_WITH_GROUP
365eval select a from $source group by b;
366drop view if exists v1;
367
368let $source_query=select t1.a*2 as a, t1.b as b from t1 where t1.a=t1.b;
369if ($count == 3)
370{
371--echo # Merged view
372eval create algorithm=merge view v1 as $source_query;
373}
374if ($count == 2)
375{
376--echo # Materialized view
377eval create algorithm=temptable view v1 as $source_query;
378}
379if ($count == 1)
380{
381--echo # Derived table
382let $source=($source_query) as v1;
383let $source_no_alias=($source_query);
384}
385eval select a from $source group by b;
386eval $show_trace;
387
388drop view if exists v1;
389
390--echo # Aggregates in view
391
392let $source_query=select sum(t1.a) as a, sum(t1.b) as b from t1;
393if ($count == 3)
394{
395--echo # Aggregates => skipping Merged view
396}
397if ($count == 2)
398{
399--echo # Materialized view
400eval create algorithm=temptable view v1 as $source_query;
401}
402if ($count == 1)
403{
404--echo # Derived table
405let $source=($source_query) as v1;
406let $source_no_alias=($source_query);
407}
408if ($count <= 2)
409{
410eval select a from $source group by b;
411eval $show_trace;
412}
413
414drop view if exists v1;
415
416--echo # Aggregates + GROUP BY in view
417
418--echo # We group by b*5, to show that it works with GROUP expressions, not only fields.
419let $source_query=select a, b*5 as b, sum(t1.c) as c, sum(t1.d) as d from t1 group by a,b*5;
420if ($count == 3)
421{
422--echo # Aggregates => skipping Merged view
423}
424if ($count == 2)
425{
426--echo # Materialized view
427eval create algorithm=temptable view v1 as $source_query;
428}
429if ($count == 1)
430{
431--echo # Derived table
432let $source=($source_query) as v1;
433let $source_no_alias=($source_query);
434}
435if ($count <= 2)
436{
437--error ER_WRONG_FIELD_WITH_GROUP
438eval select a from $source group by b;
439--error ER_WRONG_FIELD_WITH_GROUP
440eval select c from $source group by b;
441--error ER_WRONG_FIELD_WITH_GROUP
442eval select c from $source group by b,d;
443--error ER_WRONG_FIELD_WITH_GROUP
444eval select a,c from $source group by a;
445eval select d,c from $source group by b,a;
446eval $show_trace;
447}
448
449drop view if exists v1;
450
451dec $count;
452set optimizer_switch=@optimizer_switch_saved;
453}
454
455--echo # Derived table in merged view
456create algorithm=temptable view v2
457as select a as a, 2*a as b from t1;
458create algorithm=merge view v1
459 as select v2.a as a, 3*v2.b as b from v2;
460select v1.b from v1 group by v1.a;
461eval $show_trace;
462
463select t2.a from t1 as t2, v1 where t2.a=v1.b group by v1.a;
464eval $show_trace;
465
466--echo # FDs in a view are those of the underlying query expression.
467--echo # FDs in a query expression: expressions in the SELECT list must be
468--echo # deterministic.
469drop view v1;
470create algorithm=merge view v1
471 as select v2.a as a, rand()*v2.b as b from v2;
472--error ER_WRONG_FIELD_WITH_GROUP
473select v1.b from v1 group by v1.a;
474drop view v1;
475create algorithm=temptable view v1
476 as select v2.a as a, rand()*v2.b as b from v2;
477--error ER_WRONG_FIELD_WITH_GROUP
478select v1.b from v1 group by v1.a;
479
480drop view v1,v2;
481
482--echo # Item_direct_view_ref pointing to Item_direct_view_ref pointing to
483--echo # Item_field (a rare case!)
484create algorithm=merge view v2 as select 2*a as a, 2*b as b from t1;
485create algorithm=merge view v1 as select a, 3*b as b from v2 where a=b;
486select 1 from (select a,b+0 from v1 group by a) as d;
487drop view v1,v2;
488
489--echo # Some fun cases with aggregates in derived table.
490
491--echo # Inner query is valid: t1.a -> t1.b (equality in WHERE). Outer query:
492--echo # d.b -> t1.b (underlying column of d.b) -> t1.a (equality)
493--echo # -> sum(1) (because t1.a is all group columns so determines
494--echo # sum()) -> d.s (because sum() is underlying of d.s)
495select d.s from
496 (select b, sum(1) as s from t1 where a=b group by a) as d
497group by d.b;
498
499alter table t1 add column pk int primary key auto_increment;
500--echo # Inner query: t1.pk -> t1.* (pk). Outer query:
501--echo # d.b,d.c -> t1.b,t1.c (their underlying columns) -> t1.pk (because
502--echo # t1.b,t1.c is unique) -> sum(1) (because t1.pk is all group columns so
503--echo # determines sum()) -> d.s (because sum() is underlying of d.s)
504select d.s from
505 (select b, c, sum(d) as s from t1 group by pk) as d
506group by d.b,d.c;
507
508--echo # Outer query:
509--echo # d.c -> t1.b*3 (underlying column of d.c) -> sum(a) (because t1.b*3
510--echo # is all group expressions) -> d.s
511select d.s from
512 (select b*3 as c, sum(a) as s from t1 group by b*3) as d
513group by d.c;
514
515drop table t1,t2;
516
517
518--echo # Testcase from Reviewers
519
520create table customer1(pk int primary key, a int);
521create table customer2(pk int primary key, b int);
522CREATE algorithm=merge VIEW customer as SELECT pk,a,b
523FROM customer1 JOIN customer2 USING (pk);
524
525let $query=select customer.pk, customer.b
526from customer
527group by customer.pk;
528
529eval $query;
530--echo # View is merged. Show FDs. Note that in --ps-protocol, the trace
531--echo # is that of execution, so contains no group-by checks.
532eval $show_trace;
533
534drop view customer;
535CREATE algorithm=temptable VIEW customer as SELECT pk,a,b
536FROM customer1 JOIN customer2 USING (pk);
537eval $query;
538eval $show_trace;
539
540--echo # Benefit from outer-join-to-inner conversion.
541insert into customer1 values(0,10),(1,20);
542insert into customer2 values(0,10),(1,20);
543
544--echo # 1) no conversion, no FD from customer2.b to customer1.a.
545--error ER_WRONG_FIELD_WITH_GROUP
546explain select customer1.a, count(*)
547 from customer1 left join customer2 on customer1.a=customer2.b
548 where customer1.pk in (7,9)
549 group by customer2.b;
550
551--echo # 2) null-complemented row can't pass WHERE => conversion
552--echo # => FD from customer2.b to customer1.a.
553explain select customer1.a, count(*)
554 from customer1 left join customer2 on customer1.a=customer2.b
555 where customer2.pk in (7,9)
556 group by customer2.b;
557
558drop table customer1,customer2;
559drop view customer;
560
561--echo # FDs of JOIN...USING and NATURAL JOIN
562
563create table t1(pk int primary key, a int);
564create table t2(pk int primary key, b int);
565
566select t1.pk, t1.a from t1 join t2 on t1.pk=t2.pk group by t1.pk;
567select t1.pk, t1.a from t1 join t2 using(pk) group by t1.pk;
568select t1.pk, t1.a from t1 natural join t2 group by t1.pk;
569select t1.pk, t1.a from t1 left join t2 using(pk) group by t1.pk;
570select t1.pk, t1.a from t1 natural left join t2 group by t1.pk;
571
572select t1.pk, t2.b from t1 join t2 on t1.pk=t2.pk group by t1.pk;
573select t1.pk, t2.b from t1 join t2 using(pk) group by t1.pk;
574select t1.pk, t2.b from t1 natural join t2 group by t1.pk;
575select t1.pk, t2.b from t1 left join t2 using(pk) group by t1.pk;
576eval $show_trace;
577select t1.pk, t2.b from t1 natural left join t2 group by t1.pk;
578
579--echo # Equivalent queries, with RIGHT JOIN
580select t1.pk, t2.b from t2 right join t1 using(pk) group by t1.pk;
581select t1.pk, t2.b from t2 natural right join t1 group by t1.pk;
582
583--error ER_WRONG_FIELD_WITH_GROUP
584select t1.pk, t2.b from t1 left join t2 on t1.pk>t2.pk group by t1.pk;
585--echo # Even in --ps-protocol we see the group-by checks in trace because
586--echo # there has been no execution (due to error).
587eval $show_trace;
588
589--error ER_WRONG_FIELD_WITH_GROUP
590select t1.pk, t2.b from t2 right join t1 on t1.pk>t2.pk group by t1.pk;
591
592drop table t1,t2;
593
594--echo # Cases where FDs from weak side do not propagate
595
596create table t1(a int, b int);
597insert into t1 values(null,0),(null,1);
598
599let $query=
600select d.a,d.c
601from t1 left join (select a, coalesce(a,3) as c from t1) as d
602on t1.b>0;
603eval $query;
604--echo # Now group it by d.a:
605--error ER_WRONG_FIELD_WITH_GROUP
606eval $query group by d.a;
607eval $show_trace;
608
609let $query=
610select d.a,d.c
611from t1 left join (select a, count(a) as c from t1 group by a) as d
612on t1.b+d.c>0;
613eval $query;
614--echo # Now group it by d.a:
615--error ER_WRONG_FIELD_WITH_GROUP
616eval $query group by d.a;
617eval $show_trace;
618
619let $query=
620select d.m,d.c
621from t1 left join (select max(a) as m, count(a) as c from t1) as d
622on t1.b+d.c>0;
623eval $query;
624--echo # Now group it by d.m:
625--error ER_WRONG_FIELD_WITH_GROUP
626eval $query group by d.m;
627eval $show_trace;
628--echo # Now group it by d.c which is non-nullable:
629eval $query group by d.c;
630eval $show_trace;
631
632drop table t1;
633create table t1(pk int primary key, a int);
634
635--echo # Not valid per the standard, because:
636--echo # 1) In t3, t3.pk->t3.a holds.
637--echo # 2) In R1 the result of "(t2 left join t3 on 1)", t3.pk->t3.a
638--echo # holds, by application of: there is a functional dependency in the
639--echo # weak side t3, and t3.pk is not nullable in t3.
640--echo # 3) In R2 the result of "t1 left join (t2 left join t3 on 1) on 1",
641--echo # t3.pk->t3.a doesn't hold anymore, because: it's a dependency in the
642--echo # weak side (weak side is R1), and t3.pk is nullable _when
643--echo # seen as a column of R1_ (in R1 t3.pk can be NULL, if the row of t3
644--echo # is actually a null-complemented one).
645--echo # But for us it is valid, because we have refined the logic: the
646--echo # pk-based FD satisfies the requirement that a NULL value of t3.pk
647--echo # implies a NULL value of t3.a (indeed, the NULL value of t3.pk can
648--echo # only come from null-complementing of the row of t3 in R1, in which
649--echo # case t3.a is also NULL).
650select t3.a
651 from t1 left join (t1 as t2 left join t1 as t3 on 1) on 1
652 group by t3.pk;
653eval $show_trace;
654
655--echo # Outer reference - why we use resolved_used_tables():
656select (select t1.a from t1 as t2 limit 1) from t1 group by pk;
657
658--echo # We don't build the FD list if not needed
659select t1.a*3 from t1 group by t1.a;
660eval $show_trace;
661
662drop table t1;
663
664--echo # Tricky cases with "ON col=literal" propagating.
665create table t1(a int, b int);
666insert into t1 values();
667insert into t1 values(10,11);
668create table t2(c int, d int);
669insert into t2 values(2,3);
670
671let $query=
672select t4.d
673 from t1 left join (t2 as t3 join t2 as t4 on t4.d=3) on t1.a=10;
674eval $query;
675--echo # Equivalent to T1 LJ (T2, T3) ON T4.D=3 AND T1.A=10
676--echo # (this is what simplify_joins() does).
677--echo # For T4.D=3, DJS is {T1.A} which is not group column.
678--error ER_WRONG_FIELD_WITH_GROUP
679eval $query group by "";
680
681let $query=
682select t4.d
683 from t1 left join (t2 as t3 left join t2 as t4 on t4.d=3) on t1.a=10;
684eval $query;
685--echo # For T4.D=3, DJS={}, not NULL-friendly, and embedding is on weak side
686--echo # so FD cannot propagate.
687--error ER_WRONG_FIELD_WITH_GROUP
688eval $query group by "";
689
690let $query=
691select t4.d
692 from t1 join (t2 as t3 left join t2 as t4 on t4.d=3) on t1.a=10;
693eval $query;
694--echo # For T4.D=3, DJS={}, not NULL-friendly, but embedding is on weak side
695--echo # so FD can propagate.
696eval $query group by "";
697
698--echo # With a view
699
700create view v1 as select a as a, 2*a as b, coalesce(a,3) as c from t1;
701
702let $query=
703select v1.b from t1 left join v1 on 1;
704eval $query;
705--echo # If v1.a is NULL then v1.b is NULL: a->b is NULL-friendly
706eval $query group by v1.a;
707
708let $query=
709select v1.c from t1 left join v1 on 1;
710eval $query;
711--echo # If v1.a is NULL then v1.c may not be NULL: a->c is not NULL-friendly
712--error ER_WRONG_FIELD_WITH_GROUP
713eval $query group by v1.a;
714
715drop view v1;
716
717--echo # Constant view item
718create view v1 as select a as a, 2 as b from t1;
719let $query=
720select t1.a, v1.b from t1 left join v1 on t1.a is not null;
721--echo # Because of BUG#17023060, the result is wrong, should be
722--echo # [10,2 ; 10,2 ; NULL,NULL], which would show that {}->{v1.b} does not
723--echo # hold in the result, even though v1.b is constant (=2) in v1.
724eval $query;
725--echo # We correctly reject this:
726--error ER_WRONG_FIELD_WITH_GROUP
727eval $query group by v1.a;
728
729drop view v1;
730drop table t1,t2;
731
732create table emp(empno int, ename char(1), deptno int);
733create table dept(deptno int primary key, dname char(1));
734let $view_rest=
735VIEW empdept AS
736SELECT emp.empno, emp.ename, dept.deptno, dept.dname
737FROM emp LEFT OUTER JOIN dept ON (emp.deptno = dept.deptno);
738
739let $query=
740SELECT dname, COUNT(*)
741FROM empdept
742GROUP BY deptno;
743
744eval CREATE algorithm=merge $view_rest;
745eval EXPLAIN $query;
746--echo # There is pk-based FD dept.Depno->dept.dname in dept
747--echo # and it propagates in the view-which-became-nest because it is
748--echo # NULL-friendly.
749eval $query;
750drop view empdept;
751
752eval CREATE algorithm=temptable $view_rest;
753eval EXPLAIN $query;
754--echo # There is pk-based FD dept.Depno->dept.dname in dept
755--echo # and it propagates in the materialized view because it is
756--echo # NULL-friendly, and then in the top query because the view is not in
757--echo # the weak side of an outer join.
758eval $query;
759
760--echo # More tests, for code coverage.
761
762--echo # UNION in derived table
763--error ER_WRONG_FIELD_WITH_GROUP
764select emp.ename
765from
766(select 1 as empno union select 2) deriv,
767emp
768where emp.empno=deriv.empno
769group by emp.empno;
770
771drop view empdept;
772
773--echo # Make the key-searching loop meet view columns which don't wrap a
774--echo # column (CONCAT).
775
776CREATE VIEW empdept AS
777SELECT emp.empno, emp.ename, dept.deptno, concat("",dept.dname) as dname
778FROM emp LEFT JOIN dept ON (emp.deptno = dept.deptno);
779
780--error ER_WRONG_FIELD_WITH_GROUP
781SELECT ename, COUNT(*) FROM empdept WHERE empno=dname and empno=deptno GROUP BY empno;
782
783drop table emp,dept;
784drop view empdept;
785
786--echo #
787--echo # Bug#19636980 ASSERT `TABLE->OUTER_JOIN' FAILED IN GROUP_CHECK::FIND_FD_IN_JOINED_TABLE
788--echo #
789
790CREATE TABLE t1 (
791  c1 INT,
792  c2 INT,
793  c4 DATE,
794  c5 VARCHAR(1)
795);
796
797CREATE TABLE t2 (
798  c1 INT,
799  c2 INT,
800  c3 INT,
801  c5 VARCHAR(1)
802);
803
804--echo # alias1.c5 is not FD, the error is detected at SELECT time
805CREATE VIEW v1 AS
806  SELECT alias1.c4 AS field1
807  FROM t1 AS alias1
808  INNER JOIN t1 AS alias2
809  ON 1
810GROUP BY field1
811ORDER BY alias1.c5;
812
813--error ER_WRONG_FIELD_WITH_GROUP
814SELECT * FROM v1;
815
816DROP VIEW v1;
817
818--echo # alias1.c5 is FD (WHERE contains: alias1.c5='d')
819CREATE VIEW v1 AS
820  SELECT alias1.c4 AS field1, alias1.c4 AS field2
821  FROM t1 AS alias1
822    INNER JOIN t1 AS alias2
823    ON (alias2.c1 = alias1.c2)
824  WHERE ( NOT EXISTS (
825    SELECT SQ1_alias1.c5 AS SQ1_field1
826    FROM t2 AS SQ1_alias1
827    WHERE SQ1_alias1.c3 < alias1.c1
828  ))
829    AND (alias1.c5 = alias1.c5
830      AND alias1.c5 = 'd'
831    )
832GROUP BY field1, field2
833ORDER BY alias1.c5, field1, field2
834;
835
836SELECT * FROM v1;
837
838DROP VIEW v1;
839DROP TABLE t1,t2;
840
841--echo #
842--echo # Bug#19636409 ASSERT `(MAP_OF_NEW_EQ_FDS...` IN GROUP_CHECK::IS_FD_ON_SOURCE ON SELECT
843--echo #
844
845CREATE TABLE t1 (
846  pk int NOT NULL,
847  c1 datetime,
848  c2 varchar(1),
849  c3 date,
850  c4 date,
851  c5 varchar(1),
852  PRIMARY KEY (pk)
853);
854
855CREATE VIEW v1 AS
856  SELECT c3 AS subfield11,
857         pk AS subfield12,
858         c2 AS subfield13
859  FROM t1
860  GROUP BY subfield11, subfield12
861;
862
863--echo # This query is valid. Indeed: field3 i.e. t1.c2 is part of GROUP BY,
864--echo # so, in a group:
865--echo # - all rows have the same value of t1.c2, noted val_c2,
866--echo # - so all rows, which necessarily match WHERE, matched with a row of
867--echo # v1 having subfield11=val_c2 and subfield12=val_c2 (due to IN
868--echo # predicate),
869--echo # - thus both grouping columns of v1's query expression are constant
870--echo # (to val_c2)
871--echo # - thus v1.subfield13 is constant too (grouping columns determine the
872--echo # SELECT list)
873--echo # - so, due to IN, this determines the value of t1.pk (t1 is the top
874--echo # query's table).
875--echo # - so t1.pk is constant, so all columns of t1 are constant.
876--echo # Which proves that it makes sense to search FDs in semijoin
877--echo # equalities.
878--echo # In other words: a semijoin is like a join except that it eliminates
879--echo # duplicates, but duplicates are irrelevant to the decision whether a
880--echo # column is functionally dependent on a set of columns.
881
882SELECT c5 AS field1,
883       c4 AS field2,
884       c2 AS field3,
885       c1 AS field4
886FROM t1
887WHERE ( c2, c2, pk ) IN (
888  SELECT * FROM v1
889)
890GROUP BY field1, field3, field3;
891
892--echo #
893--echo # Bug#19687724 FUNCTIONAL DEPENDENCIES ARE NOT RECOGNIZED IN EQUALITIES BETWEEN ROWS
894--echo #
895
896--echo # Inspired by query above, but with a join:
897SELECT c5 AS field1,
898       c4 AS field2,
899       c2 AS field3,
900       c1 AS field4
901FROM t1, v1
902WHERE ( c2, c2, pk ) = (subfield11, subfield12, subfield13)
903GROUP BY field1, field3, field3;
904
905--echo # With constants:
906SELECT c5 AS field1,
907       c4 AS field2,
908       c2 AS field3,
909       c1 AS field4
910FROM t1
911WHERE ( c2, c2, pk ) = (1, 2, 3)
912GROUP BY field1, field3, field3;
913
914DROP TABLE t1;
915
916CREATE TABLE t1(a INT, b INT, c INT, d INT);
917SELECT a,b,c,d FROM t1 WHERE a=c AND b=d GROUP by a,b;
918SELECT a,b,c,d FROM t1 WHERE (a,b)=(c,d) GROUP BY a,b;
919--error ER_WRONG_FIELD_WITH_GROUP
920SELECT a,b,c,d FROM t1 WHERE (a,b)=(c,d+1) GROUP BY a,b;
921DROP TABLE t1;
922
923DROP VIEW v1;
924
925--echo #
926--echo # Bug #20031708 ASSERT ON GROUP_CHECK::IS_FD_ON_SOURCE
927--echo #
928
929CREATE TABLE t1 (
930  col_varchar_10_utf8 VARCHAR(10) CHARACTER SET utf8,
931  col_int_key INT,
932  pk INT PRIMARY KEY
933);
934
935CREATE TABLE t2 (
936  col_varchar_10_utf8 VARCHAR(10) CHARACTER SET utf8 DEFAULT NULL,
937  col_int_key INT DEFAULT NULL,
938  pk INT PRIMARY KEY
939);
940
941CREATE VIEW v2 AS SELECT * FROM t2;
942
943--echo # The reporter's testcase:
944
945let $query=
946SELECT COUNT(*), t1.col_int_key
947FROM v2 LEFT OUTER JOIN t1
948     ON v2.col_varchar_10_utf8 = t1.col_varchar_10_utf8
949WHERE v2.pk = 4;
950
951--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
952eval $query;
953
954DROP VIEW v2;
955
956--echo # A variant: one column is an expression:
957CREATE VIEW v2 AS SELECT
958 CONCAT(col_varchar_10_utf8,' ') AS col_varchar_10_utf8,
959 col_int_key,
960 pk
961FROM t2;
962
963--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
964eval $query;
965
966DROP VIEW v2;
967
968--echo # Query used in the commit comment: view column involving two tables
969CREATE VIEW v2 AS
970 SELECT t1.pk, t2.col_int_key+1 as c, t1.pk+t2.col_int_key as p
971 FROM t1, t2;
972
973--echo # FDs will be discovered in this order: {}->v2.pk, v2.pk->v2.c,
974--echo # v2.c->v2.p
975SELECT COUNT(*), v2.p
976FROM v2
977WHERE v2.c=v2.p and v2.c=v2.pk AND v2.pk = 4;
978DROP VIEW v2;
979
980--echo # If in the query specification defining a view, a base table's pk is
981--echo # determined,
982--echo # and the view's column is a function of this base table's columns,
983--echo # then the view's column is also determined.
984--echo # So, in this view's result, {v2.pk}->{v2.coa}:
985CREATE ALGORITHM=MERGE VIEW v2 AS
986 SELECT t2.pk, COALESCE(t2.pk, 3) AS coa
987 FROM t1 LEFT JOIN t2 ON 0;
988
989--echo # And thus {pk}->{coa} holds in the result of this query using the view;
990--echo # if there is NULL-complementing in the LEFT JOIN below then (pk,coa)
991--echo # will be (NULL,NULL) and if there is not it will be (non-NULL,3):
992--echo # v2.coa is determined by v2.pk. The key fact is that v2.pk is not
993--echo # NULLable so this is a NFFD.
994SELECT v2.pk, v2.coa
995 FROM t1 LEFT JOIN v2 AS v2 ON 0
996 GROUP BY v2.pk;
997
998DROP VIEW v2;
999DROP TABLE t1,t2;
1000
1001--echo #
1002--echo # Bug#21807579 FUNCTIONAL DEPENDENCIES ARE NOT RECOGNIZED IN GENERATED COLUMNS
1003--echo #
1004
1005CREATE TABLE t ( a INT, c INT GENERATED ALWAYS AS (a+2), d INT GENERATED ALWAYS AS (c+2) );
1006--echo # {a}->{c}, {c}->{d} and {a}->{d} hold.
1007SELECT c FROM t GROUP BY a;
1008SELECT d FROM t GROUP BY c;
1009SELECT d FROM t GROUP BY a;
1010SELECT 1+c FROM t GROUP BY a;
1011SELECT 1+d FROM t GROUP BY c;
1012SELECT 1+d FROM t GROUP BY a;
1013--echo # {t2.a}->{t2.d}->{t1.c}->{t1.d}
1014SELECT t1.d FROM t as t1, t as t2 WHERE t2.d=t1.c GROUP BY t2.a;
1015--error ER_WRONG_FIELD_WITH_GROUP
1016SELECT t1.d FROM t as t1, t as t2 WHERE t2.d>t1.c GROUP BY t2.a;
1017DROP TABLE t;
1018
1019--echo # A non-NULL-friendly dependency.
1020CREATE TABLE t ( a INT,
1021c INT GENERATED ALWAYS AS (COALESCE(a,3)) );
1022INSERT INTO t (a) VALUES(NULL);
1023CREATE TABLE u ( a INT );
1024INSERT INTO u VALUES(0),(1);
1025--echo # Even though {a}->{c} holds in 't', it doesn't propagate to the left
1026--echo # join's result
1027SELECT t.a,t.c FROM u LEFT JOIN t ON u.a>0;
1028--error ER_WRONG_FIELD_WITH_GROUP
1029SELECT t.a,t.c FROM u LEFT JOIN t ON u.a>0 GROUP BY t.a;
1030DROP TABLE t,u;
1031
1032DROP FUNCTION show_json_object;
1033