func (b *planBuilder) buildNewSelect(sel *ast.SelectStmt) Plan { oldLen := len(sel.Fields.Fields) hasAgg := b.detectSelectAgg(sel) var aggFuncs []*ast.AggregateFuncExpr var havingMap, orderMap, totalMap map[*ast.AggregateFuncExpr]int if hasAgg { aggFuncs, havingMap, orderMap, totalMap = b.extractAggFunc(sel) } // Build subquery // Convert subquery to expr with plan // TODO: add subquery support. //b.buildSubquery(sel) var p Plan if sel.From != nil { p = b.buildResultSetNode(sel.From.TableRefs) if b.err != nil { return nil } if sel.Where != nil { p = b.buildSelection(p, sel.Where, nil) } if b.err != nil { return nil } if sel.LockTp != ast.SelectLockNone { p = b.buildSelectLock(p, sel.LockTp) if b.err != nil { return nil } } if hasAgg { p = b.buildAggregation(p, aggFuncs, sel.GroupBy) if b.err != nil { return nil } } } else { p = b.buildNewTableDual() if b.err != nil { return nil } if sel.Where != nil { b.buildSelection(p, sel.Where, nil) } if hasAgg { p = b.buildAggregation(p, aggFuncs, nil) if b.err != nil { return nil } } } p = b.buildProjection(p, sel.Fields.Fields, totalMap) if b.err != nil { return nil } if sel.Having != nil { p = b.buildSelection(p, sel.Having.Expr, havingMap) if b.err != nil { return nil } } if sel.Distinct { p = b.buildDistinct(p) if b.err != nil { return nil } } // TODO: implement push order during cbo if sel.OrderBy != nil { p = b.buildNewSort(p, sel.OrderBy.Items, orderMap) if b.err != nil { return nil } } if sel.Limit != nil { p = b.buildLimit(p, sel.Limit) if b.err != nil { return nil } } if oldLen != len(sel.Fields.Fields) { proj := &Projection{} proj.id = b.allocID(proj) var newSchema expression.Schema oldSchema := p.GetSchema() proj.Exprs = make([]expression.Expression, 0, oldLen) for _, col := range oldSchema[:oldLen] { proj.Exprs = append(proj.Exprs, col) } newSchema = oldSchema[:oldLen] newSchema = newSchema.DeepCopy() for _, s := range newSchema { s.FromID = proj.id } proj.SetSchema(newSchema) addChild(proj, p) proj.correlated = p.IsCorrelated() return proj } return p }