Skip to content

Commit

Permalink
planner: enable function any_value in aggregation if `ONLY_F… (#10994)
Browse files Browse the repository at this point in the history
  • Loading branch information
XuHuaiyu authored and zz-jason committed Jul 3, 2019
1 parent 6d90e81 commit 308488c
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
2 changes: 2 additions & 0 deletions executor/aggregate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ func (s *testSuite) TestOnlyFullGroupBy(c *C) {

// test AggregateFunc
tk.MustQuery("select max(a) from t group by d")
// for issue #8161: enable `any_value` in aggregation if `ONLY_FULL_GROUP_BY` is set
tk.MustQuery("select max(a), any_value(c) from t group by d;")
// test incompatible with sql_mode = ONLY_FULL_GROUP_BY
var err error
_, err = tk.Exec("select * from t group by d")
Expand Down
25 changes: 19 additions & 6 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,13 @@ func checkExprInGroupBy(p LogicalPlan, expr ast.ExprNode, offset int, loc string
}
}
}
// Function `any_value` can be used in aggregation, even `ONLY_FULL_GROUP_BY` is set.
// See https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_any-value for details
if f, ok := expr.(*ast.FuncCallExpr); ok {
if f.FnName.L == ast.AnyValue {
return
}
}
colMap := make(map[*expression.Column]struct{}, len(p.Schema().Columns))
allColFromExprNode(p, expr, colMap)
for col := range colMap {
Expand Down Expand Up @@ -1531,17 +1538,23 @@ func (b *planBuilder) checkOnlyFullGroupByWithOutGroupClause(p LogicalPlan, fiel
// colResolverForOnlyFullGroupBy visits Expr tree to find out if an Expr tree is an aggregation function.
// If so, find out the first column name that not in an aggregation function.
type colResolverForOnlyFullGroupBy struct {
firstNonAggCol *ast.ColumnName
exprIdx int
firstNonAggColIdx int
hasAggFunc bool
firstNonAggCol *ast.ColumnName
exprIdx int
firstNonAggColIdx int
hasAggFuncOrAnyValue bool
}

func (c *colResolverForOnlyFullGroupBy) Enter(node ast.Node) (ast.Node, bool) {
switch t := node.(type) {
case *ast.AggregateFuncExpr:
c.hasAggFunc = true
c.hasAggFuncOrAnyValue = true
return node, true
case *ast.FuncCallExpr:
// enable function `any_value` in aggregation even `ONLY_FULL_GROUP_BY` is set
if t.FnName.L == ast.AnyValue {
c.hasAggFuncOrAnyValue = true
return node, true
}
case *ast.ColumnNameExpr:
if c.firstNonAggCol == nil {
c.firstNonAggCol, c.firstNonAggColIdx = t.Name, c.exprIdx
Expand All @@ -1558,7 +1571,7 @@ func (c *colResolverForOnlyFullGroupBy) Leave(node ast.Node) (ast.Node, bool) {
}

func (c *colResolverForOnlyFullGroupBy) Check() error {
if c.hasAggFunc && c.firstNonAggCol != nil {
if c.hasAggFuncOrAnyValue && c.firstNonAggCol != nil {
return ErrMixOfGroupFuncAndFields.GenWithStackByArgs(c.firstNonAggColIdx+1, c.firstNonAggCol.Name.O)
}
return nil
Expand Down

0 comments on commit 308488c

Please sign in to comment.