plan: let getPushedProp fit the plan with multi children. (#3589)

* plan: let getPushedProp fit the plan with multi children.
This commit is contained in:
Han Fei
2017-07-03 12:28:28 +08:00
committed by Lynn
parent 0f50d286bd
commit 4966dfbdeb
2 changed files with 28 additions and 47 deletions

View File

@ -50,10 +50,10 @@ func (p *requiredProp) enforceProperty(task task, ctx context.Context, allocator
return sort.attach2Task(task)
}
// getPushedProp will check if this sort property can be pushed or not.
// getChildrenPossibleProps will check if this sort property can be pushed or not.
// When a sort column will be replaced by scalar function, we refuse it.
// When a sort column will be replaced by a constant, we just remove it.
func (p *Projection) getPushedProp(prop *requiredProp) []*requiredProp {
func (p *Projection) getChildrenPossibleProps(prop *requiredProp) [][]*requiredProp {
newProp := &requiredProp{taskTp: rootTaskType}
newCols := make([]*expression.Column, 0, len(prop.cols))
for _, col := range prop.cols {
@ -70,7 +70,7 @@ func (p *Projection) getPushedProp(prop *requiredProp) []*requiredProp {
}
newProp.cols = newCols
newProp.desc = prop.desc
return []*requiredProp{newProp}
return [][]*requiredProp{{newProp}}
}
// joinKeysMatchIndex checks if all keys match columns in index.
@ -503,18 +503,22 @@ func (p *baseLogicalPlan) convert2NewPhysicalPlan(prop *requiredProp) (task, err
}
func (p *baseLogicalPlan) getBestTask(bestTask task, prop *requiredProp, pp PhysicalPlan, enforced bool) (task, error) {
var newProps []*requiredProp
var newProps [][]*requiredProp
if enforced {
newProps = pp.getPushedProp(&requiredProp{taskTp: rootTaskType})
newProps = pp.getChildrenPossibleProps(&requiredProp{taskTp: rootTaskType})
} else {
newProps = pp.getPushedProp(prop)
newProps = pp.getChildrenPossibleProps(prop)
}
for _, newProp := range newProps {
resultTask, err := p.basePlan.children[0].(LogicalPlan).convert2NewPhysicalPlan(newProp)
if err != nil {
return nil, errors.Trace(err)
tasks := make([]task, 0, len(p.basePlan.children))
for i, child := range p.basePlan.children {
childTask, err := child.(LogicalPlan).convert2NewPhysicalPlan(newProp[i])
if err != nil {
return nil, errors.Trace(err)
}
tasks = append(tasks, childTask)
}
resultTask = pp.attach2Task(resultTask)
resultTask := pp.attach2Task(tasks...)
if enforced {
resultTask = prop.enforceProperty(resultTask, p.basePlan.ctx, p.basePlan.allocator)
}
@ -841,33 +845,6 @@ func (p *DataSource) convertToTableScan(prop *requiredProp) (task task, err erro
return task, nil
}
func (p *Union) convert2NewPhysicalPlan(prop *requiredProp) (task, error) {
t, err := p.getTask(prop)
if err != nil {
return nil, errors.Trace(err)
}
if t != nil {
return t, nil
}
if prop.taskTp != rootTaskType {
// Union can only return rootTask.
return invalidTask, p.storeTask(prop, invalidTask)
}
// Union is a sort blocker. We can only enforce it.
tasks := make([]task, 0, len(p.children))
for _, child := range p.children {
t, err = child.(LogicalPlan).convert2NewPhysicalPlan(&requiredProp{taskTp: rootTaskType})
if err != nil {
return nil, errors.Trace(err)
}
tasks = append(tasks, t)
}
t = p.attach2Task(tasks...)
t = prop.enforceProperty(t, p.ctx, p.allocator)
return t, p.storeTask(prop, t)
}
func (ts *PhysicalTableScan) addPushedDownSelection(copTask *copTask) {
// Add filter condition to table plan now.
if len(ts.filterCondition) > 0 {
@ -936,18 +913,22 @@ func (p *baseLogicalPlan) generatePhysicalPlans() []PhysicalPlan {
return []PhysicalPlan{np}
}
func (p *basePhysicalPlan) getPushedProp(prop *requiredProp) []*requiredProp {
func (p *basePhysicalPlan) getChildrenPossibleProps(prop *requiredProp) [][]*requiredProp {
// By default, physicalPlan can always match the orders.
return []*requiredProp{prop}
props := make([]*requiredProp, 0, len(p.basePlan.children))
for range p.basePlan.children {
props = append(props, prop)
}
return [][]*requiredProp{props}
}
func (p *Limit) getPushedProp(prop *requiredProp) []*requiredProp {
func (p *Limit) getChildrenPossibleProps(prop *requiredProp) [][]*requiredProp {
if !prop.isEmpty() {
return nil
}
props := make([]*requiredProp, 0, len(wholeTaskTypes))
props := make([][]*requiredProp, 0, len(wholeTaskTypes))
for _, tp := range wholeTaskTypes {
props = append(props, &requiredProp{taskTp: tp})
props = append(props, []*requiredProp{{taskTp: tp}})
}
return props
}
@ -963,13 +944,13 @@ func (p *LogicalAggregation) generatePhysicalPlans() []PhysicalPlan {
return []PhysicalPlan{ha}
}
func (p *PhysicalAggregation) getPushedProp(prop *requiredProp) []*requiredProp {
func (p *PhysicalAggregation) getChildrenPossibleProps(prop *requiredProp) [][]*requiredProp {
if !prop.isEmpty() {
return nil
}
props := make([]*requiredProp, 0, len(wholeTaskTypes))
props := make([][]*requiredProp, 0, len(wholeTaskTypes))
for _, tp := range wholeTaskTypes {
props = append(props, &requiredProp{taskTp: tp})
props = append(props, []*requiredProp{{taskTp: tp}})
}
return props
}

View File

@ -262,8 +262,8 @@ type PhysicalPlan interface {
// ToPB converts physical plan to tipb executor.
ToPB(ctx context.Context) (*tipb.Executor, error)
// getPushedProp tries to push the required property to its child and get the result property.
getPushedProp(prop *requiredProp) []*requiredProp
// getChildrenPossibleProps tries to push the required properties to its children and return all the possible properties.
getChildrenPossibleProps(prop *requiredProp) [][]*requiredProp
}
type baseLogicalPlan struct {