func (b *planBuilder) buildSelect(sel *ast.SelectStmt) Plan { // Detect aggregate function or groupby clause. aggDetetor := &ast.AggFuncDetector{} sel.Accept(aggDetetor) var aggFuncs []*ast.AggregateFuncExpr if aggDetetor.HasAggFunc { extractor := &ast.AggregateFuncExtractor{AggFuncs: make([]*ast.AggregateFuncExpr, 0)} // TODO: extract aggfuncs from having clause. for _, f := range sel.GetResultFields() { f.Expr.Accept(extractor) // TODO: check error } aggFuncs = extractor.AggFuncs // TODO: extract aggfuncs from having clause. } var p Plan if sel.From != nil { p = b.buildJoin(sel.From.TableRefs) if b.err != nil { return nil } if sel.Where != nil { p = b.buildFilter(p, sel.Where) if b.err != nil { return nil } } if sel.LockTp != ast.SelectLockNone { p = b.buildSelectLock(p, sel.LockTp) if b.err != nil { return nil } } if len(aggFuncs) > 0 { p = b.buildAggregate(p, aggFuncs) } p = b.buildSelectFields(p, sel.GetResultFields()) if b.err != nil { return nil } } else { if len(aggFuncs) > 0 { p = b.buildAggregate(p, aggFuncs) } p = b.buildSelectFields(p, sel.GetResultFields()) if b.err != nil { return nil } if sel.Where != nil { p = b.buildFilter(p, sel.Where) if b.err != nil { return nil } } } if sel.OrderBy != nil { p = b.buildSort(p, sel.OrderBy.Items) if b.err != nil { return nil } } if sel.Limit != nil { p = b.buildLimit(p, sel.Limit) if b.err != nil { return nil } } return p }