Skip to content

Commit

Permalink
planner,executor: basic support for DROP_VIEW (pingcap#8758)
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewDi authored and zz-jason committed Jan 4, 2019
1 parent 6a9ad3f commit e646276
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 30 deletions.
5 changes: 5 additions & 0 deletions ddl/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ var (
ErrCoalesceOnlyOnHashPartition = terror.ClassDDL.New(codeCoalesceOnlyOnHashPartition, mysql.MySQLErrName[mysql.ErrCoalesceOnlyOnHashPartition])
// ErrViewWrongList returns create view must include all columns in the select clause
ErrViewWrongList = terror.ClassDDL.New(codeViewWrongList, mysql.MySQLErrName[mysql.ErrViewWrongList])
// ErrTableIsNotView returns for table is not base table.
ErrTableIsNotView = terror.ClassDDL.New(codeErrWrongObject, "'%s.%s' is not VIEW")
)

// DDL is responsible for updating schema in data store and maintaining in-memory InfoSchema cache.
Expand All @@ -213,6 +215,7 @@ type DDL interface {
CreateView(ctx sessionctx.Context, stmt *ast.CreateViewStmt) error
CreateTableWithLike(ctx sessionctx.Context, ident, referIdent ast.Ident, ifNotExists bool) error
DropTable(ctx sessionctx.Context, tableIdent ast.Ident) (err error)
DropView(ctx sessionctx.Context, tableIdent ast.Ident) (err error)
CreateIndex(ctx sessionctx.Context, tableIdent ast.Ident, unique bool, indexName model.CIStr,
columnNames []*ast.IndexColName, indexOption *ast.IndexOption) error
DropIndex(ctx sessionctx.Context, tableIdent ast.Ident, indexName model.CIStr) error
Expand Down Expand Up @@ -648,6 +651,7 @@ const (
codeWrongKeyColumn = 1167
codeBlobKeyWithoutLength = 1170
codeInvalidOnUpdate = 1294
codeErrWrongObject = terror.ErrCode(mysql.ErrWrongObject)
codeViewWrongList = 1353
codeUnsupportedOnGeneratedColumn = 3106
codeGeneratedColumnNonPrior = 3107
Expand Down Expand Up @@ -727,6 +731,7 @@ func init() {
codeWarnDataTruncated: mysql.WarnDataTruncated,
codeCoalesceOnlyOnHashPartition: mysql.ErrCoalesceOnlyOnHashPartition,
codeUnknownPartition: mysql.ErrUnknownPartition,
codeErrWrongObject: mysql.ErrWrongObject,
}
terror.ErrClassToMySQLCodes[terror.ClassDDL] = ddlMySQLErrCodes
}
33 changes: 31 additions & 2 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2218,8 +2218,8 @@ func (d *ddl) DropTable(ctx sessionctx.Context, ti ast.Ident) (err error) {
}

tb, err := is.TableByName(ti.Schema, ti.Name)
if err != nil {
return errors.Trace(infoschema.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name))
if err != nil || tb.Meta().IsView() {
return infoschema.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name)
}

job := &model.Job{
Expand All @@ -2234,6 +2234,35 @@ func (d *ddl) DropTable(ctx sessionctx.Context, ti ast.Ident) (err error) {
return errors.Trace(err)
}

// DropView will proceed even if some view in the list does not exists.
func (d *ddl) DropView(ctx sessionctx.Context, ti ast.Ident) (err error) {
is := d.GetInformationSchema(ctx)
schema, ok := is.SchemaByName(ti.Schema)
if !ok {
return infoschema.ErrDatabaseNotExists.GenWithStackByArgs(ti.Schema)
}

tb, err := is.TableByName(ti.Schema, ti.Name)
if err != nil {
return infoschema.ErrTableNotExists.GenWithStackByArgs(ti.Schema, ti.Name)
}

if !tb.Meta().IsView() {
return ErrTableIsNotView.GenWithStackByArgs(ti.Schema, ti.Name)
}

job := &model.Job{
SchemaID: schema.ID,
TableID: tb.Meta().ID,
Type: model.ActionDropView,
BinlogInfo: &model.HistoryInfo{},
}

err = d.doDDLJob(ctx, job)
err = d.callHookOnChanged(err)
return errors.Trace(err)
}

func (d *ddl) TruncateTable(ctx sessionctx.Context, ti ast.Ident) error {
is := d.GetInformationSchema(ctx)
schema, ok := is.SchemaByName(ti.Schema)
Expand Down
4 changes: 2 additions & 2 deletions ddl/ddl_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,8 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64,
ver, err = onCreateTable(d, t, job)
case model.ActionCreateView:
ver, err = onCreateView(d, t, job)
case model.ActionDropTable:
ver, err = onDropTable(t, job)
case model.ActionDropTable, model.ActionDropView:
ver, err = onDropTableOrView(t, job)
case model.ActionDropTablePartition:
ver, err = onDropTablePartition(t, job)
case model.ActionTruncateTablePartition:
Expand Down
6 changes: 3 additions & 3 deletions ddl/rollingback.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func rollingbackAddindex(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job) (ve
return
}

func rollingbackDropTable(t *meta.Meta, job *model.Job) error {
func rollingbackDropTableOrView(t *meta.Meta, job *model.Job) error {
tblInfo, err := checkTableExist(t, job, job.SchemaID)
if err != nil {
return errors.Trace(err)
Expand Down Expand Up @@ -200,8 +200,8 @@ func convertJob2RollbackJob(w *worker, d *ddlCtx, t *meta.Meta, job *model.Job)
ver, err = rollingbackDropColumn(t, job)
case model.ActionDropIndex:
ver, err = rollingbackDropIndex(t, job)
case model.ActionDropTable:
err = rollingbackDropTable(t, job)
case model.ActionDropTable, model.ActionDropView:
err = rollingbackDropTableOrView(t, job)
case model.ActionDropSchema:
err = rollingbackDropSchema(t, job)
default:
Expand Down
2 changes: 1 addition & 1 deletion ddl/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func onCreateView(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, _ error)
}
}

func onDropTable(t *meta.Meta, job *model.Job) (ver int64, _ error) {
func onDropTableOrView(t *meta.Meta, job *model.Job) (ver int64, _ error) {
tblInfo, err := checkTableExist(t, job, job.SchemaID)
if err != nil {
return ver, errors.Trace(err)
Expand Down
10 changes: 7 additions & 3 deletions executor/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (e *DDLExec) Next(ctx context.Context, chk *chunk.Chunk) (err error) {
case *ast.DropDatabaseStmt:
err = e.executeDropDatabase(x)
case *ast.DropTableStmt:
err = e.executeDropTable(x)
err = e.executeDropTableOrView(x)
case *ast.DropIndexStmt:
err = e.executeDropIndex(x)
case *ast.AlterTableStmt:
Expand Down Expand Up @@ -222,7 +222,7 @@ func isSystemTable(schema, table string) bool {
return false
}

func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error {
func (e *DDLExec) executeDropTableOrView(s *ast.DropTableStmt) error {
var notExistTables []string
for _, tn := range s.Tables {
fullti := ast.Ident{Schema: tn.Schema, Name: tn.Name}
Expand Down Expand Up @@ -256,7 +256,11 @@ func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error {
}
}

err = domain.GetDomain(e.ctx).DDL().DropTable(e.ctx, fullti)
if s.IsView {
err = domain.GetDomain(e.ctx).DDL().DropView(e.ctx, fullti)
} else {
err = domain.GetDomain(e.ctx).DDL().DropTable(e.ctx, fullti)
}
if infoschema.ErrDatabaseNotExists.Equal(err) || infoschema.ErrTableNotExists.Equal(err) {
notExistTables = append(notExistTables, fullti.String())
} else if err != nil {
Expand Down
45 changes: 29 additions & 16 deletions executor/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ func (s *testSuite3) TestCreateView(c *C) {
tk.MustExec("CREATE TABLE source_table (id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));")
//test create a exist view
tk.MustExec("CREATE VIEW view_t AS select id , name from source_table")
defer tk.MustExec("DROP VIEW IF EXISTS view_t")
_, err := tk.Exec("CREATE VIEW view_t AS select id , name from source_table")
c.Assert(err.Error(), Equals, "[schema:1050]Table 'test.view_t' already exists")
//create view on nonexistent table
Expand All @@ -151,31 +152,25 @@ func (s *testSuite3) TestCreateView(c *C) {
tk.MustExec("create table t1 (a int ,b int)")
tk.MustExec("insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10)")
//view with colList and SelectFieldExpr
_, err = tk.Exec("create view v1 (c) as select b+1 from t1")
c.Assert(err, IsNil)
tk.MustExec("create view v1 (c) as select b+1 from t1")
//view with SelectFieldExpr
_, err = tk.Exec("create view v2 as select b+1 from t1")
c.Assert(err, IsNil)
tk.MustExec("create view v2 as select b+1 from t1")
//view with SelectFieldExpr and AsName
_, err = tk.Exec("create view v3 as select b+1 as c from t1")
c.Assert(err, IsNil)
tk.MustExec("create view v3 as select b+1 as c from t1")
//view with colList , SelectField and AsName
_, err = tk.Exec("create view v4 (c) as select b+1 as d from t1")
c.Assert(err, IsNil)
tk.MustExec("create view v4 (c) as select b+1 as d from t1")
//view with select wild card
_, err = tk.Exec("create view v5 as select * from t1")
c.Assert(err, IsNil)
_, err = tk.Exec("create view v6 (c,d) as select * from t1")
c.Assert(err, IsNil)
tk.MustExec("create view v5 as select * from t1")
tk.MustExec("create view v6 (c,d) as select * from t1")
_, err = tk.Exec("create view v7 (c,d,e) as select * from t1")
c.Assert(err.Error(), Equals, ddl.ErrViewWrongList.Error())
tk.MustExec("drop table v1,v2,v3,v4,v5,v6")
//drop multiple views in a statement
tk.MustExec("drop view v1,v2,v3,v4,v5,v6")
//view with variable
_, err = tk.Exec("create view v1 (c,d) as select a,b+@@global.max_user_connections from t1")
c.Assert(err, IsNil)
tk.MustExec("create view v1 (c,d) as select a,b+@@global.max_user_connections from t1")
_, err = tk.Exec("create view v1 (c,d) as select a,b from t1 where a = @@global.max_user_connections")
c.Assert(err.Error(), Equals, "[schema:1050]Table 'test.v1' already exists")
tk.MustExec("drop table v1")
tk.MustExec("drop view v1")
//view with different col counts
_, err = tk.Exec("create view v1 (c,d,e) as select a,b from t1 ")
c.Assert(err.Error(), Equals, ddl.ErrViewWrongList.Error())
Expand Down Expand Up @@ -211,6 +206,24 @@ func (s *testSuite3) TestCreateDropTable(c *C) {
c.Assert(err, NotNil)
}

func (s *testSuite3) TestCreateDropView(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("create or replace view drop_test as select 1,2")
_, err := tk.Exec("drop view if exists drop_test")
c.Assert(err, IsNil)

_, err = tk.Exec("drop view mysql.gc_delete_range")
c.Assert(err.Error(), Equals, "Drop tidb system table 'mysql.gc_delete_range' is forbidden")

_, err = tk.Exec("drop view drop_test")
c.Assert(err.Error(), Equals, "[schema:1051]Unknown table 'test.drop_test'")

tk.MustExec("create table t_v(a int)")
_, err = tk.Exec("drop view t_v")
c.Assert(err.Error(), Equals, "[ddl:1347]'test.t_v' is not VIEW")
}

func (s *testSuite3) TestCreateDropIndex(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
Expand Down
8 changes: 6 additions & 2 deletions executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3434,10 +3434,14 @@ func (s *testSuite2) TearDownSuite(c *C) {
func (s *testSuite2) TearDownTest(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
r := tk.MustQuery("show tables")
r := tk.MustQuery("show full tables")
for _, tb := range r.Rows() {
tableName := tb[0]
tk.MustExec(fmt.Sprintf("drop table %v", tableName))
if tb[1] == "VIEW" {
tk.MustExec(fmt.Sprintf("drop view %v", tableName))
} else {
tk.MustExec(fmt.Sprintf("drop table %v", tableName))
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion infoschema/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (b *Builder) ApplyDiff(m *meta.Meta, diff *model.SchemaDiff) ([]int64, erro
case model.ActionCreateTable:
newTableID = diff.TableID
tblIDs = append(tblIDs, newTableID)
case model.ActionDropTable:
case model.ActionDropTable, model.ActionDropView:
oldTableID = diff.TableID
tblIDs = append(tblIDs, oldTableID)
case model.ActionTruncateTable:
Expand Down

0 comments on commit e646276

Please sign in to comment.