diff --git a/executor/show.go b/executor/show.go index 3269321888222..473b962d1a78f 100644 --- a/executor/show.go +++ b/executor/show.go @@ -1763,7 +1763,8 @@ func (e *ShowExec) fetchShowBuiltins() error { func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is infoschema.InfoSchema, dbName model.CIStr, tbl *model.TableInfo) error { if tbl.IsView() { // Retrieve view columns info. - planBuilder, _ := plannercore.NewPlanBuilder().Init(sctx, is, &hint.BlockHintProcessor{}) + planBuilder, _ := plannercore.NewPlanBuilder( + plannercore.PlanBuilderOptNoExecution{}).Init(sctx, is, &hint.BlockHintProcessor{}) if viewLogicalPlan, err := planBuilder.BuildDataSourceFromView(ctx, dbName, tbl); err == nil { viewSchema := viewLogicalPlan.Schema() viewOutputNames := viewLogicalPlan.OutputNames() diff --git a/planner/core/expression_rewriter.go b/planner/core/expression_rewriter.go index e110e4c8e267b..440f466c36050 100644 --- a/planner/core/expression_rewriter.go +++ b/planner/core/expression_rewriter.go @@ -808,7 +808,7 @@ func (er *expressionRewriter) handleExistSubquery(ctx context.Context, v *ast.Ex return v, true } np = er.popExistsSubPlan(np) - if len(ExtractCorrelatedCols4LogicalPlan(np)) > 0 { + if er.b.disableSubQueryPreprocessing || len(ExtractCorrelatedCols4LogicalPlan(np)) > 0 { er.p, er.err = er.b.buildSemiApply(er.p, np, nil, er.asScalar, v.Not) if er.err != nil || !er.asScalar { return v, true @@ -981,7 +981,7 @@ func (er *expressionRewriter) handleScalarSubquery(ctx context.Context, v *ast.S return v, true } np = er.b.buildMaxOneRow(np) - if len(ExtractCorrelatedCols4LogicalPlan(np)) > 0 { + if er.b.disableSubQueryPreprocessing || len(ExtractCorrelatedCols4LogicalPlan(np)) > 0 { er.p = er.b.buildApplyWithJoinType(er.p, np, LeftOuterJoin) if np.Schema().Len() > 1 { newCols := make([]expression.Expression, 0, np.Schema().Len()) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 2eed874f10188..4295ebb461ec3 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -510,6 +510,8 @@ type PlanBuilder struct { isForUpdateRead bool allocIDForCTEStorage int buildingRecursivePartForCTE bool + // disableSubQueryPreprocessing indicates whether to pre-process uncorrelated sub-queries in rewriting stage. + disableSubQueryPreprocessing bool } type handleColHelper struct { @@ -611,14 +613,31 @@ func (b *PlanBuilder) popSelectOffset() { b.selectOffset = b.selectOffset[:len(b.selectOffset)-1] } +// PlanBuilderOpt is used to adjust the plan builder. +type PlanBuilderOpt interface { + Apply(builder *PlanBuilder) +} + +// PlanBuilderOptNoExecution means the plan builder should not run any executor during Build(). +type PlanBuilderOptNoExecution struct{} + +// Apply implements the interface PlanBuilderOpt. +func (p PlanBuilderOptNoExecution) Apply(builder *PlanBuilder) { + builder.disableSubQueryPreprocessing = true +} + // NewPlanBuilder creates a new PlanBuilder. -func NewPlanBuilder() *PlanBuilder { - return &PlanBuilder{ +func NewPlanBuilder(opts ...PlanBuilderOpt) *PlanBuilder { + builder := &PlanBuilder{ outerCTEs: make([]*cteInfo, 0), colMapper: make(map[*ast.ColumnNameExpr]int), handleHelper: &handleColHelper{id2HandleMapStack: make([]map[int64][]HandleCols, 0)}, correlatedAggMapper: make(map[*ast.AggregateFuncExpr]*expression.CorrelatedColumn), } + for _, opt := range opts { + opt.Apply(builder) + } + return builder } // Init initialize a PlanBuilder.