コード例 #1
0
ファイル: select_list.go プロジェクト: gaohf/tidb
// CloneHiddenField checks and clones field and result field from table fields,
// and adds them to hidden field of select list.
func (s *SelectList) CloneHiddenField(name string, tableFields []*field.ResultField) bool {
	// Check and add hidden field.
	if field.ContainFieldName(name, tableFields, field.CheckFieldFlag) {
		resultField, _ := field.CloneFieldByName(name, tableFields, field.CheckFieldFlag)
		f := &field.Field{
			Expr: &expression.Ident{
				CIStr: resultField.ColumnInfo.Name,
			},
		}
		s.AddField(f, resultField)
		return true
	}

	return false
}
コード例 #2
0
ファイル: select_list.go プロジェクト: no2key/tidb
// 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
}
コード例 #3
0
ファイル: select_list.go プロジェクト: gaohf/tidb
// 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
}
コード例 #4
0
ファイル: result_field_test.go プロジェクト: H0bby/tidb
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)

}
コード例 #5
0
ファイル: result_field_test.go プロジェクト: lovedboy/tidb
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)

	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}

	// For CloneFieldByName
	_, err := field.CloneFieldByName("cx", rs)
	c.Assert(err, NotNil)
	_, err = field.CloneFieldByName("c2", rs)
	c.Assert(err, IsNil)

	// For ContainAllFieldNames
	names := []string{"cx", "c2"}
	b := field.ContainAllFieldNames(names, rs)
	c.Assert(b, IsFalse)
	names = []string{"c2", "c1"}
	b = field.ContainAllFieldNames(names, rs)
	c.Assert(b, IsTrue)
}