// 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.(expressions.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 = &expressions.Position{N: position} } } else { colNames := expressions.MentionedColumns(e) if err := field.CheckAllFieldNames(colNames, fields, field.CheckFieldFlag); err != nil { return nil, errors.Trace(err) } } 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 }
// 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{}), } wildcardNum := 0 for _, v := range selectFields { if err := expressions.CheckOneColumn(v.Expr); err != nil { return nil, errors.Trace(err) } // Check metioned field. names := expressions.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.(*expressions.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 !expressions.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 }
func (*testResultFieldSuite) TestMain(c *C) { col := column.Col{ ColumnInfo: model.ColumnInfo{ FieldType: *types.NewFieldType(mysql.TypeLong), Name: model.NewCIStr("c1"), }, } col.Flag |= mysql.UnsignedFlag r := &field.ResultField{ Col: col, Name: "c1", OrgTableName: "t1", } c.Assert(r.String(), Equals, "c1") r.TableName = "a" c.Assert(r.String(), Equals, "a.c1") r.DBName = "test" c.Assert(r.String(), Equals, "test.a.c1") cr := r.Clone() c.Assert(r.String(), Equals, cr.String()) col1 := column.Col{ ColumnInfo: model.ColumnInfo{ FieldType: *types.NewFieldType(mysql.TypeLong), Name: model.NewCIStr("c2"), }, } col1.Flag |= mysql.UnsignedFlag r1 := &field.ResultField{ Col: col1, Name: "c2", TableName: "a", OrgTableName: "t1", DBName: "test", } rs := []*field.ResultField{r, r1} ns := field.RFQNames(rs) c.Assert(ns, HasLen, 2) c.Assert(ns[0], Equals, "\"c1\"") c.Assert(ns[1], Equals, "\"c2\"") col2 := column.Col{ ColumnInfo: model.ColumnInfo{ FieldType: *types.NewFieldType(mysql.TypeVarchar), Name: model.NewCIStr("c3"), }, } col2.Flag |= mysql.UnsignedFlag col3 := column.Col{ ColumnInfo: model.ColumnInfo{ FieldType: *types.NewFieldType(mysql.TypeBlob), Name: model.NewCIStr("c4"), }, } col3.Flag |= mysql.UnsignedFlag cols := []*column.Col{&col, &col1, &col2, &col3} rs = field.ColsToResultFields(cols, "t") c.Assert(rs, HasLen, 4) c.Assert(rs[2].Tp, Equals, mysql.TypeVarString) c.Assert(rs[3].Tp, Equals, mysql.TypeBlob) // For CheckAmbiguousField err := field.CheckAmbiguousField("c1", rs, field.OrgFieldNameFlag) c.Assert(err, IsNil) col4 := column.Col{ ColumnInfo: model.ColumnInfo{ FieldType: *types.NewFieldType(mysql.TypeVarchar), Name: model.NewCIStr("c2"), }, } r2 := &field.ResultField{ Col: col4, Name: "c22", TableName: "b", OrgTableName: "t2", DBName: "test", } rs = []*field.ResultField{r, r1, r2} // r1 and r2 are ambiguous: same column name but different table names err = field.CheckAmbiguousField("c2", rs, field.OrgFieldNameFlag) c.Assert(err, NotNil) // r1 and r2 with different alias name err = field.CheckAmbiguousField("c2", rs, field.FieldNameFlag) c.Assert(err, IsNil) // For CloneFieldByName _, err = field.CloneFieldByName("cx", rs, field.OrgFieldNameFlag) c.Assert(err, NotNil) _, err = field.CloneFieldByName("c2", rs, field.OrgFieldNameFlag) c.Assert(err, IsNil) // For check all fields name names := []string{"cx"} err = field.CheckAllFieldNames(names, rs, field.OrgFieldNameFlag) c.Assert(err, NotNil) names = []string{"c1"} err = field.CheckAllFieldNames(names, rs, field.OrgFieldNameFlag) c.Assert(err, IsNil) // For ContainAllFieldNames names = []string{"cx", "c2"} b := field.ContainAllFieldNames(names, rs, field.OrgFieldNameFlag) c.Assert(b, IsFalse) names = []string{"c2", "c1"} b = field.ContainAllFieldNames(names, rs, field.OrgFieldNameFlag) c.Assert(b, IsTrue) // For GetFieldIndex f1 := &field.Field{ Expr: &expression.Ident{CIStr: model.NewCIStr("c1")}, AsName: "a", } f2 := &field.Field{ Expr: &expression.Ident{CIStr: model.NewCIStr("c2")}, AsName: "a", } fs := []*field.Field{f1, f2} idxs := field.GetFieldIndex("c1", fs, field.OrgFieldNameFlag) c.Assert(idxs, HasLen, 1) idxs = field.GetFieldIndex("a", fs, field.FieldNameFlag) c.Assert(idxs, HasLen, 2) }
// 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) } // 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 }