func (v *havingVisitor) checkIdentInGroupBy(i *expression.Ident) (*expression.Ident, bool, error) { for _, by := range v.groupBy { e := castIdent(by) if e == nil { // group by must be a identifier too continue } if !field.CheckFieldsEqual(e.L, i.L) { // not same, continue continue } // if group by references select list or having is qualified identifier, // no other check. if e.ReferScope == expression.IdentReferSelectList || field.IsQualifiedName(i.L) { i.ReferScope = e.ReferScope i.ReferIndex = e.ReferIndex return i, true, nil } // having is unqualified name, e.g, select * from t1, t2 group by t1.c having c. // both t1 and t2 have column c, we must check ambiguous here. idx := field.GetResultFieldIndex(i.L, v.selectList.FromFields) if len(idx) > 1 { return i, false, errors.Errorf("Column '%s' in having clause is ambiguous", i) } i.ReferScope = e.ReferScope i.ReferIndex = e.ReferIndex return i, true, nil } return i, false, nil }
// UpdateAggFields adds aggregate function resultfield to select result field list. func (s *SelectList) UpdateAggFields(expr expression.Expression, tableFields []*field.ResultField) (expression.Expression, error) { // For aggregate function, the name can be in table or select list. names := expression.MentionedColumns(expr) for _, name := range names { if field.ContainFieldName(name, tableFields, field.DefaultFieldFlag) { continue } if field.ContainFieldName(name, s.ResultFields, field.DefaultFieldFlag) { continue } return nil, errors.Errorf("Unknown column '%s'", name) } // We must add aggregate function to hidden select list // and use a position expression to fetch its value later. exprName := expr.String() idx := field.GetResultFieldIndex(exprName, s.ResultFields, field.CheckFieldFlag) if len(idx) == 0 { f := &field.Field{Expr: expr} resultField := &field.ResultField{Name: exprName} s.AddField(f, resultField) return &expression.Position{N: len(s.Fields), Name: exprName}, nil } // select list has this field, use it directly. return &expression.Position{N: idx[0] + 1, Name: exprName}, nil }
func (v *havingVisitor) visitIdentInAggregate(i *expression.Ident) (expression.Expression, error) { // if we are visiting aggregate function arguments, the identifier first checks in from table, // then in select list, and outer query finally. // find this identifier in FROM. idx := field.GetResultFieldIndex(i.L, v.selectList.FromFields) if len(idx) > 0 { i.ReferScope = expression.IdentReferFromTable i.ReferIndex = idx[0] return i, nil } // check in select list. index, err := checkIdentAmbiguous(i, v.selectList, HavingClause) if err != nil { return i, errors.Trace(err) } if index >= 0 { // find in select list i.ReferScope = expression.IdentReferSelectList i.ReferIndex = index return i, nil } // TODO: check in out query // TODO: return unknown field error, but now just return directly. // Because this may reference outer query. return i, nil }
func getIdentValue(name string, fields []*field.ResultField, row []interface{}, flag uint32) (interface{}, error) { indices := field.GetResultFieldIndex(name, fields, flag) if len(indices) == 0 { return nil, errors.Errorf("unknown field %s", name) } index := indices[0] return row[index], nil }
func (v *groupByVisitor) VisitIdent(i *expression.Ident) (expression.Expression, error) { // Group by ambiguous rule: // select c1 as a, c2 as a from t group by a is ambiguous // select c1 as a, c2 as a from t group by a + 1 is ambiguous // select c1 as c2, c2 from t group by c2 is ambiguous // select c1 as c2, c2 from t group by c2 + 1 is not ambiguous var ( index int err error ) if v.rootIdent == i { // The group by is an identifier, we must check it first. index, err = checkIdentAmbiguous(i, v.selectList, GroupByClause) if err != nil { return nil, errors.Trace(err) } } // first find this identifier in FROM. idx := field.GetResultFieldIndex(i.L, v.selectList.FromFields) if len(idx) > 0 { i.ReferScope = expression.IdentReferFromTable i.ReferIndex = idx[0] return i, nil } if v.rootIdent != i { // This identifier is the part of the group by, check ambiguous here. index, err = checkIdentAmbiguous(i, v.selectList, GroupByClause) if err != nil { return nil, errors.Trace(err) } } // try to find in select list, we have got index using checkIdent before. if index >= 0 { // group by can not reference aggregate fields if _, ok := v.selectList.AggFields[index]; ok { return nil, errors.Errorf("Reference '%s' not supported (reference to group function)", i) } // find in select list i.ReferScope = expression.IdentReferSelectList i.ReferIndex = index return i, nil } // TODO: check in out query return i, errors.Errorf("Unknown column '%s' in 'group statement'", i) }
func (v *fromIdentVisitor) VisitIdent(i *expression.Ident) (expression.Expression, error) { idx := field.GetResultFieldIndex(i.L, v.fromFields, field.DefaultFieldFlag) if len(idx) == 1 { i.ReferScope = expression.IdentReferFromTable i.ReferIndex = idx[0] return i, nil } else if len(idx) > 1 { return nil, errors.Errorf("Column '%s' in %s is ambiguous", i, v.clause) } if v.clause == onClause { // on clause can't check outer query. return nil, errors.Errorf("Unknown column '%s' in '%s'", i, v.clause) } // TODO: check in outer query return i, nil }
func getUpdateColumns(assignList []*expression.Assignment, fields []*field.ResultField) (map[int]*expression.Assignment, error) { m := make(map[int]*expression.Assignment, len(assignList)) for _, v := range assignList { name := v.ColName if len(v.TableName) > 0 { name = fmt.Sprintf("%s.%s", v.TableName, v.ColName) } // use result fields to check assign list, otherwise use origin table columns idx := field.GetResultFieldIndex(name, fields) if n := len(idx); n > 1 { return nil, errors.Errorf("ambiguous field %s", name) } else if n == 0 { return nil, errors.Errorf("unknown field %s", name) } m[idx[0]] = v } return m, nil }
func (v *orderByVisitor) VisitIdent(i *expression.Ident) (expression.Expression, error) { // Order by ambiguous rule: // select c1 as a, c2 as a from t order by a is ambiguous // select c1 as a, c2 as a from t order by a + 1 is ambiguous // select c1 as c2, c2 from t order by c2 is ambiguous // select c1 as c2, c2 from t order by c2 + 1 is not ambiguous // Order by identifier reference check // select c1 as c2 from t order by c2, c2 in order by references c1 in select field. // select c1 as c2 from t order by c2 + 1, c2 in order by c2 + 1 references t.c2 in from table. // select c1 as c2 from t order by sum(c2), c2 in order by sum(c2) references t.c2 in from table. // select c1 as c2 from t order by sum(1) + c2, c2 in order by sum(1) + c2 references t.c2 in from table. // select c1 as a from t order by a, a references c1 in select field. // select c1 as a from t order by sum(a), a in order by sum(a) references c1 in select field. // TODO: unify VisitIdent for group by and order by visitor, they are little different. var ( index int err error ) if v.rootIdent == i { // The order by is an identifier, we must check it first. index, err = checkIdentAmbiguous(i, v.selectList, OrderByClause) if err != nil { return nil, errors.Trace(err) } if index >= 0 { // identifier references a select field. use it directly. // e,g. select c1 as c2 from t order by c2, here c2 references c1. i.ReferScope = expression.IdentReferSelectList i.ReferIndex = index return i, nil } } // find this identifier in FROM. idx := field.GetResultFieldIndex(i.L, v.selectList.FromFields) if len(idx) > 0 { i.ReferScope = expression.IdentReferFromTable i.ReferIndex = idx[0] return i, nil } if v.rootIdent != i { // This identifier is the part of the order by, check ambiguous here. index, err = checkIdentAmbiguous(i, v.selectList, OrderByClause) if err != nil { return nil, errors.Trace(err) } } // try to find in select list, we have got index using checkIdentAmbiguous before. if index >= 0 { // find in select list i.ReferScope = expression.IdentReferSelectList i.ReferIndex = index return i, nil } // TODO: check in out query return i, errors.Errorf("Unknown column '%s' in 'order clause'", i) }
// 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 for _, name := range names { idx := field.GetResultFieldIndex(name, srcFields, field.DefaultFieldFlag) if len(idx) > 1 { return nil, errors.Errorf("ambiguous field %s", name) } // TODO: must check in outer query too. if len(idx) == 0 { return nil, errors.Errorf("unknown field %s", name) } } 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) } // Use alias name if len(v.AsName) > 0 { result.Name = v.AsName } else { // use field identifier name directly, but not contain qualified name. // e.g, select t.c will only return c as the column name. s := v.Expr.String() n := strings.LastIndexByte(s, '.') if n == -1 { result.Name = s } else { result.Name = s[n+1:] } } } 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 get SrcPlan/OrderByDefaultPlan. // If src is NullPlan or order by fields are empty, then gets SrcPlan. // Default gets OrderByDefaultPlan. func (r *OrderByRset) Plan(ctx context.Context) (plan.Plan, error) { if _, ok := r.Src.(*plans.NullPlan); ok { return r.Src, nil } var ( by []expression.Expression ascs []bool ) fields := r.Src.GetFields() for i := range r.By { e := r.By[i].Expr if v, ok := e.(expression.Value); ok { var ( position int isPosition = true ) switch u := v.Val.(type) { case int64: position = int(u) case uint64: position = int(u) default: isPosition = false // only const value } if isPosition { if position < 1 || position > len(fields) { return nil, errors.Errorf("Unknown column '%d' in 'order clause'", position) } // use Position expression for the associated field. r.By[i].Expr = &expression.Position{N: position} } } else { // Don't check ambiguous here, only check field exists or not. // TODO: use visitor to refactor. colNames := expression.MentionedColumns(e) for _, name := range colNames { if idx := field.GetResultFieldIndex(name, r.SelectList.ResultFields, field.DefaultFieldFlag); len(idx) == 0 { // find in from if idx = field.GetResultFieldIndex(name, r.SelectList.FromFields, field.DefaultFieldFlag); len(idx) == 0 { return nil, errors.Errorf("unknown field %s", name) } } } } by = append(by, r.By[i].Expr) ascs = append(ascs, r.By[i].Asc) } // if no order by key, use src plan instead. if len(by) == 0 { return r.Src, nil } return &plans.OrderByDefaultPlan{By: by, Ascs: ascs, Src: r.Src, SelectList: r.SelectList}, nil }