Skip to content

Commit

Permalink
planner: use code-gen to generate CloneForPlanCache method for some o…
Browse files Browse the repository at this point in the history
…perators (#54601)

ref #54057
  • Loading branch information
qw4990 authored Jul 15, 2024
1 parent ac786cb commit a453b81
Show file tree
Hide file tree
Showing 11 changed files with 397 additions and 26 deletions.
1 change: 1 addition & 0 deletions build/nogo_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@
"pkg/parser/goyacc/": "ignore goyacc code",
"pkg/parser/ast/": "ignore parser/ast code",
"pkg/parser/test_driver/": "ignore parser/test_driver code",
"pkg/planner/core/plan_clone_generated.go": "ignore plan_clone_generated code",
".*_test\\.go$": "ignore generated code",
".*_generated\\.go$": "ignore generated code",
".*mock.go$": "ignore generated code",
Expand Down
3 changes: 3 additions & 0 deletions pkg/expression/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ func (s *Schema) String() string {

// Clone copies the total schema.
func (s *Schema) Clone() *Schema {
if s == nil {
return nil
}
cols := make([]*Column, 0, s.Len())
keys := make([]KeyInfo, 0, len(s.Keys))
for _, col := range s.Columns {
Expand Down
8 changes: 7 additions & 1 deletion pkg/planner/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ go_library(
"plan_cache_rebuild.go",
"plan_cache_utils.go",
"plan_cacheable_checker.go",
"plan_clone_generated.go",
"plan_clone_generator.go",
"plan_cost_detail.go",
"plan_cost_ver1.go",
"plan_cost_ver2.go",
Expand Down Expand Up @@ -256,6 +258,7 @@ go_test(
"plan_cache_rebuild_test.go",
"plan_cache_test.go",
"plan_cacheable_checker_test.go",
"plan_clone_test.go",
"plan_cost_detail_test.go",
"plan_cost_ver1_test.go",
"plan_cost_ver2_test.go",
Expand All @@ -271,7 +274,10 @@ go_test(
"stringer_test.go",
"util_test.go",
],
data = glob(["testdata/**"]),
data = glob([
"testdata/**",
"*.go",
]),
embed = [":core"],
flaky = True,
shard_count = 50,
Expand Down
40 changes: 20 additions & 20 deletions pkg/planner/core/physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -680,26 +680,26 @@ type PhysicalIndexScan struct {
// AccessCondition is used to calculate range.
AccessCondition []expression.Expression

Table *model.TableInfo
Index *model.IndexInfo
Table *model.TableInfo `plan-cache-clone:"shallow"` // please see comment on genPlanCloneForPlanCacheCode.
Index *model.IndexInfo `plan-cache-clone:"shallow"`
IdxCols []*expression.Column
IdxColLens []int
Ranges []*ranger.Range
Columns []*model.ColumnInfo
DBName model.CIStr
Columns []*model.ColumnInfo `plan-cache-clone:"shallow"`
DBName model.CIStr `plan-cache-clone:"shallow"`

TableAsName *model.CIStr
TableAsName *model.CIStr `plan-cache-clone:"shallow"`

// dataSourceSchema is the original schema of DataSource. The schema of index scan in KV and index reader in TiDB
// will be different. The schema of index scan will decode all columns of index but the TiDB only need some of them.
dataSourceSchema *expression.Schema
dataSourceSchema *expression.Schema `plan-cache-clone:"shallow"`

rangeInfo string

// The index scan may be on a partition.
physicalTableID int64

GenExprs map[model.TableItemID]expression.Expression `json:"-"`
GenExprs map[model.TableItemID]expression.Expression `plan-cache-clone:"must-nil"`

isPartition bool
Desc bool
Expand All @@ -715,18 +715,18 @@ type PhysicalIndexScan struct {

// required by cost model
// tblColHists contains all columns before pruning, which are used to calculate row-size
tblColHists *statistics.HistColl
tblColHists *statistics.HistColl `plan-cache-clone:"shallow"`
pkIsHandleCol *expression.Column

// constColsByCond records the constant part of the index columns caused by the access conds.
// e.g. the index is (a, b, c) and there's filter a = 1 and b = 2, then the column a and b are const part.
constColsByCond []bool

prop *property.PhysicalProperty
prop *property.PhysicalProperty `plan-cache-clone:"shallow"`

// usedStatsInfo records stats status of this physical table.
// It's for printing stats related information when display execution plan.
usedStatsInfo *stmtctx.UsedStatsInfoForTable
usedStatsInfo *stmtctx.UsedStatsInfoForTable `plan-cache-clone:"shallow"`
}

// Clone implements op.PhysicalPlan interface.
Expand Down Expand Up @@ -857,12 +857,12 @@ type PhysicalTableScan struct {
// TODO: remove this field after we support pushing down selection to coprocessor.
LateMaterializationFilterCondition []expression.Expression

Table *model.TableInfo
Columns []*model.ColumnInfo
DBName model.CIStr
Table *model.TableInfo `plan-cache-clone:"shallow"`
Columns []*model.ColumnInfo `plan-cache-clone:"shallow"`
DBName model.CIStr `plan-cache-clone:"shallow"`
Ranges []*ranger.Range

TableAsName *model.CIStr
TableAsName *model.CIStr `plan-cache-clone:"shallow"`

physicalTableID int64

Expand Down Expand Up @@ -890,13 +890,13 @@ type PhysicalTableScan struct {

PlanPartInfo *PhysPlanPartInfo

SampleInfo *tablesampler.TableSampleInfo
SampleInfo *tablesampler.TableSampleInfo `plan-cache-clone:"must-nil"`

// required by cost model
// tblCols and tblColHists contains all columns before pruning, which are used to calculate row-size
tblCols []*expression.Column
tblColHists *statistics.HistColl
prop *property.PhysicalProperty
tblCols []*expression.Column `plan-cache-clone:"shallow"`
tblColHists *statistics.HistColl `plan-cache-clone:"shallow"`
prop *property.PhysicalProperty `plan-cache-clone:"shallow"`

// constColsByCond records the constant part of the index columns caused by the access conds.
// e.g. the index is (a, b, c) and there's filter a = 1 and b = 2, then the column a and b are const part.
Expand All @@ -905,10 +905,10 @@ type PhysicalTableScan struct {

// usedStatsInfo records stats status of this physical table.
// It's for printing stats related information when display execution plan.
usedStatsInfo *stmtctx.UsedStatsInfoForTable
usedStatsInfo *stmtctx.UsedStatsInfoForTable `plan-cache-clone:"shallow"`

// for runtime filter
runtimeFilterList []*RuntimeFilter
runtimeFilterList []*RuntimeFilter `plan-cache-clone:"must-nil"` // plan with runtime filter is not cached
maxWaitTimeMs int
}

Expand Down
35 changes: 33 additions & 2 deletions pkg/planner/core/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,14 @@ func getActualProbeCntFromProbeParents(pps []base.PhysicalPlan, statsColl *execd
type basePhysicalPlan struct {
baseimpl.Plan

childrenReqProps []*property.PhysicalProperty
childrenReqProps []*property.PhysicalProperty `plan-cache-clone:"shallow"`
self base.PhysicalPlan
children []base.PhysicalPlan

// used by the new cost interface
planCostInit bool
planCost float64
planCostVer2 costusage.CostVer2
planCostVer2 costusage.CostVer2 `plan-cache-clone:"shallow"`

// probeParents records the IndexJoins and Applys with this operator in their inner children.
// Please see comments in op.PhysicalPlan for details.
Expand All @@ -268,6 +268,37 @@ type basePhysicalPlan struct {
TiFlashFineGrainedShuffleStreamCount uint64
}

func (p *basePhysicalPlan) cloneForPlanCacheWithSelf(newCtx base.PlanContext, newSelf base.PhysicalPlan) (*basePhysicalPlan, bool) {
cloned := new(basePhysicalPlan)
*cloned = *p
cloned.SetSCtx(newCtx)
cloned.self = newSelf
cloned.children = make([]base.PhysicalPlan, 0, len(p.children))
for _, child := range p.children {
clonedChild, ok := child.CloneForPlanCache(newCtx)
if !ok {
return nil, false
}
clonedPP, ok := clonedChild.(base.PhysicalPlan)
if !ok {
return nil, false
}
cloned.children = append(cloned.children, clonedPP)
}
for _, probe := range p.probeParents {
clonedProbe, ok := probe.CloneForPlanCache(newCtx)
if !ok {
return nil, false
}
clonedPP, ok := clonedProbe.(base.PhysicalPlan)
if !ok {
return nil, false
}
cloned.probeParents = append(cloned.probeParents, clonedPP)
}
return cloned, true
}

func (p *basePhysicalPlan) cloneWithSelf(newCtx base.PlanContext, newSelf base.PhysicalPlan) (*basePhysicalPlan, error) {
base := &basePhysicalPlan{
Plan: p.Plan,
Expand Down
6 changes: 3 additions & 3 deletions pkg/planner/core/plan_cache_rebuild_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func TestCheckPlanClone(t *testing.T) {

// test tag
type S struct {
p1 *int `plan-cache-shallow-clone:"true"`
p1 *int `plan-cache-clone:"shallow"`
p2 *int
}
s1 := new(S)
Expand Down Expand Up @@ -255,8 +255,8 @@ func planCacheUnclearCloneCheck(v1, v2 reflect.Value, path string, visited map[v
return planCacheUnclearCloneCheck(v1.Elem(), v2.Elem(), path, visited)
case reflect.Struct:
for i, n := 0, v1.NumField(); i < n; i++ {
tag := v1.Type().Field(i).Tag.Get("plan-cache-shallow-clone")
if tag == "true" {
tag := v1.Type().Field(i).Tag.Get("plan-cache-clone")
if tag == "shallow" {
continue
}
fieldName := v1.Type().Field(i).Name
Expand Down
102 changes: 102 additions & 0 deletions pkg/planner/core/plan_clone_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a453b81

Please sign in to comment.