Skip to content

Commit 15f5886

Browse files
authored
Bugfix: GROUP BY/HAVING alias resolution (#15344)
1 parent 0200369 commit 15f5886

21 files changed

+935
-310
lines changed

go/test/endtoend/vtgate/queries/aggregation/aggregation_test.go

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,21 @@ func start(t *testing.T) (utils.MySQLCompare, func()) {
4040
deleteAll := func() {
4141
_, _ = utils.ExecAllowError(t, mcmp.VtConn, "set workload = oltp")
4242

43-
tables := []string{"t9", "aggr_test", "t3", "t7_xxhash", "aggr_test_dates", "t7_xxhash_idx", "t1", "t2", "t10"}
43+
tables := []string{
44+
"t3",
45+
"t3_id7_idx",
46+
"t9",
47+
"aggr_test",
48+
"aggr_test_dates",
49+
"t7_xxhash",
50+
"t7_xxhash_idx",
51+
"t1",
52+
"t2",
53+
"t10",
54+
"emp",
55+
"dept",
56+
"bet_logs",
57+
}
4458
for _, table := range tables {
4559
_, _ = mcmp.ExecAndIgnore("delete from " + table)
4660
}
@@ -673,3 +687,84 @@ func TestDistinctAggregation(t *testing.T) {
673687
})
674688
}
675689
}
690+
691+
func TestHavingQueries(t *testing.T) {
692+
mcmp, closer := start(t)
693+
defer closer()
694+
695+
inserts := []string{
696+
`INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, comm, deptno) VALUES
697+
(1, 'John', 'Manager', NULL, '2022-01-01', 5000, 500, 1),
698+
(2, 'Doe', 'Analyst', 1, '2023-01-01', 4500, NULL, 1),
699+
(3, 'Jane', 'Clerk', 1, '2023-02-01', 3000, 200, 2),
700+
(4, 'Mary', 'Analyst', 2, '2022-03-01', 4700, NULL, 1),
701+
(5, 'Smith', 'Salesman', 3, '2023-01-15', 3200, 300, 3)`,
702+
"INSERT INTO dept (deptno, dname, loc) VALUES (1, 'IT', 'New York'), (2, 'HR', 'London'), (3, 'Sales', 'San Francisco')",
703+
"INSERT INTO t1 (t1_id, name, value, shardKey) VALUES (1, 'Name1', 'Value1', 100), (2, 'Name2', 'Value2', 100), (3, 'Name1', 'Value3', 200)",
704+
"INSERT INTO aggr_test_dates (id, val1, val2) VALUES (1, '2023-01-01', '2023-01-02'), (2, '2023-02-01', '2023-02-02'), (3, '2023-03-01', '2023-03-02')",
705+
"INSERT INTO t10 (k, a, b) VALUES (1, 10, 20), (2, 30, 40), (3, 50, 60)",
706+
"INSERT INTO t3 (id5, id6, id7) VALUES (1, 10, 100), (2, 20, 200), (3, 30, 300)",
707+
"INSERT INTO t9 (id1, id2, id3) VALUES (1, 'A1', 'B1'), (2, 'A2', 'B2'), (3, 'A1', 'B3')",
708+
"INSERT INTO aggr_test (id, val1, val2) VALUES (1, 'Test1', 100), (2, 'Test2', 200), (3, 'Test1', 300), (4, 'Test3', 400)",
709+
"INSERT INTO t2 (id, shardKey) VALUES (1, 100), (2, 200), (3, 300)",
710+
`INSERT INTO bet_logs (id, merchant_game_id, bet_amount, game_id) VALUES
711+
(1, 1, 100.0, 10),
712+
(2, 1, 200.0, 11),
713+
(3, 2, 300.0, 10),
714+
(4, 3, 400.0, 12)`,
715+
}
716+
717+
for _, insert := range inserts {
718+
mcmp.Exec(insert)
719+
}
720+
721+
queries := []string{
722+
// The following queries are not allowed by MySQL but Vitess allows them
723+
// SELECT ename FROM emp GROUP BY ename HAVING sal > 5000
724+
// SELECT val1, COUNT(val2) FROM aggr_test_dates GROUP BY val1 HAVING val2 > 5
725+
// SELECT k, a FROM t10 GROUP BY k HAVING b > 2
726+
// SELECT loc FROM dept GROUP BY loc HAVING COUNT(deptno) AND dname = 'Sales'
727+
// SELECT AVG(val2) AS average_val2 FROM aggr_test HAVING val1 = 'Test'
728+
729+
// these first queries are all failing in different ways. let's check that Vitess also fails
730+
731+
"SELECT deptno, AVG(sal) AS average_salary HAVING average_salary > 5000 FROM emp",
732+
"SELECT job, COUNT(empno) AS num_employees FROM emp HAVING num_employees > 2",
733+
"SELECT dname, SUM(sal) FROM dept JOIN emp ON dept.deptno = emp.deptno HAVING AVG(sal) > 6000",
734+
"SELECT COUNT(*) AS count FROM emp WHERE count > 5",
735+
"SELECT `name`, AVG(`value`) FROM t1 GROUP BY `name` HAVING `name`",
736+
"SELECT empno, MAX(sal) FROM emp HAVING COUNT(*) > 3",
737+
"SELECT id, SUM(bet_amount) AS total_bets FROM bet_logs HAVING total_bets > 1000",
738+
"SELECT merchant_game_id FROM bet_logs GROUP BY merchant_game_id HAVING SUM(bet_amount)",
739+
"SELECT shardKey, COUNT(id) FROM t2 HAVING shardKey > 100",
740+
"SELECT deptno FROM emp GROUP BY deptno HAVING MAX(hiredate) > '2020-01-01'",
741+
742+
// These queries should not fail
743+
"SELECT deptno, COUNT(*) AS num_employees FROM emp GROUP BY deptno HAVING num_employees > 5",
744+
"SELECT ename, SUM(sal) FROM emp GROUP BY ename HAVING SUM(sal) > 10000",
745+
"SELECT dname, AVG(sal) AS average_salary FROM emp JOIN dept ON emp.deptno = dept.deptno GROUP BY dname HAVING average_salary > 5000",
746+
"SELECT dname, MAX(sal) AS max_salary FROM emp JOIN dept ON emp.deptno = dept.deptno GROUP BY dname HAVING max_salary < 10000",
747+
"SELECT YEAR(hiredate) AS year, COUNT(*) FROM emp GROUP BY year HAVING COUNT(*) > 2",
748+
"SELECT mgr, COUNT(empno) AS managed_employees FROM emp WHERE mgr IS NOT NULL GROUP BY mgr HAVING managed_employees >= 3",
749+
"SELECT deptno, SUM(comm) AS total_comm FROM emp GROUP BY deptno HAVING total_comm > AVG(total_comm)",
750+
"SELECT id2, COUNT(*) AS count FROM t9 GROUP BY id2 HAVING count > 1",
751+
"SELECT val1, COUNT(*) FROM aggr_test GROUP BY val1 HAVING COUNT(*) > 1",
752+
"SELECT DATE(val1) AS date, SUM(val2) FROM aggr_test_dates GROUP BY date HAVING SUM(val2) > 100",
753+
"SELECT shardKey, AVG(`value`) FROM t1 WHERE `value` IS NOT NULL GROUP BY shardKey HAVING AVG(`value`) > 10",
754+
"SELECT job, COUNT(*) AS job_count FROM emp GROUP BY job HAVING job_count > 3",
755+
"SELECT b, AVG(a) AS avg_a FROM t10 GROUP BY b HAVING AVG(a) > 5",
756+
"SELECT merchant_game_id, SUM(bet_amount) AS total_bets FROM bet_logs GROUP BY merchant_game_id HAVING total_bets > 1000",
757+
"SELECT loc, COUNT(deptno) AS num_depts FROM dept GROUP BY loc HAVING num_depts > 1",
758+
"SELECT `name`, COUNT(*) AS name_count FROM t1 GROUP BY `name` HAVING name_count > 2",
759+
"SELECT COUNT(*) AS num_jobs FROM emp GROUP BY empno HAVING num_jobs > 1",
760+
"SELECT id, COUNT(*) AS count FROM t2 GROUP BY id HAVING count > 1",
761+
"SELECT val2, SUM(id) FROM aggr_test GROUP BY val2 HAVING SUM(id) > 10",
762+
"SELECT game_id, COUNT(*) AS num_logs FROM bet_logs GROUP BY game_id HAVING num_logs > 5",
763+
}
764+
765+
for _, query := range queries {
766+
mcmp.Run(query, func(mcmp *utils.MySQLCompare) {
767+
mcmp.ExecAllowAndCompareError(query)
768+
})
769+
}
770+
}

go/vt/vtgate/executor_select_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,7 +1932,7 @@ func TestSelectScatterOrderBy(t *testing.T) {
19321932
require.NoError(t, err)
19331933

19341934
wantQueries := []*querypb.BoundQuery{{
1935-
Sql: "select col1, col2, weight_string(col2) from `user` order by col2 desc",
1935+
Sql: "select col1, col2, weight_string(col2) from `user` order by `user`.col2 desc",
19361936
BindVariables: map[string]*querypb.BindVariable{},
19371937
}}
19381938
for _, conn := range conns {
@@ -2005,7 +2005,7 @@ func TestSelectScatterOrderByVarChar(t *testing.T) {
20052005
require.NoError(t, err)
20062006

20072007
wantQueries := []*querypb.BoundQuery{{
2008-
Sql: "select col1, textcol, weight_string(textcol) from `user` order by textcol desc",
2008+
Sql: "select col1, textcol, weight_string(textcol) from `user` order by `user`.textcol desc",
20092009
BindVariables: map[string]*querypb.BindVariable{},
20102010
}}
20112011
for _, conn := range conns {
@@ -2071,7 +2071,7 @@ func TestStreamSelectScatterOrderBy(t *testing.T) {
20712071
require.NoError(t, err)
20722072

20732073
wantQueries := []*querypb.BoundQuery{{
2074-
Sql: "select id, col, weight_string(col) from `user` order by col desc",
2074+
Sql: "select id, col, weight_string(col) from `user` order by `user`.col desc",
20752075
BindVariables: map[string]*querypb.BindVariable{},
20762076
}}
20772077
for _, conn := range conns {
@@ -2133,7 +2133,7 @@ func TestStreamSelectScatterOrderByVarChar(t *testing.T) {
21332133
require.NoError(t, err)
21342134

21352135
wantQueries := []*querypb.BoundQuery{{
2136-
Sql: "select id, textcol, weight_string(textcol) from `user` order by textcol desc",
2136+
Sql: "select id, textcol, weight_string(textcol) from `user` order by `user`.textcol desc",
21372137
BindVariables: map[string]*querypb.BindVariable{},
21382138
}}
21392139
for _, conn := range conns {
@@ -2329,7 +2329,7 @@ func TestSelectScatterLimit(t *testing.T) {
23292329
require.NoError(t, err)
23302330

23312331
wantQueries := []*querypb.BoundQuery{{
2332-
Sql: "select col1, col2, weight_string(col2) from `user` order by col2 desc limit :__upper_limit",
2332+
Sql: "select col1, col2, weight_string(col2) from `user` order by `user`.col2 desc limit :__upper_limit",
23332333
BindVariables: map[string]*querypb.BindVariable{"__upper_limit": sqltypes.Int64BindVariable(3)},
23342334
}}
23352335
for _, conn := range conns {
@@ -2401,7 +2401,7 @@ func TestStreamSelectScatterLimit(t *testing.T) {
24012401
require.NoError(t, err)
24022402

24032403
wantQueries := []*querypb.BoundQuery{{
2404-
Sql: "select col1, col2, weight_string(col2) from `user` order by col2 desc limit :__upper_limit",
2404+
Sql: "select col1, col2, weight_string(col2) from `user` order by `user`.col2 desc limit :__upper_limit",
24052405
BindVariables: map[string]*querypb.BindVariable{"__upper_limit": sqltypes.Int64BindVariable(3)},
24062406
}}
24072407
for _, conn := range conns {

0 commit comments

Comments
 (0)