diff --git a/executor/aggregate_test.go b/executor/aggregate_test.go index 1b1efa00646b3..c10e89f6fe8ad 100644 --- a/executor/aggregate_test.go +++ b/executor/aggregate_test.go @@ -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") diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 976f452a1391f..228e6d7351054 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -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 { @@ -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 @@ -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