From d8e76657a17750c62ff280a027089e665d38d4c9 Mon Sep 17 00:00:00 2001 From: Mingcong Han Date: Thu, 12 Nov 2020 10:44:23 +0800 Subject: [PATCH 1/3] cherry pick #20398 to release-4.0 Signed-off-by: ti-srebot --- errors.toml | 5 +++ executor/ddl_test.go | 13 ++++++ planner/core/errors.go | 67 ++++++++++++++++++++++++++++ planner/core/logical_plan_builder.go | 35 +++++++++++++-- planner/core/planbuilder.go | 27 ++++++----- 5 files changed, 133 insertions(+), 14 deletions(-) diff --git a/errors.toml b/errors.toml index 7a0611015e6ca..47b498b4cd179 100644 --- a/errors.toml +++ b/errors.toml @@ -756,6 +756,11 @@ error = ''' View '%-.192s.%-.192s' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them ''' +["planner:1462"] +error = ''' +`%-.192s`.`%-.192s` contains view recursion +''' + ["planner:1747"] error = ''' PARTITION () clause on non partitioned table diff --git a/executor/ddl_test.go b/executor/ddl_test.go index 113d88b114a8f..b643c1039a262 100644 --- a/executor/ddl_test.go +++ b/executor/ddl_test.go @@ -278,6 +278,19 @@ func (s *testSuite6) TestCreateView(c *C) { tk.MustExec("drop view v_nested, v_nested2") } +func (s *testSuite6) TestViewRecursion(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("create table if not exists t(a int)") + tk.MustExec("create definer='root'@'localhost' view recursive_view1 as select * from t") + tk.MustExec("create definer='root'@'localhost' view recursive_view2 as select * from recursive_view1") + tk.MustExec("drop table t") + tk.MustExec("rename table recursive_view2 to t") + _, err := tk.Exec("select * from recursive_view1") + c.Assert(terror.ErrorEqual(err, plannercore.ErrViewRecursive), IsTrue) + tk.MustExec("drop view recursive_view1, t") +} + func (s *testSuite6) TestIssue16250(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") diff --git a/planner/core/errors.go b/planner/core/errors.go index 7e659ff646142..d708aac6e9a5f 100644 --- a/planner/core/errors.go +++ b/planner/core/errors.go @@ -20,6 +20,7 @@ import ( // error definitions. var ( +<<<<<<< HEAD ErrUnsupportedType = terror.ClassOptimizer.New(mysql.ErrUnsupportedType, mysql.MySQLErrName[mysql.ErrUnsupportedType]) ErrAnalyzeMissIndex = terror.ClassOptimizer.New(mysql.ErrAnalyzeMissIndex, mysql.MySQLErrName[mysql.ErrAnalyzeMissIndex]) ErrWrongParamCount = terror.ClassOptimizer.New(mysql.ErrWrongParamCount, mysql.MySQLErrName[mysql.ErrWrongParamCount]) @@ -80,6 +81,72 @@ var ( ErrCartesianProductUnsupported = terror.ClassOptimizer.New(mysql.ErrCartesianProductUnsupported, mysql.MySQLErrName[mysql.ErrCartesianProductUnsupported]) ErrStmtNotFound = terror.ClassOptimizer.New(mysql.ErrPreparedStmtNotFound, mysql.MySQLErrName[mysql.ErrPreparedStmtNotFound]) ErrAmbiguous = terror.ClassOptimizer.New(mysql.ErrNonUniq, mysql.MySQLErrName[mysql.ErrNonUniq]) +======= + ErrUnsupportedType = dbterror.ClassOptimizer.NewStd(mysql.ErrUnsupportedType) + ErrAnalyzeMissIndex = dbterror.ClassOptimizer.NewStd(mysql.ErrAnalyzeMissIndex) + ErrWrongParamCount = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongParamCount) + ErrSchemaChanged = dbterror.ClassOptimizer.NewStd(mysql.ErrSchemaChanged) + ErrTablenameNotAllowedHere = dbterror.ClassOptimizer.NewStd(mysql.ErrTablenameNotAllowedHere) + ErrNotSupportedYet = dbterror.ClassOptimizer.NewStd(mysql.ErrNotSupportedYet) + ErrWrongUsage = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongUsage) + ErrUnknown = dbterror.ClassOptimizer.NewStd(mysql.ErrUnknown) + ErrUnknownTable = dbterror.ClassOptimizer.NewStd(mysql.ErrUnknownTable) + ErrNoSuchTable = dbterror.ClassOptimizer.NewStd(mysql.ErrNoSuchTable) + ErrViewRecursive = dbterror.ClassOptimizer.NewStd(mysql.ErrViewRecursive) + ErrWrongArguments = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongArguments) + ErrWrongNumberOfColumnsInSelect = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongNumberOfColumnsInSelect) + ErrBadGeneratedColumn = dbterror.ClassOptimizer.NewStd(mysql.ErrBadGeneratedColumn) + ErrFieldNotInGroupBy = dbterror.ClassOptimizer.NewStd(mysql.ErrFieldNotInGroupBy) + ErrBadTable = dbterror.ClassOptimizer.NewStd(mysql.ErrBadTable) + ErrKeyDoesNotExist = dbterror.ClassOptimizer.NewStd(mysql.ErrKeyDoesNotExist) + ErrOperandColumns = dbterror.ClassOptimizer.NewStd(mysql.ErrOperandColumns) + ErrInvalidGroupFuncUse = dbterror.ClassOptimizer.NewStd(mysql.ErrInvalidGroupFuncUse) + ErrIllegalReference = dbterror.ClassOptimizer.NewStd(mysql.ErrIllegalReference) + ErrNoDB = dbterror.ClassOptimizer.NewStd(mysql.ErrNoDB) + ErrUnknownExplainFormat = dbterror.ClassOptimizer.NewStd(mysql.ErrUnknownExplainFormat) + ErrWrongGroupField = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongGroupField) + ErrDupFieldName = dbterror.ClassOptimizer.NewStd(mysql.ErrDupFieldName) + ErrNonUpdatableTable = dbterror.ClassOptimizer.NewStd(mysql.ErrNonUpdatableTable) + ErrInternal = dbterror.ClassOptimizer.NewStd(mysql.ErrInternal) + ErrNonUniqTable = dbterror.ClassOptimizer.NewStd(mysql.ErrNonuniqTable) + ErrWindowInvalidWindowFuncUse = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowInvalidWindowFuncUse) + ErrWindowInvalidWindowFuncAliasUse = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowInvalidWindowFuncAliasUse) + ErrWindowNoSuchWindow = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowNoSuchWindow) + ErrWindowCircularityInWindowGraph = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowCircularityInWindowGraph) + ErrWindowNoChildPartitioning = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowNoChildPartitioning) + ErrWindowNoInherentFrame = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowNoInherentFrame) + ErrWindowNoRedefineOrderBy = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowNoRedefineOrderBy) + ErrWindowDuplicateName = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowDuplicateName) + ErrPartitionClauseOnNonpartitioned = dbterror.ClassOptimizer.NewStd(mysql.ErrPartitionClauseOnNonpartitioned) + ErrWindowFrameStartIllegal = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowFrameStartIllegal) + ErrWindowFrameEndIllegal = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowFrameEndIllegal) + ErrWindowFrameIllegal = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowFrameIllegal) + ErrWindowRangeFrameOrderType = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRangeFrameOrderType) + ErrWindowRangeFrameTemporalType = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRangeFrameTemporalType) + ErrWindowRangeFrameNumericType = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRangeFrameNumericType) + ErrWindowRangeBoundNotConstant = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRangeBoundNotConstant) + ErrWindowRowsIntervalUse = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRowsIntervalUse) + ErrWindowFunctionIgnoresFrame = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowFunctionIgnoresFrame) + ErrUnsupportedOnGeneratedColumn = dbterror.ClassOptimizer.NewStd(mysql.ErrUnsupportedOnGeneratedColumn) + ErrPrivilegeCheckFail = dbterror.ClassOptimizer.NewStd(mysql.ErrPrivilegeCheckFail) + ErrInvalidWildCard = dbterror.ClassOptimizer.NewStd(mysql.ErrInvalidWildCard) + ErrMixOfGroupFuncAndFields = dbterror.ClassOptimizer.NewStd(mysql.ErrMixOfGroupFuncAndFieldsIncompatible) + errTooBigPrecision = dbterror.ClassExpression.NewStd(mysql.ErrTooBigPrecision) + ErrDBaccessDenied = dbterror.ClassOptimizer.NewStd(mysql.ErrDBaccessDenied) + ErrTableaccessDenied = dbterror.ClassOptimizer.NewStd(mysql.ErrTableaccessDenied) + ErrSpecificAccessDenied = dbterror.ClassOptimizer.NewStd(mysql.ErrSpecificAccessDenied) + ErrViewNoExplain = dbterror.ClassOptimizer.NewStd(mysql.ErrViewNoExplain) + ErrWrongValueCountOnRow = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongValueCountOnRow) + ErrViewInvalid = dbterror.ClassOptimizer.NewStd(mysql.ErrViewInvalid) + ErrNoSuchThread = dbterror.ClassOptimizer.NewStd(mysql.ErrNoSuchThread) + ErrUnknownColumn = dbterror.ClassOptimizer.NewStd(mysql.ErrBadField) + ErrCartesianProductUnsupported = dbterror.ClassOptimizer.NewStd(mysql.ErrCartesianProductUnsupported) + ErrStmtNotFound = dbterror.ClassOptimizer.NewStd(mysql.ErrPreparedStmtNotFound) + ErrAmbiguous = dbterror.ClassOptimizer.NewStd(mysql.ErrNonUniq) + ErrUnresolvedHintName = dbterror.ClassOptimizer.NewStd(mysql.ErrUnresolvedHintName) + ErrNotHintUpdatable = dbterror.ClassOptimizer.NewStd(mysql.ErrNotHintUpdatable) + ErrWarnConflictingHint = dbterror.ClassOptimizer.NewStd(mysql.ErrWarnConflictingHint) +>>>>>>> f81a5d131... planner: check view recursion when building source from view (#20398) // Since we cannot know if user logged in with a password, use message of ErrAccessDeniedNoPassword instead ErrAccessDenied = terror.ClassOptimizer.New(mysql.ErrAccessDenied, mysql.MySQLErrName[mysql.ErrAccessDeniedNoPassword]) ) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 0bef4438aedbe..b1dbe0a93fd87 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/parser/model" "github.com/pingcap/parser/mysql" "github.com/pingcap/parser/opcode" + "github.com/pingcap/parser/terror" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/expression/aggregation" @@ -52,6 +53,7 @@ import ( "github.com/pingcap/tidb/util/chunk" utilhint "github.com/pingcap/tidb/util/hint" "github.com/pingcap/tidb/util/plancodec" + "github.com/pingcap/tidb/util/set" ) const ( @@ -2744,9 +2746,6 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as } if tableInfo.IsView() { - if b.capFlag&collectUnderlyingViewName != 0 { - b.underlyingViewNames.Insert(dbName.L + "." + tn.Name.L) - } return b.BuildDataSourceFromView(ctx, dbName, tableInfo) } @@ -3068,8 +3067,33 @@ func (b *PlanBuilder) buildMemTable(_ context.Context, dbName model.CIStr, table return p, nil } +// checkRecursiveView checks whether this view is recursively defined. +func (b *PlanBuilder) checkRecursiveView(dbName model.CIStr, tableName model.CIStr) (func(), error) { + viewFullName := dbName.L + "." + tableName.L + if b.buildingViewStack == nil { + b.buildingViewStack = set.NewStringSet() + } + // If this view has already been on the building stack, it means + // this view contains a recursive definition. + if b.buildingViewStack.Exist(viewFullName) { + return nil, ErrViewRecursive.GenWithStackByArgs(dbName.O, tableName.O) + } + // If the view is being renamed, we return the mysql compatible error message. + if b.capFlag&renameView != 0 && viewFullName == b.renamingViewName { + return nil, ErrNoSuchTable.GenWithStackByArgs(dbName.O, tableName.O) + } + b.buildingViewStack.Insert(viewFullName) + return func() { delete(b.buildingViewStack, viewFullName) }, nil +} + // BuildDataSourceFromView is used to build LogicalPlan from view func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.CIStr, tableInfo *model.TableInfo) (LogicalPlan, error) { + deferFunc, err := b.checkRecursiveView(dbName, tableInfo.Name) + if err != nil { + return nil, err + } + defer deferFunc() + charset, collation := b.ctx.GetSessionVars().GetCharsetInfo() viewParser := parser.New() viewParser.EnableWindowFunc(b.ctx.GetSessionVars().EnableWindowFunction) @@ -3081,7 +3105,10 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. b.visitInfo = make([]visitInfo, 0) selectLogicalPlan, err := b.Build(ctx, selectNode) if err != nil { - err = ErrViewInvalid.GenWithStackByArgs(dbName.O, tableInfo.Name.O) + if terror.ErrorNotEqual(err, ErrViewRecursive) && + terror.ErrorNotEqual(err, ErrNoSuchTable) { + err = ErrViewInvalid.GenWithStackByArgs(dbName.O, tableInfo.Name.O) + } return nil, err } diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index dfa28a856c648..49cf7cdf2e643 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -392,9 +392,9 @@ const ( // canExpandAST indicates whether the origin AST can be expanded during plan // building. ONLY used for `CreateViewStmt` now. canExpandAST - // collectUnderlyingViewName indicates whether to collect the underlying - // view names of a CreateViewStmt during plan building. - collectUnderlyingViewName + // renameView indicates a view is being renamed, so we cannot use the origin + // definition of that view. + renameView ) // PlanBuilder builds Plan from an ast.Node. @@ -444,8 +444,19 @@ type PlanBuilder struct { // SelectLock need this information to locate the lock on partitions. partitionedTable []table.PartitionedTable +<<<<<<< HEAD // CreateView needs this information to check whether exists nested view. underlyingViewNames set.StringSet +======= + // buildingViewStack is used to check whether there is a recursive view. + buildingViewStack set.StringSet + // renamingViewName is the name of the view which is being renamed. + renamingViewName string + + // evalDefaultExpr needs this information to find the corresponding column. + // It stores the OutputNames before buildProjection. + allNames [][]*types.FieldName +>>>>>>> f81a5d131... planner: check view recursion when building source from view (#20398) } type handleColHelper struct { @@ -2777,20 +2788,16 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err v.ReferTable.Name.L, "", authErr) } case *ast.CreateViewStmt: - b.capFlag |= canExpandAST - b.capFlag |= collectUnderlyingViewName + b.capFlag |= canExpandAST | renameView + b.renamingViewName = v.ViewName.Schema.L + "." + v.ViewName.Name.L defer func() { b.capFlag &= ^canExpandAST - b.capFlag &= ^collectUnderlyingViewName + b.capFlag &= ^renameView }() - b.underlyingViewNames = set.NewStringSet() plan, err := b.Build(ctx, v.Select) if err != nil { return nil, err } - if b.underlyingViewNames.Exist(v.ViewName.Schema.L + "." + v.ViewName.Name.L) { - return nil, ErrNoSuchTable.GenWithStackByArgs(v.ViewName.Schema.O, v.ViewName.Name.O) - } schema := plan.Schema() names := plan.OutputNames() if v.Cols == nil { From bceba6425a00b5093e1427be5e9af59cfadde02e Mon Sep 17 00:00:00 2001 From: Mingcong Han Date: Thu, 12 Nov 2020 18:20:15 +0800 Subject: [PATCH 2/3] resolve conflicts --- planner/core/errors.go | 68 +------------------------------------ planner/core/planbuilder.go | 10 +----- 2 files changed, 2 insertions(+), 76 deletions(-) diff --git a/planner/core/errors.go b/planner/core/errors.go index d708aac6e9a5f..87e97039e0b97 100644 --- a/planner/core/errors.go +++ b/planner/core/errors.go @@ -20,7 +20,6 @@ import ( // error definitions. var ( -<<<<<<< HEAD ErrUnsupportedType = terror.ClassOptimizer.New(mysql.ErrUnsupportedType, mysql.MySQLErrName[mysql.ErrUnsupportedType]) ErrAnalyzeMissIndex = terror.ClassOptimizer.New(mysql.ErrAnalyzeMissIndex, mysql.MySQLErrName[mysql.ErrAnalyzeMissIndex]) ErrWrongParamCount = terror.ClassOptimizer.New(mysql.ErrWrongParamCount, mysql.MySQLErrName[mysql.ErrWrongParamCount]) @@ -31,6 +30,7 @@ var ( ErrUnknown = terror.ClassOptimizer.New(mysql.ErrUnknown, mysql.MySQLErrName[mysql.ErrUnknown]) ErrUnknownTable = terror.ClassOptimizer.New(mysql.ErrUnknownTable, mysql.MySQLErrName[mysql.ErrUnknownTable]) ErrNoSuchTable = terror.ClassOptimizer.New(mysql.ErrNoSuchTable, mysql.MySQLErrName[mysql.ErrNoSuchTable]) + ErrViewRecursive = terror.ClassOptimizer.New(mysql.ErrViewRecursive, mysql.MySQLErrName[mysql.ErrViewRecursive]) ErrWrongArguments = terror.ClassOptimizer.New(mysql.ErrWrongArguments, mysql.MySQLErrName[mysql.ErrWrongArguments]) ErrWrongNumberOfColumnsInSelect = terror.ClassOptimizer.New(mysql.ErrWrongNumberOfColumnsInSelect, mysql.MySQLErrName[mysql.ErrWrongNumberOfColumnsInSelect]) ErrBadGeneratedColumn = terror.ClassOptimizer.New(mysql.ErrBadGeneratedColumn, mysql.MySQLErrName[mysql.ErrBadGeneratedColumn]) @@ -81,72 +81,6 @@ var ( ErrCartesianProductUnsupported = terror.ClassOptimizer.New(mysql.ErrCartesianProductUnsupported, mysql.MySQLErrName[mysql.ErrCartesianProductUnsupported]) ErrStmtNotFound = terror.ClassOptimizer.New(mysql.ErrPreparedStmtNotFound, mysql.MySQLErrName[mysql.ErrPreparedStmtNotFound]) ErrAmbiguous = terror.ClassOptimizer.New(mysql.ErrNonUniq, mysql.MySQLErrName[mysql.ErrNonUniq]) -======= - ErrUnsupportedType = dbterror.ClassOptimizer.NewStd(mysql.ErrUnsupportedType) - ErrAnalyzeMissIndex = dbterror.ClassOptimizer.NewStd(mysql.ErrAnalyzeMissIndex) - ErrWrongParamCount = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongParamCount) - ErrSchemaChanged = dbterror.ClassOptimizer.NewStd(mysql.ErrSchemaChanged) - ErrTablenameNotAllowedHere = dbterror.ClassOptimizer.NewStd(mysql.ErrTablenameNotAllowedHere) - ErrNotSupportedYet = dbterror.ClassOptimizer.NewStd(mysql.ErrNotSupportedYet) - ErrWrongUsage = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongUsage) - ErrUnknown = dbterror.ClassOptimizer.NewStd(mysql.ErrUnknown) - ErrUnknownTable = dbterror.ClassOptimizer.NewStd(mysql.ErrUnknownTable) - ErrNoSuchTable = dbterror.ClassOptimizer.NewStd(mysql.ErrNoSuchTable) - ErrViewRecursive = dbterror.ClassOptimizer.NewStd(mysql.ErrViewRecursive) - ErrWrongArguments = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongArguments) - ErrWrongNumberOfColumnsInSelect = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongNumberOfColumnsInSelect) - ErrBadGeneratedColumn = dbterror.ClassOptimizer.NewStd(mysql.ErrBadGeneratedColumn) - ErrFieldNotInGroupBy = dbterror.ClassOptimizer.NewStd(mysql.ErrFieldNotInGroupBy) - ErrBadTable = dbterror.ClassOptimizer.NewStd(mysql.ErrBadTable) - ErrKeyDoesNotExist = dbterror.ClassOptimizer.NewStd(mysql.ErrKeyDoesNotExist) - ErrOperandColumns = dbterror.ClassOptimizer.NewStd(mysql.ErrOperandColumns) - ErrInvalidGroupFuncUse = dbterror.ClassOptimizer.NewStd(mysql.ErrInvalidGroupFuncUse) - ErrIllegalReference = dbterror.ClassOptimizer.NewStd(mysql.ErrIllegalReference) - ErrNoDB = dbterror.ClassOptimizer.NewStd(mysql.ErrNoDB) - ErrUnknownExplainFormat = dbterror.ClassOptimizer.NewStd(mysql.ErrUnknownExplainFormat) - ErrWrongGroupField = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongGroupField) - ErrDupFieldName = dbterror.ClassOptimizer.NewStd(mysql.ErrDupFieldName) - ErrNonUpdatableTable = dbterror.ClassOptimizer.NewStd(mysql.ErrNonUpdatableTable) - ErrInternal = dbterror.ClassOptimizer.NewStd(mysql.ErrInternal) - ErrNonUniqTable = dbterror.ClassOptimizer.NewStd(mysql.ErrNonuniqTable) - ErrWindowInvalidWindowFuncUse = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowInvalidWindowFuncUse) - ErrWindowInvalidWindowFuncAliasUse = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowInvalidWindowFuncAliasUse) - ErrWindowNoSuchWindow = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowNoSuchWindow) - ErrWindowCircularityInWindowGraph = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowCircularityInWindowGraph) - ErrWindowNoChildPartitioning = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowNoChildPartitioning) - ErrWindowNoInherentFrame = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowNoInherentFrame) - ErrWindowNoRedefineOrderBy = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowNoRedefineOrderBy) - ErrWindowDuplicateName = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowDuplicateName) - ErrPartitionClauseOnNonpartitioned = dbterror.ClassOptimizer.NewStd(mysql.ErrPartitionClauseOnNonpartitioned) - ErrWindowFrameStartIllegal = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowFrameStartIllegal) - ErrWindowFrameEndIllegal = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowFrameEndIllegal) - ErrWindowFrameIllegal = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowFrameIllegal) - ErrWindowRangeFrameOrderType = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRangeFrameOrderType) - ErrWindowRangeFrameTemporalType = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRangeFrameTemporalType) - ErrWindowRangeFrameNumericType = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRangeFrameNumericType) - ErrWindowRangeBoundNotConstant = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRangeBoundNotConstant) - ErrWindowRowsIntervalUse = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowRowsIntervalUse) - ErrWindowFunctionIgnoresFrame = dbterror.ClassOptimizer.NewStd(mysql.ErrWindowFunctionIgnoresFrame) - ErrUnsupportedOnGeneratedColumn = dbterror.ClassOptimizer.NewStd(mysql.ErrUnsupportedOnGeneratedColumn) - ErrPrivilegeCheckFail = dbterror.ClassOptimizer.NewStd(mysql.ErrPrivilegeCheckFail) - ErrInvalidWildCard = dbterror.ClassOptimizer.NewStd(mysql.ErrInvalidWildCard) - ErrMixOfGroupFuncAndFields = dbterror.ClassOptimizer.NewStd(mysql.ErrMixOfGroupFuncAndFieldsIncompatible) - errTooBigPrecision = dbterror.ClassExpression.NewStd(mysql.ErrTooBigPrecision) - ErrDBaccessDenied = dbterror.ClassOptimizer.NewStd(mysql.ErrDBaccessDenied) - ErrTableaccessDenied = dbterror.ClassOptimizer.NewStd(mysql.ErrTableaccessDenied) - ErrSpecificAccessDenied = dbterror.ClassOptimizer.NewStd(mysql.ErrSpecificAccessDenied) - ErrViewNoExplain = dbterror.ClassOptimizer.NewStd(mysql.ErrViewNoExplain) - ErrWrongValueCountOnRow = dbterror.ClassOptimizer.NewStd(mysql.ErrWrongValueCountOnRow) - ErrViewInvalid = dbterror.ClassOptimizer.NewStd(mysql.ErrViewInvalid) - ErrNoSuchThread = dbterror.ClassOptimizer.NewStd(mysql.ErrNoSuchThread) - ErrUnknownColumn = dbterror.ClassOptimizer.NewStd(mysql.ErrBadField) - ErrCartesianProductUnsupported = dbterror.ClassOptimizer.NewStd(mysql.ErrCartesianProductUnsupported) - ErrStmtNotFound = dbterror.ClassOptimizer.NewStd(mysql.ErrPreparedStmtNotFound) - ErrAmbiguous = dbterror.ClassOptimizer.NewStd(mysql.ErrNonUniq) - ErrUnresolvedHintName = dbterror.ClassOptimizer.NewStd(mysql.ErrUnresolvedHintName) - ErrNotHintUpdatable = dbterror.ClassOptimizer.NewStd(mysql.ErrNotHintUpdatable) - ErrWarnConflictingHint = dbterror.ClassOptimizer.NewStd(mysql.ErrWarnConflictingHint) ->>>>>>> f81a5d131... planner: check view recursion when building source from view (#20398) // Since we cannot know if user logged in with a password, use message of ErrAccessDeniedNoPassword instead ErrAccessDenied = terror.ClassOptimizer.New(mysql.ErrAccessDenied, mysql.MySQLErrName[mysql.ErrAccessDeniedNoPassword]) ) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 49cf7cdf2e643..b2f777fa7b39b 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -444,19 +444,11 @@ type PlanBuilder struct { // SelectLock need this information to locate the lock on partitions. partitionedTable []table.PartitionedTable -<<<<<<< HEAD - // CreateView needs this information to check whether exists nested view. - underlyingViewNames set.StringSet -======= + // buildingViewStack is used to check whether there is a recursive view. buildingViewStack set.StringSet // renamingViewName is the name of the view which is being renamed. renamingViewName string - - // evalDefaultExpr needs this information to find the corresponding column. - // It stores the OutputNames before buildProjection. - allNames [][]*types.FieldName ->>>>>>> f81a5d131... planner: check view recursion when building source from view (#20398) } type handleColHelper struct { From d9d06a3619a399a977d95fccaf36c02ff31026dc Mon Sep 17 00:00:00 2001 From: Feng Liyuan Date: Tue, 17 Nov 2020 15:40:51 +0800 Subject: [PATCH 3/3] Update planbuilder.go --- planner/core/planbuilder.go | 1 - 1 file changed, 1 deletion(-) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 24823faa49a87..d484ca01aae41 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -444,7 +444,6 @@ type PlanBuilder struct { // SelectLock need this information to locate the lock on partitions. partitionedTable []table.PartitionedTable - // buildingViewStack is used to check whether there is a recursive view. buildingViewStack set.StringSet // renamingViewName is the name of the view which is being renamed.