Example #1
0
func (r *JoinRset) buildSourcePlan(ctx context.Context, t *TableSource) (plan.Plan, []*field.ResultField, error) {
	var (
		src interface{}
		tr  *TableRset
		err error
	)
	switch s := t.Source.(type) {
	case table.Ident:
		fullIdent := s.Full(ctx)
		tr, err = newTableRset(fullIdent.Schema.O, fullIdent.Name.O)
		if err != nil {
			return nil, nil, errors.Trace(err)
		}
		src = tr
		if t.Name == "" {
			qualifiedTableName := tr.Schema + "." + tr.Name
			if r.tableNames[qualifiedTableName] {
				return nil, nil, errors.Errorf("%s: duplicate name %s", r.String(), s)
			}
			r.tableNames[qualifiedTableName] = true
		}
	case stmt.Statement:
		src = s
	default:
		return nil, nil, errors.Errorf("invalid table source %T", t.Source)
	}

	var p plan.Plan
	switch x := src.(type) {
	case plan.Planner:
		if p, err = x.Plan(ctx); err != nil {
			return nil, nil, errors.Trace(err)
		}
	case plan.Plan:
		p = x
	default:
		return nil, nil, errors.Errorf("invalid table source %T, no Plan interface", t.Source)
	}

	var fields []*field.ResultField
	dupNames := make(map[string]struct{}, len(p.GetFields()))
	for _, nf := range p.GetFields() {
		f := nf.Clone()
		if t.Name != "" {
			f.TableName = t.Name
		}

		// duplicate column name in one table is not allowed.
		name := strings.ToLower(f.Name)
		if _, ok := dupNames[name]; ok {
			return nil, nil, errors.Errorf("Duplicate column name '%s'", name)
		}
		dupNames[name] = struct{}{}

		fields = append(fields, f)
	}

	return p, fields, nil
}
Example #2
0
func (r *JoinPlan) filterNode(ctx context.Context, expr expression.Expression, node plan.Plan) (plan.Plan, bool, error) {
	if node == nil {
		return r, false, nil
	}

	e2 := expr.Clone()
	return node.Filter(ctx, e2)
}
Example #3
0
File: join.go Project: maserg/tidb
func (r *JoinPlan) findMatchedRows(ctx context.Context, row *plan.Row, p plan.Plan, right bool) (err error) {
	r.cursor = 0
	r.matchedRows = nil
	p.Close()
	for {
		var cmpRow *plan.Row
		cmpRow, err = p.Next(ctx)
		if err != nil {
			return errors.Trace(err)
		}
		if cmpRow == nil {
			break
		}

		// Do append(s1, s2) safely. Sometime the s1 capability is larger than its real length, so
		// multi append may overwrite last valid data, e.g,
		//   s1 = make([]interface{}, 0, 1)
		//   s = append(s1, []interface{}{1})
		//   ss = append(ss, s)
		//   s = append(s1, []interface{}{2})
		//   ss = append(ss, s)
		// We will see that ss only contains 2.
		joined := make([]interface{}, 0, len(cmpRow.Data)+len(row.Data))
		if right {
			joined = append(append(joined, cmpRow.Data...), row.Data...)
		} else {
			joined = append(append(joined, row.Data...), cmpRow.Data...)
		}
		r.evalArgs[expression.ExprEvalIdentFunc] = func(name string) (interface{}, error) {
			return GetIdentValue(name, r.Fields, joined, field.DefaultFieldFlag)
		}
		var b bool
		b, err = expression.EvalBoolExpr(ctx, r.On, r.evalArgs)
		if err != nil {
			return errors.Trace(err)
		}
		if b {
			cmpRow.Data = joined
			keys := make([]*plan.RowKeyEntry, 0, len(row.RowKeys)+len(cmpRow.RowKeys))
			cmpRow.RowKeys = append(append(keys, row.RowKeys...), cmpRow.RowKeys...)
			r.matchedRows = append(r.matchedRows, cmpRow)
		}
	}
	if len(r.matchedRows) == 0 {
		if right {
			leftLen := len(r.Fields) - len(r.Right.GetFields())
			row.Data = append(make([]interface{}, leftLen), row.Data...)
		} else {
			rightLen := len(r.Fields) - len(r.Left.GetFields())
			row.Data = append(row.Data, make([]interface{}, rightLen)...)
		}
		r.matchedRows = append(r.matchedRows, row)
	}
	return nil
}
Example #4
0
func (r *JoinPlan) explainNode(w format.Formatter, node plan.Plan) {
	sel := !isTableOrIndex(node)
	if sel {
		w.Format("┌Iterate all rows of virtual table\n")
	}
	node.Explain(w)
	if sel {
		w.Format("└Output field names %v\n", field.RFQNames(node.GetFields()))
	}

}
Example #5
0
func (r *JoinPlan) findMatchedRows(ctx context.Context, row *plan.Row, right bool) (err error) {
	var p plan.Plan
	if right {
		p = r.Left
	} else {
		p = r.Right
	}
	r.cursor = 0
	r.matchedRows = nil
	p.Close()
	for {
		var cmpRow *plan.Row
		cmpRow, err = p.Next(ctx)
		if err != nil {
			return errors.Trace(err)
		}
		if cmpRow == nil {
			break
		}
		var joined []interface{}
		if right {
			joined = append(cmpRow.Data, row.Data...)
		} else {
			joined = append(row.Data, cmpRow.Data...)
		}
		r.evalArgs[expressions.ExprEvalIdentFunc] = func(name string) (interface{}, error) {
			return GetIdentValue(name, r.Fields, joined, field.DefaultFieldFlag)
		}
		var b bool
		b, err = expressions.EvalBoolExpr(ctx, r.On, r.evalArgs)
		if err != nil {
			return errors.Trace(err)
		}
		if b {
			cmpRow.Data = joined
			cmpRow.RowKeys = append(row.RowKeys, cmpRow.RowKeys...)
			r.matchedRows = append(r.matchedRows, cmpRow)
		}
	}
	if len(r.matchedRows) == 0 {
		if right {
			leftLen := len(r.Fields) - len(r.Right.GetFields())
			row.Data = append(make([]interface{}, leftLen), row.Data...)
		} else {
			rightLen := len(r.Fields) - len(r.Left.GetFields())
			row.Data = append(row.Data, make([]interface{}, rightLen)...)
		}
		r.matchedRows = append(r.matchedRows, row)
	}
	return nil
}
Example #6
0
func (v *explainVisitor) explain(p plan.Plan) {
	switch x := p.(type) {
	case *plan.TableScan:
		v.entries = append(v.entries, v.newEntryForTableScan(x))
	case *plan.IndexScan:
		v.entries = append(v.entries, v.newEntryForIndexScan(x))
	case *plan.Sort:
		v.sort = true
	}

	for _, c := range p.GetChildren() {
		v.explain(c)
	}
}
Example #7
0
File: update.go Project: botvs/tidb
func (s *UpdateStmt) plan(ctx context.Context) (plan.Plan, error) {
	var (
		r   plan.Plan
		err error
	)
	if s.TableRefs != nil {
		r, err = s.TableRefs.Plan(ctx)
		if err != nil {
			return nil, errors.Trace(err)
		}
	}
	if s.Where != nil {
		r, err = (&rsets.WhereRset{Expr: s.Where, Src: r}).Plan(ctx)
		if err != nil {
			return nil, errors.Trace(err)
		}
	}
	if s.Order != nil {
		s.Order.Src = r
		r, err = s.Order.Plan(ctx)
		if err != nil {
			return nil, errors.Trace(err)
		}
	}
	if s.Limit != nil {
		s.Limit.Src = r
		r, err = s.Limit.Plan(ctx)
		if err != nil {
			return nil, errors.Trace(err)
		}
	}

	visitor := rsets.NewFromIdentVisitor(r.GetFields(), rsets.UpdateClause)
	for i := range s.List {
		e, err := s.List[i].Expr.Accept(visitor)
		if err != nil {
			return nil, errors.Trace(err)
		}

		s.List[i].Expr = e
	}

	return r, nil
}
Example #8
0
func (e *ExplainExec) prepareExplainInfo(p plan.Plan, parent plan.Plan) error {
	for _, child := range p.GetChildren() {
		err := e.prepareExplainInfo(child, p)
		if err != nil {
			return errors.Trace(err)
		}
	}
	explain, err := json.MarshalIndent(p, "", "    ")
	if err != nil {
		return errors.Trace(err)
	}
	parentStr := ""
	if parent != nil {
		parentStr = parent.GetID()
	}
	row := &Row{
		Data: types.MakeDatums(p.GetID(), string(explain), parentStr),
	}
	e.rows = append(e.rows, row)
	return nil
}
Example #9
0
// Plan implements the plan.Planner interface.
// The whole phase for select is
// `from -> where -> lock -> group by -> having -> select fields -> distinct -> order by -> limit -> final`
func (s *SelectStmt) Plan(ctx context.Context) (plan.Plan, error) {
	var (
		r   plan.Plan
		err error
	)

	if s.From != nil {
		r, err = s.From.Plan(ctx)
		if err != nil {
			return nil, err
		}
	} else if s.Fields != nil {
		// Only evaluate fields values.
		fr := &rsets.SelectFromDualRset{Fields: s.Fields}
		r, err = fr.Plan(ctx)
		if err != nil {
			return nil, err
		}

	}

	// Put RowStackFromPlan here so that we can catch the origin from data after above FROM phase.
	r = &plans.RowStackFromPlan{Src: r}

	if w := s.Where; w != nil {
		r, err = (&rsets.WhereRset{Expr: w.Expr, Src: r}).Plan(ctx)
		if err != nil {
			return nil, err
		}
	}
	lock := s.Lock
	if variable.ShouldAutocommit(ctx) {
		// Locking of rows for update using SELECT FOR UPDATE only applies when autocommit
		// is disabled (either by beginning transaction with START TRANSACTION or by setting
		// autocommit to 0. If autocommit is enabled, the rows matching the specification are not locked.
		// See: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
		lock = coldef.SelectLockNone
	}
	r = &plans.SelectLockPlan{Src: r, Lock: lock}

	if err := s.checkOneColumn(ctx); err != nil {
		return nil, errors.Trace(err)
	}

	// Get select list for futher field values evaluation.
	selectList, err := plans.ResolveSelectList(s.Fields, r.GetFields())
	if err != nil {
		return nil, errors.Trace(err)
	}

	var groupBy []expression.Expression
	if s.GroupBy != nil {
		groupBy = s.GroupBy.By
	}

	if s.Having != nil {
		// `having` may contain aggregate functions, and we will add this to hidden fields.
		if err = s.Having.CheckAndUpdateSelectList(selectList, groupBy, r.GetFields()); err != nil {
			return nil, errors.Trace(err)
		}
	}

	if s.OrderBy != nil {
		// `order by` may contain aggregate functions, and we will add this to hidden fields.
		if err = s.OrderBy.CheckAndUpdateSelectList(selectList, r.GetFields()); err != nil {
			return nil, errors.Trace(err)
		}
	}

	switch {
	case !rsets.HasAggFields(selectList.Fields) && s.GroupBy == nil:
		// If no group by and no aggregate functions, we will use SelectFieldsPlan.
		if r, err = (&rsets.SelectFieldsRset{Src: r,
			SelectList: selectList,
		}).Plan(ctx); err != nil {
			return nil, err
		}

	default:
		if r, err = (&rsets.GroupByRset{By: groupBy,
			Src:        r,
			SelectList: selectList,
		}).Plan(ctx); err != nil {
			return nil, err
		}
	}

	if s := s.Having; s != nil {
		if r, err = (&rsets.HavingRset{
			Src:  r,
			Expr: s.Expr}).Plan(ctx); err != nil {
			return nil, err
		}
	}

	if s.Distinct {
		r = &plans.DistinctDefaultPlan{Src: r, SelectList: selectList}
	}

	if s := s.OrderBy; s != nil {
		if r, err = (&rsets.OrderByRset{By: s.By,
			Src:        r,
			SelectList: selectList,
		}).Plan(ctx); err != nil {
			return nil, err
		}
	}

	if s := s.Offset; s != nil {
		r = &plans.OffsetDefaultPlan{Count: s.Count, Src: r, Fields: r.GetFields()}
	}
	if s := s.Limit; s != nil {
		r = &plans.LimitDefaultPlan{Count: s.Count, Src: r, Fields: r.GetFields()}
	}
	r = &plans.SelectFinalPlan{Src: r, SelectList: selectList}
	return r, nil
}
Example #10
0
// Plan implements the plan.Planner interface.
func (s *UnionStmt) Plan(ctx context.Context) (plan.Plan, error) {
	srcs := make([]plan.Plan, 0, len(s.Selects))
	columnCount := 0
	for _, s := range s.Selects {
		p, err := s.Plan(ctx)
		if err != nil {
			return nil, err
		}
		if columnCount > 0 && columnCount != len(p.GetFields()) {
			return nil, errors.New("The used SELECT statements have a different number of columns")
		}
		columnCount = len(p.GetFields())

		srcs = append(srcs, p)
	}

	for i := len(s.Distincts) - 1; i >= 0; i-- {
		if s.Distincts[i] {
			// distinct overwrites all previous all
			// e.g, select * from t1 union all select * from t2 union distinct select * from t3.
			// The distinct will overwrite all for t1 and t2.
			i--
			for ; i >= 0; i-- {
				s.Distincts[i] = true
			}
			break
		}
	}

	fields := srcs[0].GetFields()
	selectList := &plans.SelectList{}
	selectList.ResultFields = make([]*field.ResultField, len(fields))
	selectList.HiddenFieldOffset = len(fields)

	// Union uses first select return column names and ignores table name.
	// We only care result name and type here.
	for i, f := range fields {
		nf := &field.ResultField{}
		nf.Name = f.Name
		nf.FieldType = f.FieldType
		selectList.ResultFields[i] = nf
	}

	var (
		r   plan.Plan
		err error
	)

	r = &plans.UnionPlan{Srcs: srcs, Distincts: s.Distincts, RFields: selectList.ResultFields}

	if s := s.OrderBy; s != nil {
		if r, err = (&rsets.OrderByRset{By: s.By,
			Src:        r,
			SelectList: selectList,
		}).Plan(ctx); err != nil {
			return nil, err
		}
	}

	if s := s.Offset; s != nil {
		r = &plans.OffsetDefaultPlan{Count: s.Count, Src: r, Fields: r.GetFields()}
	}
	if s := s.Limit; s != nil {
		r = &plans.LimitDefaultPlan{Count: s.Count, Src: r, Fields: r.GetFields()}
	}

	return r, nil
}