// ResolveSelectList gets fields and result fields from selectFields and srcFields, // including field validity check and wildcard field processing. func ResolveSelectList(selectFields []*field.Field, srcFields []*field.ResultField) (*SelectList, error) { selectList := &SelectList{ Fields: make([]*field.Field, 0, len(selectFields)), ResultFields: make([]*field.ResultField, 0, len(selectFields)), AggFields: make(map[int]struct{}), FromFields: srcFields, } wildcardNum := 0 for _, v := range selectFields { // Check metioned field. names := expression.MentionedColumns(v.Expr) if len(names) == 0 { selectList.AddField(v, nil) continue } // Check wildcard field. name := names[0] table, ok, err := field.CheckWildcardField(name) if err != nil { return nil, err } if ok { // Check unqualified wildcard field number, // like `select *, * from t`. if table == "" { wildcardNum++ if wildcardNum > 1 { return nil, errors.Errorf("wildcard field exist more than once") } } selectList.updateFields(table, srcFields) continue } var result *field.ResultField if err = field.CheckAllFieldNames(names, srcFields, field.DefaultFieldFlag); err != nil { return nil, errors.Trace(err) } if _, ok := v.Expr.(*expression.Ident); ok { // Field is ident. if result, err = field.CloneFieldByName(name, srcFields, field.DefaultFieldFlag); err != nil { return nil, errors.Trace(err) } // Maybe alias name or only column name. if !expression.IsQualified(v.Name) { result.Name = v.Name } } else { // The field is not an ident, maybe binary expression, // like `select c1 + c2`, or `select c1 + 10`, etc. result = &field.ResultField{Name: v.Name} } selectList.AddField(v, result) } selectList.HiddenFieldOffset = len(selectList.Fields) selectList.resolveAggFields() if selectList.HiddenFieldOffset == 0 { return nil, errors.Errorf("invalid empty select fields") } return selectList, nil }
// Plan gets GroupByDefaultPlan. func (r *GroupByRset) Plan(ctx context.Context) (plan.Plan, error) { fields := r.SelectList.Fields resultfields := r.SelectList.ResultFields srcFields := r.Src.GetFields() r.SelectList.AggFields = GetAggFields(fields) aggFields := r.SelectList.AggFields for i, e := range r.By { if v, ok := e.(expression.Value); ok { var position int switch u := v.Val.(type) { case int64: position = int(u) case uint64: position = int(u) default: continue } if position < 1 || position > len(fields) { return nil, errors.Errorf("Unknown column '%d' in 'group statement'", position) } index := position - 1 if _, ok := aggFields[index]; ok { return nil, errors.Errorf("Can't group on '%s'", fields[index].Name) } // use Position expression for the associated field. r.By[i] = &expression.Position{N: position} } else { names := expression.MentionedColumns(e) for _, name := range names { if field.ContainFieldName(name, srcFields, field.DefaultFieldFlag) { // check whether column is qualified, like `select t.c1 c1, t.c2 from t group by t.c1, t.c2` // no need to check ambiguous field. if expression.IsQualified(name) { continue } // check ambiguous fields, like `select c1 as c2, c2 from t group by c2`. if err := field.CheckAmbiguousField(name, resultfields, field.DefaultFieldFlag); err == nil { continue } } // check reference to group function name indices := field.GetFieldIndex(name, fields[0:r.SelectList.HiddenFieldOffset], field.CheckFieldFlag) if len(indices) > 1 { // check ambiguous fields, like `select c1 as a, c2 as a from t group by a`, // notice that `select c2 as c2, c2 as c2 from t group by c2;` is valid. if r.HasAmbiguousField(indices, fields[0:r.SelectList.HiddenFieldOffset]) { return nil, errors.Errorf("Column '%s' in group statement is ambiguous", name) } } else if len(indices) == 1 { // check reference to aggregate function, like `select c1, count(c1) as b from t group by b + 1`. index := indices[0] if _, ok := aggFields[index]; ok { return nil, errors.Errorf("Reference '%s' not supported (reference to group function)", name) } } } // group by should be an expression, a qualified field name or a select field position, // but can not contain any aggregate function. if e := r.By[i]; expression.ContainAggregateFunc(e) { return nil, errors.Errorf("group by cannot contain aggregate function %s", e.String()) } } } return &plans.GroupByDefaultPlan{By: r.By, Src: r.Src, SelectList: r.SelectList}, nil }