Skip to content

Commit

Permalink
planner: forbiden nested view creation (pingcap#15420) (pingcap#15424)
Browse files Browse the repository at this point in the history
  • Loading branch information
sre-bot authored Mar 26, 2020
1 parent a490e0e commit c6d91a1
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 0 deletions.
9 changes: 9 additions & 0 deletions executor/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@ func (s *testSuite3) TestCreateView(c *C) {
tk.MustExec("drop view v")
tk.MustExec("create view v as (select * from t1 union select * from t2)")
tk.MustExec("drop view v")

// Test for create nested view.
tk.MustExec("create table test_v_nested(a int)")
tk.MustExec("create definer='root'@'localhost' view v_nested as select * from test_v_nested")
tk.MustExec("create definer='root'@'localhost' view v_nested2 as select * from v_nested")
_, err = tk.Exec("create or replace definer='root'@'localhost' view v_nested as select * from v_nested2")
c.Assert(terror.ErrorEqual(err, plannercore.ErrNoSuchTable), IsTrue)
tk.MustExec("drop table test_v_nested")
tk.MustExec("drop view v_nested, v_nested2")
}

func (s *testSuite3) TestCreateViewWithOverlongColName(c *C) {
Expand Down
1 change: 1 addition & 0 deletions planner/core/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ var (
ErrWindowNoRedefineOrderBy = terror.ClassOptimizer.New(codeWindowNoRedefineOrderBy, mysql.MySQLErrName[mysql.ErrWindowNoRedefineOrderBy])
ErrWindowDuplicateName = terror.ClassOptimizer.New(codeWindowDuplicateName, mysql.MySQLErrName[mysql.ErrWindowDuplicateName])
ErrPartitionClauseOnNonpartitioned = terror.ClassOptimizer.New(codePartitionClauseOnNonpartitioned, mysql.MySQLErrName[mysql.ErrPartitionClauseOnNonpartitioned])
ErrNoSuchTable = terror.ClassOptimizer.New(mysql.ErrNoSuchTable, mysql.MySQLErrName[mysql.ErrNoSuchTable])
errTooBigPrecision = terror.ClassExpression.New(mysql.ErrTooBigPrecision, mysql.MySQLErrName[mysql.ErrTooBigPrecision])
ErrDBaccessDenied = terror.ClassOptimizer.New(mysql.ErrDBaccessDenied, mysql.MySQLErrName[mysql.ErrDBaccessDenied])
ErrTableaccessDenied = terror.ClassOptimizer.New(mysql.ErrTableaccessDenied, mysql.MySQLErrName[mysql.ErrTableaccessDenied])
Expand Down
3 changes: 3 additions & 0 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2234,6 +2234,9 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName) (L
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SelectPriv, dbName.L, tableInfo.Name.L, "", authErr)

if tableInfo.IsView() {
if b.capFlag&collectUnderlyingViewName != 0 {
b.underlyingViewNames.Insert(dbName.L + "." + tn.Name.L)
}
return b.BuildDataSourceFromView(ctx, dbName, tableInfo)
}

Expand Down
12 changes: 12 additions & 0 deletions planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/logutil"
"github.com/pingcap/tidb/util/ranger"
"github.com/pingcap/tidb/util/set"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -169,6 +170,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
)

// PlanBuilder builds Plan from an ast.Node.
Expand Down Expand Up @@ -203,6 +207,8 @@ type PlanBuilder struct {

// SelectLock need this information to locate the lock on partitions.
partitionedTable []table.PartitionedTable
// CreateView needs this information to check whether exists nested view.
underlyingViewNames set.StringSet
}

// GetVisitInfo gets the visitInfo of the PlanBuilder.
Expand Down Expand Up @@ -2195,13 +2201,19 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err
}
case *ast.CreateViewStmt:
b.capFlag |= canExpandAST
b.capFlag |= collectUnderlyingViewName
defer func() {
b.capFlag &= ^canExpandAST
b.capFlag &= ^collectUnderlyingViewName
}()
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()
if v.Cols == nil {
adjustOverlongViewColname(plan.(LogicalPlan))
Expand Down

0 comments on commit c6d91a1

Please sign in to comment.