diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index dd2b97707f..bc808c1a96 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -3773,7 +3773,7 @@ func (b *PlanBuilder) tryBuildCTE(ctx context.Context, tn *ast.TableName, asName } cte.recursiveRef = true - p := LogicalCTETable{name: cte.def.Name.String(), idForStorage: cte.storageID, seedPlan: cte.seedLP}.Init(b.ctx, b.getSelectOffset()) + p := LogicalCTETable{name: cte.def.Name.String(), idForStorage: cte.storageID, seedStat: cte.seedStat}.Init(b.ctx, b.getSelectOffset()) p.SetSchema(getResultCTESchema(cte.seedLP.Schema(), b.ctx.GetSessionVars())) p.SetOutputNames(cte.seedLP.OutputNames()) return p, nil @@ -3801,7 +3801,7 @@ func (b *PlanBuilder) tryBuildCTE(ctx context.Context, tn *ast.TableName, asName lp := LogicalCTE{cteAsName: tn.Name, cte: &CTEClass{IsDistinct: cte.isDistinct, seedPartLogicalPlan: cte.seedLP, recursivePartLogicalPlan: cte.recurLP, IDForStorage: cte.storageID, optFlag: cte.optFlag, HasLimit: hasLimit, LimitBeg: limitBeg, - LimitEnd: limitEnd}}.Init(b.ctx, b.getSelectOffset()) + LimitEnd: limitEnd}, seedStat: cte.seedStat}.Init(b.ctx, b.getSelectOffset()) lp.SetSchema(getResultCTESchema(cte.seedLP.Schema(), b.ctx.GetSessionVars())) p = lp p.SetOutputNames(cte.seedLP.OutputNames()) @@ -6228,7 +6228,7 @@ func (b *PlanBuilder) buildWith(ctx context.Context, w *ast.WithClause) error { nameMap[cte.Name.L] = struct{}{} } for _, cte := range w.CTEs { - b.outerCTEs = append(b.outerCTEs, &cteInfo{def: cte, nonRecursive: !w.IsRecursive, isBuilding: true, storageID: b.allocIDForCTEStorage}) + b.outerCTEs = append(b.outerCTEs, &cteInfo{def: cte, nonRecursive: !w.IsRecursive, isBuilding: true, storageID: b.allocIDForCTEStorage, seedStat: &property.StatsInfo{}}) b.allocIDForCTEStorage++ saveFlag := b.optFlag // Init the flag to flagPrunColumns, otherwise it's missing. diff --git a/planner/core/logical_plans.go b/planner/core/logical_plans.go index 7c02b3526b..dedd379f1b 100644 --- a/planner/core/logical_plans.go +++ b/planner/core/logical_plans.go @@ -1216,13 +1216,14 @@ type LogicalCTE struct { cte *CTEClass cteAsName model.CIStr + seedStat *property.StatsInfo } // LogicalCTETable is for CTE table type LogicalCTETable struct { logicalSchemaProducer - seedPlan LogicalPlan + seedStat *property.StatsInfo name string idForStorage int } diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 3e39d12bd5..335951a1b5 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -433,6 +433,8 @@ type cteInfo struct { enterSubquery bool recursiveRef bool limitLP LogicalPlan + // seedStat is shared between logicalCTE and logicalCTETable. + seedStat *property.StatsInfo } // PlanBuilder builds Plan from an ast.Node. diff --git a/planner/core/stats.go b/planner/core/stats.go index f892f6884c..65be100877 100644 --- a/planner/core/stats.go +++ b/planner/core/stats.go @@ -1110,6 +1110,8 @@ func (p *LogicalCTE) DeriveStats(childStats []*property.StatsInfo, selfSchema *e return nil, err } resStat := p.cte.seedPartPhysicalPlan.Stats() + // Changing the pointer so that seedStat in LogicalCTETable can get the new stat. + *p.seedStat = *resStat p.stats = &property.StatsInfo{ RowCount: resStat.RowCount, ColNDVs: make(map[int64]float64, selfSchema.Len()), @@ -1140,6 +1142,6 @@ func (p *LogicalCTETable) DeriveStats(childStats []*property.StatsInfo, selfSche if p.stats != nil { return p.stats, nil } - p.stats = p.seedPlan.statsInfo() + p.stats = p.seedStat return p.stats, nil }