|
- // Copyright 2015 PingCAP, Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // See the License for the specific language governing permissions and
- // limitations under the License.
-
- package plan
-
- import (
- "math"
-
- "github.com/pingcap/tidb/ast"
- )
-
- // Plan is a description of an execution flow.
- // It is created from ast.Node first, then optimized by optimizer,
- // then used by executor to create a Cursor which executes the statement.
- type Plan interface {
- // Accept a visitor, implementation should call Visitor.Enter first,
- // then call children Accept methods, finally call Visitor.Leave.
- Accept(v Visitor) (out Plan, ok bool)
- // Fields returns the result fields of the plan.
- Fields() []*ast.ResultField
- // SetFields sets the results fields of the plan.
- SetFields(fields []*ast.ResultField)
- // The cost before returning fhe first row.
- StartupCost() float64
- // The cost after returning all the rows.
- TotalCost() float64
- // The expected row count.
- RowCount() float64
- // SetLimit is used to push limit to upstream to estimate the cost.
- SetLimit(limit float64)
- }
-
- // WithSrcPlan is a Plan has a source Plan.
- type WithSrcPlan interface {
- Plan
- Src() Plan
- SetSrc(src Plan)
- }
-
- // Visitor visits a Plan.
- type Visitor interface {
- // Enter is called before visit children.
- // The out plan should be of exactly the same type as the in plan.
- // if skipChildren is true, the children should not be visited.
- Enter(in Plan) (out Plan, skipChildren bool)
-
- // Leave is called after children has been visited, the out Plan can
- // be another type, this is different than ast.Visitor Leave, because
- // Plans only contain children plans as Plan interface type, so it is safe
- // to return a different type of plan.
- Leave(in Plan) (out Plan, ok bool)
- }
-
- // basePlan implements base Plan interface.
- // Should be used as embedded struct in Plan implementations.
- type basePlan struct {
- fields []*ast.ResultField
- startupCost float64
- totalCost float64
- rowCount float64
- limit float64
- }
-
- // StartupCost implements Plan StartupCost interface.
- func (p *basePlan) StartupCost() float64 {
- return p.startupCost
- }
-
- // TotalCost implements Plan TotalCost interface.
- func (p *basePlan) TotalCost() float64 {
- return p.totalCost
- }
-
- // RowCount implements Plan RowCount interface.
- func (p *basePlan) RowCount() float64 {
- if p.limit == 0 {
- return p.rowCount
- }
- return math.Min(p.rowCount, p.limit)
- }
-
- // SetLimit implements Plan SetLimit interface.
- func (p *basePlan) SetLimit(limit float64) {
- p.limit = limit
- }
-
- // Fields implements Plan Fields interface.
- func (p *basePlan) Fields() []*ast.ResultField {
- return p.fields
- }
-
- // SetFields implements Plan SetFields interface.
- func (p *basePlan) SetFields(fields []*ast.ResultField) {
- p.fields = fields
- }
-
- // srcPlan implements base PlanWithSrc interface.
- type planWithSrc struct {
- basePlan
- src Plan
- }
-
- // Src implements PlanWithSrc interface.
- func (p *planWithSrc) Src() Plan {
- return p.src
- }
-
- // SetSrc implements PlanWithSrc interface.
- func (p *planWithSrc) SetSrc(src Plan) {
- p.src = src
- }
-
- // SetLimit implements Plan interface.
- func (p *planWithSrc) SetLimit(limit float64) {
- p.limit = limit
- p.src.SetLimit(limit)
- }
|