New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support SQLMode ONLY_FULL_GROUP_BY and fix a join panic bug #4613
Changes from 82 commits
229f129
57547c6
71bb746
f5dadd5
da4405a
dd18f96
b2570bb
acd4546
a12fbca
f517321
d6bd63e
9756236
03da4c0
84fb417
803b9a2
961ba93
06b4674
506be2f
b9dd383
802e146
f7491e9
070b867
dc49b82
6eb2564
84694ea
947a06f
f152f90
940a40a
39c9b91
6712018
e7ef3c6
a3ee2bc
0ed42fc
f602bd1
7c1b979
648199f
79e14d2
fa87ec4
f0ef632
d57b460
9f4ce42
6cebdb1
b537d82
4194122
32ff413
7dd1bab
be9456e
62cc92f
d15d8e6
e19c46b
17e33c2
0e624d5
10cd46c
500385c
895c291
27a4b12
8670ee1
b587ebd
8cd1243
34037b7
e205e56
c326d14
11843f4
ac617e1
16a907d
295512a
3b27ce0
554b50c
4b4b852
cbd64e4
a4b0613
f3aaf30
64c99f7
2993861
924532d
e3ce8a6
5986b0b
f0d2e8c
7f730cd
f75aaf7
8237ab6
89b2b3d
df1f692
045f37c
94e1771
f22d952
d99bb67
bf54bf0
430bfff
e1f711a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,11 +14,14 @@ | |
package executor_test | ||
|
||
import ( | ||
"github.com/juju/errors" | ||
. "github.com/pingcap/check" | ||
"github.com/pingcap/tidb/ast" | ||
"github.com/pingcap/tidb/executor" | ||
"github.com/pingcap/tidb/expression" | ||
"github.com/pingcap/tidb/mysql" | ||
"github.com/pingcap/tidb/plan" | ||
"github.com/pingcap/tidb/terror" | ||
"github.com/pingcap/tidb/util/testkit" | ||
) | ||
|
||
|
@@ -349,9 +352,148 @@ func (s *testSuite) TestAggPushDown(c *C) { | |
tk.MustQuery("select a, count(b) from (select * from t union all select * from tt) k group by a").Check(testkit.Rows("1 2", "2 1")) | ||
} | ||
|
||
func (s *testSuite) TestOnlyFullGroupBy(c *C) { | ||
tk := testkit.NewTestKit(c, s.store) | ||
tk.MustExec("use test") | ||
tk.MustExec("set sql_mode = 'ONLY_FULL_GROUP_BY'") | ||
tk.MustExec("drop table if exists t") | ||
tk.MustExec("create table t(a int not null primary key, b int not null, c int default null, d int not null, unique key I_b_c (b,c), unique key I_b_d (b,d))") | ||
tk.MustExec("create table x(a int not null primary key, b int not null, c int default null, d int not null, unique key I_b_c (b,c), unique key I_b_d (b,d))") | ||
|
||
// test AggregateFunc | ||
tk.MustExec("select max(a) from t group by d") | ||
// test incompatible with sql_mode = ONLY_FULL_GROUP_BY | ||
var err error | ||
var terr *terror.Error | ||
_, err = tk.Exec("select * from t group by d") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is an easier way to check error code.
|
||
_, err = tk.Exec("select b-c from t group by b+c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select (b-c)*(b+c), min(a) from t group by b+c, b-c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select b between c and d from t group by b,c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select case b when 1 then c when 2 then d else d end from t group by b,c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select c > (select b from t) from t group by b") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select c is null from t group by b") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select c is true from t group by b") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select (c+b)*d from t group by c,d") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select b in (c,d) from t group by b,c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select b like '%a' from t group by c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select c REGEXP '1.*' from t group by b") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select -b from t group by c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
// test compatible with sql_mode = ONLY_FULL_GROUP_BY | ||
tk.MustExec("select a from t group by a,b,c") | ||
tk.MustExec("select b from t group by b") | ||
tk.MustExec("select b as e from t group by b") | ||
tk.MustExec("select b+c from t group by b+c") | ||
tk.MustExec("select b+c, min(a) from t group by b+c, b-c") | ||
tk.MustExec("select b+c, min(a) from t group by b, c") | ||
tk.MustExec("select b+c from t group by b,c") | ||
tk.MustExec("select b between c and d from t group by b,c,d") | ||
tk.MustExec("select case b when 1 then c when 2 then d else d end from t group by b,c,d") | ||
tk.MustExec("select c > (select b from t) from t group by c") | ||
tk.MustExec("select exists (select * from t) from t group by d;") | ||
tk.MustExec("select c is null from t group by c") | ||
tk.MustExec("select c is true from t group by c") | ||
tk.MustExec("select (c+b)*d from t group by c,b,d") | ||
tk.MustExec("select b in (c,d) from t group by b,c,d") | ||
tk.MustExec("select b like '%a' from t group by b") | ||
tk.MustExec("select c REGEXP '1.*' from t group by c") | ||
tk.MustExec("select -b from t group by b") | ||
// test functinal depend on primary key | ||
tk.MustExec("select * from t group by a") | ||
// test functional depend on unique not null columns | ||
tk.MustExec("select * from t group by b,d") | ||
// test functional depend on a unique null column | ||
_, err = tk.Exec("select * from t group by b,c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
// test functional dependency derived from keys in where condition | ||
tk.MustExec("select * from t where c = d group by b, c") | ||
tk.MustExec("select t.*, x.* from t, x where t.a = x.a group by t.a") | ||
tk.MustExec("select t.*, x.* from t, x where t.b = x.b and t.d = x.d group by t.b, t.d") | ||
tk.MustExec("select t.*, x.* from t, x where t.b = x.a group by t.b, t.d") | ||
tk.MustExec("select t.b, x.* from t, x where t.b = x.a group by t.b") | ||
_, err = tk.Exec("select t.*, x.* from t, x where t.c = x.a group by t.b, t.c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
// test functional dependency derived from keys in join | ||
tk.MustExec("select t.*, x.* from t inner join x on t.a = x.a group by t.a") | ||
tk.MustExec("select t.*, x.* from t inner join x on (t.b = x.b and t.d = x.d) group by t.b, x.d") | ||
tk.MustExec("select t.b, x.* from t inner join x on t.b = x.b group by t.b, x.d") | ||
tk.MustExec("select t.b, x.* from t left join x on t.b = x.b group by t.b, x.d") | ||
tk.MustExec("select t.b, x.* from t left join x on x.b = t.b group by t.b, x.d") | ||
tk.MustExec("select x.b, t.* from t right join x on x.b = t.b group by x.b, t.d") | ||
tk.MustExec("select x.b, t.* from t right join x on t.b = x.b group by x.b, t.d") | ||
_, err = tk.Exec("select t.b, x.* from t right join x on t.b = x.b group by t.b, x.d") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
_, err = tk.Exec("select t.b, x.* from t right join x on t.b = x.b group by t.b, x.d") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
// test functional dependency of derived table | ||
tk.MustExec("select * from (select * from t) as e group by a") | ||
tk.MustExec("select * from (select * from t) as e group by b,d") | ||
_, err = tk.Exec("select * from (select * from t) as e group by b,c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
// test order by | ||
tk.MustExec("select c from t group by c,d order by d") | ||
_, err = tk.Exec("select c from t group by c order by d") | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrFieldNotInGroupBy)) | ||
// test ambiguous column | ||
_, err = tk.Exec("select c from t,x group by t.c") | ||
c.Assert(err, NotNil) | ||
terr = errors.Trace(err).(*errors.Err).Cause().(*terror.Error) | ||
c.Assert(terr.Code(), Equals, terror.ErrCode(mysql.ErrNonUniq)) | ||
} | ||
|
||
func (s *testSuite) TestHaving(c *C) { | ||
tk := testkit.NewTestKitWithInit(c, s.store) | ||
|
||
tk.MustExec("set sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'") | ||
tk.MustExec("drop table if exists t") | ||
tk.MustExec("create table t (c1 int, c2 int, c3 int)") | ||
tk.MustExec("insert into t values (1,2,3), (2, 3, 1), (3, 1, 2)") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,9 +89,12 @@ func (s *testSuite) TestNestedLoopJoin(c *C) { | |
func (s *testSuite) TestJoinPanic(c *C) { | ||
tk := testkit.NewTestKit(c, s.store) | ||
tk.MustExec("use test") | ||
tk.MustExec("set sql_mode = 'ONLY_FULL_GROUP_BY'") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it still panic if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it would not panic. |
||
tk.MustExec("drop table if exists events") | ||
tk.MustExec("create table events (clock int, source int)") | ||
tk.MustQuery("SELECT * FROM events e JOIN (SELECT MAX(clock) AS clock FROM events e2 GROUP BY e2.source) e3 ON e3.clock=e.clock") | ||
_, err := tk.Exec("SELECT * FROM events e JOIN (SELECT clock FROM events e2 GROUP BY e2.source) e3 ON e3.clock=e.clock") | ||
c.Check(err, NotNil) | ||
} | ||
|
||
func (s *testSuite) TestJoin(c *C) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We better check error equals
ErrFieldNotInGroupBy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok