From 77f7f9dab7fc9a511db8ce29179abcc4130d0eb6 Mon Sep 17 00:00:00 2001 From: ti-srebot <66930949+ti-srebot@users.noreply.github.com> Date: Wed, 10 Aug 2022 11:36:48 +0800 Subject: [PATCH] executor: prevent sending cop request for show columns (#36613) (#36817) close pingcap/tidb#36426, ref pingcap/tidb#36496 --- executor/show.go | 3 ++- planner/core/expression_rewriter.go | 4 ++-- planner/core/planbuilder.go | 23 +++++++++++++++++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/executor/show.go b/executor/show.go index 5f1b3f8bad927..8bcc2a7bd5bb0 100644 --- a/executor/show.go +++ b/executor/show.go @@ -1885,7 +1885,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 c088e0f48d582..1071d5fd6ebc4 100644 --- a/planner/core/expression_rewriter.go +++ b/planner/core/expression_rewriter.go @@ -816,7 +816,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 @@ -991,7 +991,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 84954e37575ee..06b94e42bef9c 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -516,6 +516,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 { @@ -617,14 +619,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.