@@ -252,6 +252,7 @@ func validateGroupBy(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Scop
252252
253253 var err error
254254 var project * plan.Project
255+ var orderBy * plan.Sort
255256 transform .Inspect (n , func (n sql.Node ) bool {
256257 switch n := n .(type ) {
257258 case * plan.GroupBy :
@@ -307,20 +308,35 @@ func validateGroupBy(ctx *sql.Context, a *Analyzer, n sql.Node, scope *plan.Scop
307308 return true
308309 }
309310
310- selectExprs := getSelectExprs (project , n .SelectDeps , groupBys )
311+ selectExprs , orderByExprs := getSelectAndOrderByExprs (project , orderBy , n .SelectDeps , groupBys )
311312
312313 for i , expr := range selectExprs {
313314 if valid , col := expressionReferencesOnlyGroupBys (groupBys , expr , noGroupBy ); ! valid {
314315 if noGroupBy {
315316 err = sql .ErrNonAggregatedColumnWithoutGroupBy .New (i + 1 , col )
316317 } else {
317- err = analyzererrors .ErrValidationGroupBy .New (i + 1 )
318+ err = analyzererrors .ErrValidationGroupBy .New (i + 1 , col )
318319 }
319320 return false
320321 }
321322 }
323+ // According to MySQL documentation, we should still be validating ORDER BY expressions ("If a query has
324+ // aggregate functions and no GROUP BY clause, it cannot have nonaggregated columns in the select list, HAVING
325+ // condition, or ORDER BY list with ONLY_FULL_GROUP_BY enabled"). But when testing actual queries in MySQL,
326+ // it doesn't seem like they validate ORDER BY expressions in aggregate queries without an explicit GROUP BY
327+ if ! noGroupBy {
328+ for i , expr := range orderByExprs {
329+ if valid , col := expressionReferencesOnlyGroupBys (groupBys , expr , noGroupBy ); ! valid {
330+ err = analyzererrors .ErrValidationGroupByOrderBy .New (i + 1 , col )
331+ return false
332+ }
333+ }
334+ }
322335 case * plan.Project :
323336 project = n
337+ orderBy = nil
338+ case * plan.Sort :
339+ orderBy = n
324340 }
325341 return true
326342 })
@@ -351,42 +367,56 @@ func getEqualsDependencies(expr sql.Expression) []sql.Expression {
351367
352368// getSelectExprs transforms the projection expressions from a Project node such that it uses the appropriate select
353369// dependency expressions.
354- func getSelectExprs (project * plan.Project , selectDeps []sql.Expression , groupBys map [string ]bool ) []sql.Expression {
355- if project == nil {
356- return selectDeps
370+ func getSelectAndOrderByExprs (project * plan.Project , orderBy * plan. Sort , selectDeps []sql.Expression , groupBys map [string ]bool ) ( []sql.Expression , []sql. Expression ) {
371+ if project == nil && orderBy == nil {
372+ return selectDeps , make ([]sql. Expression , 0 )
357373 } else {
358374 sd := make (map [string ]sql.Expression , len (selectDeps ))
359375 for _ , dep := range selectDeps {
360376 sd [strings .ToLower (dep .String ())] = dep
361377 }
362378
363379 selectExprs := make ([]sql.Expression , 0 )
380+ orderByExprs := make ([]sql.Expression , 0 )
364381
365382 for _ , expr := range project .Projections {
366383 if ! project .AliasDeps [strings .ToLower (expr .String ())] {
367- resolvedExpr , _ , _ := transform .Expr (expr , func (expr sql.Expression ) (sql.Expression , transform.TreeIdentity , error ) {
368- if groupBys [strings .ToLower (expr .String ())] {
369- return expr , transform .SameTree , nil
370- }
371- switch expr := expr .(type ) {
372- case * expression.Alias :
373- if dep , ok := sd [strings .ToLower (expr .Child .String ())]; ok {
374- return dep , transform .NewTree , nil
375- }
376- case * expression.GetField :
377- if dep , ok := sd [strings .ToLower (expr .String ())]; ok {
378- return dep , transform .NewTree , nil
379- }
380- }
381- return expr , transform .SameTree , nil
382- })
384+ resolvedExpr := resolveExpr (expr , sd , groupBys )
383385 selectExprs = append (selectExprs , resolvedExpr )
384386 }
385387 }
386- return selectExprs
388+
389+ if orderBy != nil {
390+ for _ , expr := range orderBy .Expressions () {
391+ resolvedExpr := resolveExpr (expr , sd , groupBys )
392+ orderByExprs = append (orderByExprs , resolvedExpr )
393+ }
394+ }
395+
396+ return selectExprs , orderByExprs
387397 }
388398}
389399
400+ func resolveExpr (expr sql.Expression , selectDeps map [string ]sql.Expression , groupBys map [string ]bool ) sql.Expression {
401+ resolvedExpr , _ , _ := transform .Expr (expr , func (expr sql.Expression ) (sql.Expression , transform.TreeIdentity , error ) {
402+ if groupBys [strings .ToLower (expr .String ())] {
403+ return expr , transform .SameTree , nil
404+ }
405+ switch expr := expr .(type ) {
406+ case * expression.Alias :
407+ if dep , ok := selectDeps [strings .ToLower (expr .Child .String ())]; ok {
408+ return dep , transform .NewTree , nil
409+ }
410+ case * expression.GetField :
411+ if dep , ok := selectDeps [strings .ToLower (expr .String ())]; ok {
412+ return dep , transform .NewTree , nil
413+ }
414+ }
415+ return expr , transform .SameTree , nil
416+ })
417+ return resolvedExpr
418+ }
419+
390420// expressionReferencesOnlyGroupBys validates that an expression is dependent on only group by expressions
391421func expressionReferencesOnlyGroupBys (groupBys map [string ]bool , expr sql.Expression , noGroupBy bool ) (bool , string ) {
392422 var col string
0 commit comments