Skip to content

Commit

Permalink
executor: forbid user to drop important system table (#7471)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiancaiamao authored and jackysp committed Aug 29, 2018
1 parent 69d5e36 commit 55af7e1
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
31 changes: 31 additions & 0 deletions executor/ddl.go
Expand Up @@ -156,6 +156,13 @@ func (e *DDLExec) executeCreateIndex(s *ast.CreateIndexStmt) error {

func (e *DDLExec) executeDropDatabase(s *ast.DropDatabaseStmt) error {
dbName := model.NewCIStr(s.Name)

// Protect important system table from been dropped by a mistake.
// I can hardly find a case that a user really need to do this.
if dbName.L == "mysql" {
return errors.New("Drop 'mysql' database is forbidden")
}

err := domain.GetDomain(e.ctx).DDL().DropSchema(e.ctx, dbName)
if infoschema.ErrDatabaseNotExists.Equal(err) {
if s.IfExists {
Expand All @@ -179,6 +186,24 @@ func (e *DDLExec) executeDropDatabase(s *ast.DropDatabaseStmt) error {
return errors.Trace(err)
}

// If one drop those tables by mistake, it's difficult to recover.
// In the worst case, the whole TiDB cluster fails to bootstrap, so we prevent user from dropping them.
var systemTables = map[string]struct{}{
"tidb": {},
"gc_delete_range": {},
"gc_delete_range_done": {},
}

func isSystemTable(schema, table string) bool {
if schema != "mysql" {
return false
}
if _, ok := systemTables[table]; ok {
return true
}
return false
}

func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error {
var notExistTables []string
for _, tn := range s.Tables {
Expand All @@ -198,6 +223,12 @@ func (e *DDLExec) executeDropTable(s *ast.DropTableStmt) error {
return errors.Trace(err)
}

// Protect important system table from been dropped by a mistake.
// I can hardly find a case that a user really need to do this.
if isSystemTable(tn.Schema.L, tn.Name.L) {
return errors.Errorf("Drop tidb system table '%s.%s' is forbidden", tn.Schema.L, tn.Name.L)
}

if config.CheckTableBeforeDrop {
log.Warnf("admin check table `%s`.`%s` before drop.", fullti.Schema.O, fullti.Name.O)
sql := fmt.Sprintf("admin check table `%s`.`%s`", fullti.Schema.O, fullti.Name.O)
Expand Down
6 changes: 6 additions & 0 deletions executor/ddl_test.go
Expand Up @@ -128,6 +128,9 @@ func (s *testSuite) TestCreateDropDatabase(c *C) {
c.Assert(err.Error(), Equals, plan.ErrNoDB.Error())
_, err = tk.Exec("select * from t;")
c.Assert(err.Error(), Equals, plan.ErrNoDB.Error())

_, err = tk.Exec("drop database mysql")
c.Assert(err, NotNil)
}

func (s *testSuite) TestCreateDropTable(c *C) {
Expand All @@ -137,6 +140,9 @@ func (s *testSuite) TestCreateDropTable(c *C) {
tk.MustExec("drop table if exists drop_test")
tk.MustExec("create table drop_test (a int)")
tk.MustExec("drop table drop_test")

_, err := tk.Exec("drop table mysql.gc_delete_range")
c.Assert(err, NotNil)
}

func (s *testSuite) TestCreateDropIndex(c *C) {
Expand Down

0 comments on commit 55af7e1

Please sign in to comment.