Skip to content

Commit

Permalink
planner: classify logical selection into a separate file for later pk…
Browse files Browse the repository at this point in the history
  • Loading branch information
AilinKid authored Jul 4, 2024
1 parent 6421f86 commit acbf74a
Show file tree
Hide file tree
Showing 16 changed files with 308 additions and 240 deletions.
1 change: 1 addition & 0 deletions pkg/planner/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ go_library(
"logical_partition_union_all.go",
"logical_plan_builder.go",
"logical_plans.go",
"logical_selection.go",
"logical_sort.go",
"logical_table_dual.go",
"logical_table_scan.go",
Expand Down
10 changes: 1 addition & 9 deletions pkg/planner/core/exhaust_physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -3503,8 +3503,7 @@ func getHashAggs(lp base.LogicalPlan, prop *property.PhysicalProperty) []base.Ph
return hashAggs
}

// ExhaustPhysicalPlans implements LogicalPlan interface.
func (p *LogicalSelection) ExhaustPhysicalPlans(prop *property.PhysicalProperty) ([]base.PhysicalPlan, bool, error) {
func exhaustPhysicalPlans4LogicalSelection(p *LogicalSelection, prop *property.PhysicalProperty) ([]base.PhysicalPlan, bool, error) {
newProps := make([]*property.PhysicalProperty, 0, 2)
childProp := prop.CloneEssentialFields()
newProps = append(newProps, childProp)
Expand All @@ -3527,13 +3526,6 @@ func (p *LogicalSelection) ExhaustPhysicalPlans(prop *property.PhysicalProperty)
return ret, true, nil
}

// utility function to check whether we can push down Selection to TiKV or TiFlash
func (p *LogicalSelection) canPushDown(storeTp kv.StoreType) bool {
return !expression.ContainVirtualColumn(p.Conditions) &&
p.CanPushToCop(storeTp) &&
expression.CanExprsPushDown(GetPushDownCtx(p.SCtx()), p.Conditions, storeTp)
}

func getLimitPhysicalPlans(p *LogicalLimit, prop *property.PhysicalProperty) ([]base.PhysicalPlan, bool, error) {
if !prop.IsSortItemEmpty() {
return nil, true, nil
Expand Down
5 changes: 0 additions & 5 deletions pkg/planner/core/explain.go
Original file line number Diff line number Diff line change
Expand Up @@ -910,11 +910,6 @@ func (p *LogicalProjection) ExplainInfo() string {
return expression.ExplainExpressionList(p.SCtx().GetExprCtx().GetEvalCtx(), p.Exprs, p.Schema())
}

// ExplainInfo implements Plan interface.
func (p *LogicalSelection) ExplainInfo() string {
return string(expression.SortedExplainExpressionList(p.SCtx().GetExprCtx().GetEvalCtx(), p.Conditions))
}

// ExplainInfo implements Plan interface.
func (p *LogicalApply) ExplainInfo() string {
return p.LogicalJoin.ExplainInfo()
Expand Down
27 changes: 0 additions & 27 deletions pkg/planner/core/hashcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
package core

import (
"bytes"
"slices"

"github.com/pingcap/tidb/pkg/planner/util"
"github.com/pingcap/tidb/pkg/util/plancodec"
)
Expand All @@ -38,27 +35,3 @@ func (p *LogicalProjection) HashCode() []byte {
}
return result
}

// HashCode implements LogicalPlan interface.
func (p *LogicalSelection) HashCode() []byte {
// PlanType + SelectOffset + ConditionNum + [Conditions]
// Conditions are commonly `ScalarFunction`s, whose hashcode usually has a
// length larger than 20, so we pre-alloc 25 bytes for each expr's hashcode.
result := make([]byte, 0, 12+len(p.Conditions)*25)
result = util.EncodeIntAsUint32(result, plancodec.TypeStringToPhysicalID(p.TP()))
result = util.EncodeIntAsUint32(result, p.QueryBlockOffset())
result = util.EncodeIntAsUint32(result, len(p.Conditions))

condHashCodes := make([][]byte, len(p.Conditions))
for i, expr := range p.Conditions {
condHashCodes[i] = expr.HashCode()
}
// Sort the conditions, so `a > 1 and a < 100` can equal to `a < 100 and a > 1`.
slices.SortFunc(condHashCodes, func(i, j []byte) int { return bytes.Compare(i, j) })

for _, condHashCode := range condHashCodes {
result = util.EncodeIntAsUint32(result, len(condHashCode))
result = append(result, condHashCode...)
}
return result
}
6 changes: 0 additions & 6 deletions pkg/planner/core/logical_initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,6 @@ func (la LogicalApply) Init(ctx base.PlanContext, offset int) *LogicalApply {
return &la
}

// Init initializes LogicalSelection.
func (p LogicalSelection) Init(ctx base.PlanContext, qbOffset int) *LogicalSelection {
p.BaseLogicalPlan = logicalop.NewBaseLogicalPlan(ctx, plancodec.TypeSel, &p, qbOffset)
return &p
}

// Init initializes LogicalUnionScan.
func (p LogicalUnionScan) Init(ctx base.PlanContext, qbOffset int) *LogicalUnionScan {
p.BaseLogicalPlan = logicalop.NewBaseLogicalPlan(ctx, plancodec.TypeUnionScan, &p, qbOffset)
Expand Down
60 changes: 0 additions & 60 deletions pkg/planner/core/logical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -914,16 +914,6 @@ func (p *LogicalProjection) GetUsedCols() (usedCols []*expression.Column) {
return usedCols
}

// LogicalSelection represents a where or having predicate.
type LogicalSelection struct {
logicalop.BaseLogicalPlan

// Originally the WHERE or ON condition is parsed into a single expression,
// but after we converted to CNF(Conjunctive normal form), it can be
// split into a list of AND conditions.
Conditions []expression.Expression
}

func extractNotNullFromConds(conditions []expression.Expression, p base.LogicalPlan) intset.FastIntSet {
// extract the column NOT NULL rejection characteristic from selection condition.
// CNF considered only, DNF doesn't have its meanings (cause that condition's eval may don't take effect)
Expand Down Expand Up @@ -1019,56 +1009,6 @@ func extractEquivalenceCols(conditions []expression.Expression, sctx base.PlanCo
return equivUniqueIDs
}

// ExtractFD implements the LogicalPlan interface.
func (p *LogicalSelection) ExtractFD() *fd.FDSet {
// basically extract the children's fdSet.
fds := p.BaseLogicalPlan.ExtractFD()
// collect the output columns' unique ID.
outputColsUniqueIDs := intset.NewFastIntSet()
notnullColsUniqueIDs := intset.NewFastIntSet()
// eg: select t2.a, count(t2.b) from t1 join t2 using (a) where t1.a = 1
// join's schema will miss t2.a while join.full schema has. since selection
// itself doesn't contain schema, extracting schema should tell them apart.
var columns []*expression.Column
if join, ok := p.Children()[0].(*LogicalJoin); ok && join.FullSchema != nil {
columns = join.FullSchema.Columns
} else {
columns = p.Schema().Columns
}
for _, one := range columns {
outputColsUniqueIDs.Insert(int(one.UniqueID))
}

// extract the not null attributes from selection conditions.
notnullColsUniqueIDs.UnionWith(extractNotNullFromConds(p.Conditions, p))

// extract the constant cols from selection conditions.
constUniqueIDs := extractConstantCols(p.Conditions, p.SCtx(), fds)

// extract equivalence cols.
equivUniqueIDs := extractEquivalenceCols(p.Conditions, p.SCtx(), fds)

// apply operator's characteristic's FD setting.
fds.MakeNotNull(notnullColsUniqueIDs)
fds.AddConstants(constUniqueIDs)
for _, equiv := range equivUniqueIDs {
fds.AddEquivalence(equiv[0], equiv[1])
}
fds.ProjectCols(outputColsUniqueIDs)
// just trace it down in every operator for test checking.
p.SetFDs(fds)
return fds
}

// ExtractCorrelatedCols implements LogicalPlan interface.
func (p *LogicalSelection) ExtractCorrelatedCols() []*expression.CorrelatedColumn {
corCols := make([]*expression.CorrelatedColumn, 0, len(p.Conditions))
for _, cond := range p.Conditions {
corCols = append(corCols, expression.ExtractCorColumns(cond)...)
}
return corCols
}

// LogicalApply gets one row from outer executor and gets one row from inner executor according to outer row.
type LogicalApply struct {
LogicalJoin
Expand Down
Loading

0 comments on commit acbf74a

Please sign in to comment.