示例#1
0
文件: having.go 项目: lovedboy/tidb
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
}
示例#2
0
文件: select_list.go 项目: gaohf/tidb
// 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
}
示例#3
0
文件: having.go 项目: lovedboy/tidb
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
}
示例#4
0
文件: plans.go 项目: szctop/tidb
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
}
示例#5
0
文件: groupby.go 项目: lovedboy/tidb
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)
}
示例#6
0
文件: helper.go 项目: H0bby/tidb
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
}
示例#7
0
文件: update.go 项目: botvs/tidb
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
}
示例#8
0
文件: orderby.go 项目: lovedboy/tidb
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)
}
示例#9
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
}
示例#10
0
文件: orderby.go 项目: gaohf/tidb
// 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
}