func logicalOptimize(flag uint64, logic LogicalPlan) (LogicalPlan, error) {
var err error
for i, rule := range optRuleList {
// The order of flags is same as the order of optRule in the list.
// We use a bitmask to record which opt rules should be used. If the i-th bit is 1, it means we should
// apply i-th optimizing rule.
if flag&(1<<uint(i)) == 0 {
continue
}
logic, err = rule.optimize(logic)
if err != nil {
return nil, errors.Trace(err)
}
}
return logic, errors.Trace(err)
}
func (p *LogicalProjection) PruneColumns(parentUsedCols []*expression.Column) {
child := p.children[0]
used := getUsedList(parentUsedCols, p.schema)
for i := len(used) - 1; i >= 0; i-- {
if !used[i] && !exprHasSetVar(p.Exprs[i]) {
p.schema.Columns = append(p.schema.Columns[:i], p.schema.Columns[i+1:]...)
p.Exprs = append(p.Exprs[:i], p.Exprs[i+1:]...)
}
}
selfUsedCols := make([]*expression.Column, 0, len(p.Exprs))
selfUsedCols = expression.ExtractColumnsFromExpressions(selfUsedCols, p.Exprs, nil)
child.PruneColumns(selfUsedCols)
}
// PruneColumns implements LogicalPlan interface.
func (ds *DataSource) PruneColumns(parentUsedCols []*expression.Column) {
used := getUsedList(parentUsedCols, ds.schema)
for i := len(used) - 1; i >= 0; i-- {
if !used[i] {
ds.schema.Columns = append(ds.schema.Columns[:i], ds.schema.Columns[i+1:]...)
ds.Columns = append(ds.Columns[:i], ds.Columns[i+1:]...)
}
}
for k, cols := range ds.schema.TblID2Handle {
if ds.schema.ColumnIndex(cols[0]) == -1 {
delete(ds.schema.TblID2Handle, k)
}
}
}
// eliminate eliminates the redundant projection in a logical plan.
func (pe *projectionEliminater) eliminate(p LogicalPlan, replace map[string]*expression.Column, canEliminate bool) LogicalPlan {
proj, isProj := p.(*LogicalProjection)
childFlag := canEliminate
if _, isUnion := p.(*LogicalUnionAll); isUnion {
childFlag = false
} else if _, isAgg := p.(*LogicalAggregation); isAgg || isProj {
childFlag = true
}
for i, child := range p.Children() {
p.Children()[i] = pe.eliminate(child, replace, childFlag)
}
switch x := p.(type) {
case *LogicalJoin:
x.schema = buildLogicalJoinSchema(x.JoinType, x)
case *LogicalApply:
x.schema = buildLogicalJoinSchema(x.JoinType, x)
default:
for _, dst := range p.Schema().Columns {
resolveColumnAndReplace(dst, replace)
}
}
p.replaceExprColumns(replace)
if !(isProj && canEliminate && canProjectionBeEliminatedLoose(proj)) {
return p
}
exprs := proj.Exprs
for i, col := range proj.Schema().Columns {
replace[string(col.HashCode())] = exprs[i].(*expression.Column)
}
return p.Children()[0]
}