Skip to content
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

plan: fix a bug when 'only_full_group_by' is set in sql_mode #6734

Merged
merged 35 commits into from
Jun 25, 2018

Conversation

spongedu
Copy link
Contributor

@spongedu spongedu commented Jun 2, 2018

In MySQL 5.7, when only_full_group_by is set in SQL_MODE, The following query will fail, raise error for nonaggregated column in query without GROUP BY:

mysql> create table t(a bigint, b bigint, c bigint);                                                                                           Query OK, 0 rows affected (0.02 sec)

mysql> select a, max(b) from t;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'dc_test.t.a'; this is incompatible with sql_mode=only_full_group_by

This pr make TiDB compatible with MySQL 5.7 under this circustance.

@shenli shenli added the contribution This PR is from a community contributor. label Jun 3, 2018
@shenli
Copy link
Member

shenli commented Jun 3, 2018

/run-all-tests

@shenli
Copy link
Member

shenli commented Jun 4, 2018

/run-all-tests

@@ -1342,6 +1350,51 @@ func (b *planBuilder) checkOnlyFullGroupBy(p LogicalPlan, fields []*ast.SelectFi
}
}

func (b *planBuilder) checkOnlyFullGroupByWithOutGroupClause(p LogicalPlan, fields []*ast.SelectField) {
resolver := colResolverForOnlyFullGroupBy{}
//for idx, field := range fields {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the useless comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}
}

type colResolverForOnlyFullGroupBy struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@zz-jason
Copy link
Member

zz-jason commented Jun 5, 2018

@spongedu plz fix ci

@spongedu
Copy link
Contributor Author

spongedu commented Jun 5, 2018

@zz-jason Done. PTAL

@shenli
Copy link
Member

shenli commented Jun 6, 2018

/run-all-tests

resolver.exprIdx = idx
field.Accept(&resolver)
if err := resolver.Check(); err != nil {
b.err = err
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b.err = errors.Trace(err)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

}

func (c *colResolverForOnlyFullGroupBy) Enter(node ast.Node) (ast.Node, bool) {
switch node.(type) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use x := node.(type), so that we don't need to do the type assertion again at line 1381.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


func (c *colResolverForOnlyFullGroupBy) Check() error {
if c.hasAggFunc && c.firstNonAggCol != nil {
return ErrMixOfGroupFuncAndFields.GenByArgs(c.firstNonAggColIdx+1, c.firstNonAggCol.Name.O)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MySQL(localhost:3306) > select count(a) + a from t;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'test.t.a'; this is incompatible with sql_mode=only_full_group_by

Seems MySQL use database_name + table_name + column_name to print the name of nonaggregated column

Copy link
Contributor Author

@spongedu spongedu Jun 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not always go that way.... If the FROM clause is a subquery, table_name + column_name is used, no database_name.....

mysql> select max(a) + a from (select 1 as a, 2 as b , 3 as c) f;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'f.a'; this is incompatible with sql_mode=only_full_group_by

another case, if FROM clause is a join, the error message depends on where the column coms from

mysql> select max(a) + a from (select 1 as a, 2 as b , 3 as c) f join t on f.a = t.c1;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'f.a'; this is incompati
ble with sql_mode=only_full_group_by
mysql> select max(c1) + c1 from (select 1 as a, 2 as b , 3 as c) f join t on f.a = t.c1;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'cdbagentmanager.t.c1'; 
this is incompatible with sql_mode=only_full_group_by

so I wonder if it's necessary keep the error message as exactly the same as MySQL....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spongedu It's not necessary, we can leave it to the future work 😆

}

func (c *colResolverForOnlyFullGroupBy) Check() error {
if c.hasAggFunc && c.firstNonAggCol != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about select min(c1) from t where c2 in (select c2 from t where c3 > 10); Could this checker handle the situation of subquery?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this situation is not handled by this checker. ColumnRefs in predicates is not affected under this circumstance because predicates are processed prior to aggregations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least, this PR is an improvement. @shenli

Copy link
Member

@zz-jason zz-jason left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@zz-jason zz-jason added the status/LGT1 Indicates that a PR has LGTM 1. label Jun 12, 2018
@zz-jason zz-jason changed the title plan: when 'only_full_group_by' is set in sql_mode, raise error for nonaggregated column in query without GROUP BY plan: fix a bug when 'only_full_group_by' is set in sql_mode Jun 12, 2018
@zz-jason zz-jason added the type/bugfix This PR fixes a bug. label Jun 12, 2018
@@ -444,6 +452,9 @@ func (s *testSuite) TestOnlyFullGroupBy(c *C) {
tk.MustQuery("select b like '%a' from t group by b")
tk.MustQuery("select c REGEXP '1.*' from t group by c")
tk.MustQuery("select -b from t group by b")
tk.MustQuery("select max(a+b) from t")
tk.MustQuery("select avg(a)+1 from t")
_, err = tk.Exec("select count(c), 5 from t")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check this error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. @zimulala PTAL :)

@spongedu
Copy link
Contributor Author

@zimulala PTAL

@spongedu
Copy link
Contributor Author

@shenli PTAL :P

@tiancaiamao
Copy link
Contributor

LGTM

@tiancaiamao tiancaiamao added the status/LGT2 Indicates that a PR has LGTM 2. label Jun 25, 2018
@tiancaiamao tiancaiamao merged commit a936065 into pingcap:master Jun 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution This PR is from a community contributor. status/LGT1 Indicates that a PR has LGTM 1. status/LGT2 Indicates that a PR has LGTM 2. type/bugfix This PR fixes a bug.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants