package logicalplan
var hashedMatch = "hashed"
type Optimizer interface {
Optimize (plan *LogicalPlan ) *LogicalPlan
}
func DefaultOptimizers () []Optimizer {
return []Optimizer {
&PhysicalProjectionPushDown {
defaultProjections : []Expr {
Not (DynCol (hashedMatch )),
},
},
&FilterPushDown {},
&DistinctPushDown {},
&AggFuncPushDown {},
}
}
type PhysicalProjectionPushDown struct {
defaultProjections []Expr
}
func (p *PhysicalProjectionPushDown ) Optimize (plan *LogicalPlan ) *LogicalPlan {
p .optimize (plan , nil )
return plan
}
func (p *PhysicalProjectionPushDown ) optimize (plan *LogicalPlan , columnsUsedExprs []Expr ) {
switch {
case plan .SchemaScan != nil :
plan .SchemaScan .PhysicalProjection = append (p .defaultProjections , columnsUsedExprs ...)
case plan .TableScan != nil :
plan .TableScan .PhysicalProjection = append (p .defaultProjections , columnsUsedExprs ...)
case plan .Filter != nil :
p .defaultProjections = []Expr {}
columnsUsedExprs = append (columnsUsedExprs , plan .Filter .Expr .ColumnsUsedExprs ()...)
case plan .Distinct != nil :
columnsUsedExprs = []Expr {}
for _ , expr := range plan .Distinct .Exprs {
columnsUsedExprs = append (columnsUsedExprs , expr .ColumnsUsedExprs ()...)
}
case plan .Projection != nil :
columnsUsedExprs = []Expr {}
for _ , expr := range plan .Projection .Exprs {
columnsUsedExprs = append (columnsUsedExprs , expr .ColumnsUsedExprs ()...)
}
case plan .Aggregation != nil :
columnsUsedExprs = []Expr {}
for _ , expr := range plan .Aggregation .GroupExprs {
columnsUsedExprs = append (columnsUsedExprs , expr .ColumnsUsedExprs ()...)
}
for _ , expr := range plan .Aggregation .AggExprs {
columnsUsedExprs = append (columnsUsedExprs , expr .ColumnsUsedExprs ()...)
}
p .defaultProjections = []Expr {}
columnsUsedExprs = append (columnsUsedExprs , DynCol (hashedMatch ))
}
if plan .Input != nil {
p .optimize (plan .Input , columnsUsedExprs )
}
}
type FilterPushDown struct {}
func (p *FilterPushDown ) Optimize (plan *LogicalPlan ) *LogicalPlan {
p .optimize (plan , nil )
return plan
}
func (p *FilterPushDown ) optimize (plan *LogicalPlan , exprs []Expr ) {
switch {
case plan .SchemaScan != nil :
if len (exprs ) > 0 {
plan .SchemaScan .Filter = and (exprs )
}
case plan .TableScan != nil :
if len (exprs ) > 0 {
plan .TableScan .Filter = and (exprs )
}
case plan .Filter != nil :
exprs = append (exprs , plan .Filter .Expr )
}
if plan .Input != nil {
p .optimize (plan .Input , exprs )
}
}
type DistinctPushDown struct {}
func (p *DistinctPushDown ) Optimize (plan *LogicalPlan ) *LogicalPlan {
p .optimize (plan , nil )
return plan
}
func exprsEqual(a , b []Expr ) bool {
if len (a ) != len (b ) {
return false
}
for i , expr := range a {
if !expr .Equal (b [i ]) {
return false
}
}
return true
}
func (p *DistinctPushDown ) optimize (plan *LogicalPlan , distinctColumns []Expr ) {
switch {
case plan .TableScan != nil :
if len (distinctColumns ) > 0 {
plan .TableScan .Distinct = distinctColumns
}
case plan .Distinct != nil :
distinctColumns = append (distinctColumns , plan .Distinct .Exprs ...)
case plan .Projection != nil :
if !exprsEqual (distinctColumns , plan .Projection .Exprs ) {
distinctColumns = []Expr {}
}
default :
distinctColumns = []Expr {}
}
if plan .Input != nil {
p .optimize (plan .Input , distinctColumns )
}
}
type AggFuncPushDown struct {}
func (p *AggFuncPushDown ) Optimize (plan *LogicalPlan ) *LogicalPlan {
p .optimize (plan , nil )
return plan
}
func (p *AggFuncPushDown ) optimize (plan *LogicalPlan , filterExpr Expr ) {
switch {
case plan .TableScan != nil :
if filterExpr != nil {
plan .TableScan .Filter = filterExpr
}
case plan .Aggregation != nil :
if len (plan .Aggregation .GroupExprs ) == 0 && len (plan .Aggregation .AggExprs ) == 1 {
filterExpr = plan .Aggregation .AggExprs [0 ]
}
default :
filterExpr = nil
}
if plan .Input != nil {
p .optimize (plan .Input , filterExpr )
}
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .