From 8c118cecc2a43130ea214920a87b48bd5160becb Mon Sep 17 00:00:00 2001 From: crazycs Date: Mon, 8 Apr 2019 15:21:37 +0800 Subject: [PATCH] *: clean code for restore table (#9090) --- ddl/ddl.go | 2 +- ddl/ddl_api.go | 6 +-- ddl/ddl_worker.go | 16 +++--- ddl/serial_test.go | 94 ++++++++++++++++++------------------ ddl/table.go | 48 +++++++++--------- executor/builder.go | 12 ----- executor/ddl.go | 68 +++++++------------------- go.mod | 2 +- go.sum | 4 +- infoschema/builder.go | 2 +- planner/core/common_plans.go | 8 --- planner/core/planbuilder.go | 11 ++--- planner/core/preprocess.go | 10 ++-- 13 files changed, 112 insertions(+), 171 deletions(-) diff --git a/ddl/ddl.go b/ddl/ddl.go index c21ac119c4def..e2ca983d82902 100644 --- a/ddl/ddl.go +++ b/ddl/ddl.go @@ -242,7 +242,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) - RestoreTable(ctx sessionctx.Context, tbInfo *model.TableInfo, schemaID, autoID, dropJobID int64, snapshotTS uint64) (err error) + RecoverTable(ctx sessionctx.Context, tbInfo *model.TableInfo, schemaID, autoID, dropJobID int64, snapshotTS uint64) (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 diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index faf2953f56ed2..8a83294f627a9 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -1207,7 +1207,7 @@ func (d *ddl) CreateTable(ctx sessionctx.Context, s *ast.CreateTableStmt) (err e return errors.Trace(err) } -func (d *ddl) RestoreTable(ctx sessionctx.Context, tbInfo *model.TableInfo, schemaID, autoID, dropJobID int64, snapshotTS uint64) (err error) { +func (d *ddl) RecoverTable(ctx sessionctx.Context, tbInfo *model.TableInfo, schemaID, autoID, dropJobID int64, snapshotTS uint64) (err error) { is := d.GetInfoSchemaWithInterceptor(ctx) // Check schema exist. schema, ok := is.SchemaByID(schemaID) @@ -1225,9 +1225,9 @@ func (d *ddl) RestoreTable(ctx sessionctx.Context, tbInfo *model.TableInfo, sche job := &model.Job{ SchemaID: schemaID, TableID: tbInfo.ID, - Type: model.ActionRestoreTable, + Type: model.ActionRecoverTable, BinlogInfo: &model.HistoryInfo{}, - Args: []interface{}{tbInfo, autoID, dropJobID, snapshotTS, restoreTableCheckFlagNone}, + Args: []interface{}{tbInfo, autoID, dropJobID, snapshotTS, recoverTableCheckFlagNone}, } err = d.doDDLJob(ctx, job) err = d.callHookOnChanged(err) diff --git a/ddl/ddl_worker.go b/ddl/ddl_worker.go index 7292c42a0da28..3a0e9c8f74459 100644 --- a/ddl/ddl_worker.go +++ b/ddl/ddl_worker.go @@ -285,8 +285,8 @@ func (w *worker) finishDDLJob(t *meta.Meta, job *model.Job) (err error) { } } switch job.Type { - case model.ActionRestoreTable: - err = finishRestoreTable(w, t, job) + case model.ActionRecoverTable: + err = finishRecoverTable(w, t, job) } if err != nil { return errors.Trace(err) @@ -303,15 +303,15 @@ func (w *worker) finishDDLJob(t *meta.Meta, job *model.Job) (err error) { return errors.Trace(err) } -func finishRestoreTable(w *worker, t *meta.Meta, job *model.Job) error { +func finishRecoverTable(w *worker, t *meta.Meta, job *model.Job) error { tbInfo := &model.TableInfo{} - var autoID, dropJobID, restoreTableCheckFlag int64 + var autoID, dropJobID, recoverTableCheckFlag int64 var snapshotTS uint64 - err := job.DecodeArgs(tbInfo, &autoID, &dropJobID, &snapshotTS, &restoreTableCheckFlag) + err := job.DecodeArgs(tbInfo, &autoID, &dropJobID, &snapshotTS, &recoverTableCheckFlag) if err != nil { return errors.Trace(err) } - if restoreTableCheckFlag == restoreTableCheckFlagEnableGC { + if recoverTableCheckFlag == recoverTableCheckFlagEnableGC { err = enableGC(w) if err != nil { return errors.Trace(err) @@ -532,8 +532,8 @@ func (w *worker) runDDLJob(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, ver, err = onAddTablePartition(t, job) case model.ActionModifyTableCharsetAndCollate: ver, err = onModifyTableCharsetAndCollate(t, job) - case model.ActionRestoreTable: - ver, err = w.onRestoreTable(d, t, job) + case model.ActionRecoverTable: + ver, err = w.onRecoverTable(d, t, job) default: // Invalid job, cancel it. job.State = model.JobStateCancelled diff --git a/ddl/serial_test.go b/ddl/serial_test.go index 0dbc9c2b20a00..1b1a50313b357 100644 --- a/ddl/serial_test.go +++ b/ddl/serial_test.go @@ -128,10 +128,10 @@ func (s *testSerialSuite) TestCancelAddIndexPanic(c *C) { c.Assert(err.Error(), Equals, "[ddl:12]cancelled DDL job") } -func (s *testSerialSuite) TestRestoreTableByJobID(c *C) { +func (s *testSerialSuite) TestRecoverTableByJobID(c *C) { tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_restore") - tk.MustExec("use test_restore") + tk.MustExec("create database if not exists test_recover") + tk.MustExec("use test_recover") tk.MustExec("drop table if exists t_recover") tk.MustExec("create table t_recover (a int);") defer func(originGC bool) { @@ -162,19 +162,19 @@ func (s *testSerialSuite) TestRestoreTableByJobID(c *C) { rows, err := session.GetRows4Test(context.Background(), tk.Se, rs) c.Assert(err, IsNil) row := rows[0] - c.Assert(row.GetString(1), Equals, "test_restore") + c.Assert(row.GetString(1), Equals, "test_recover") c.Assert(row.GetString(3), Equals, "drop table") jobID := row.GetInt64(0) // if GC safe point is not exists in mysql.tidb - _, err = tk.Exec(fmt.Sprintf("admin restore table by job %d", jobID)) + _, err = tk.Exec(fmt.Sprintf("recover table by job %d", jobID)) c.Assert(err, NotNil) c.Assert(err.Error(), Equals, "can not get 'tikv_gc_safe_point'") // set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // if GC enable is not exists in mysql.tidb - _, err = tk.Exec(fmt.Sprintf("admin restore table by job %d", jobID)) + _, err = tk.Exec(fmt.Sprintf("recover table by job %d", jobID)) c.Assert(err, NotNil) c.Assert(err.Error(), Equals, "[ddl:-1]can not get 'tikv_gc_enable'") @@ -183,7 +183,7 @@ func (s *testSerialSuite) TestRestoreTableByJobID(c *C) { // recover job is before GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeAfterDrop)) - _, err = tk.Exec(fmt.Sprintf("admin restore table by job %d", jobID)) + _, err = tk.Exec(fmt.Sprintf("recover table by job %d", jobID)) c.Assert(err, NotNil) c.Assert(strings.Contains(err.Error(), "snapshot is older than GC safe point"), Equals, true) @@ -191,14 +191,14 @@ func (s *testSerialSuite) TestRestoreTableByJobID(c *C) { tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // if there is a new table with the same name, should return failed. tk.MustExec("create table t_recover (a int);") - _, err = tk.Exec(fmt.Sprintf("admin restore table by job %d", jobID)) + _, err = tk.Exec(fmt.Sprintf("recover table by job %d", jobID)) c.Assert(err.Error(), Equals, infoschema.ErrTableExists.GenWithStackByArgs("t_recover").Error()) - // drop the new table with the same name, then restore table. + // drop the new table with the same name, then recover table. tk.MustExec("drop table t_recover") - // do restore table. - tk.MustExec(fmt.Sprintf("admin restore table by job %d", jobID)) + // do recover table. + tk.MustExec(fmt.Sprintf("recover table by job %d", jobID)) // check recover table meta and data record. tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3")) @@ -206,8 +206,8 @@ func (s *testSerialSuite) TestRestoreTableByJobID(c *C) { tk.MustExec("insert into t_recover values (4),(5),(6)") tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) - // restore table by none exits job. - _, err = tk.Exec(fmt.Sprintf("admin restore table by job %d", 10000000)) + // recover table by none exits job. + _, err = tk.Exec(fmt.Sprintf("recover table by job %d", 10000000)) c.Assert(err, NotNil) // Disable GC by manual first, then after recover table, the GC enable status should also be disabled. @@ -221,11 +221,11 @@ func (s *testSerialSuite) TestRestoreTableByJobID(c *C) { rows, err = session.GetRows4Test(context.Background(), tk.Se, rs) c.Assert(err, IsNil) row = rows[0] - c.Assert(row.GetString(1), Equals, "test_restore") + c.Assert(row.GetString(1), Equals, "test_recover") c.Assert(row.GetString(3), Equals, "drop table") jobID = row.GetInt64(0) - tk.MustExec(fmt.Sprintf("admin restore table by job %d", jobID)) + tk.MustExec(fmt.Sprintf("recover table by job %d", jobID)) // check recover table meta and data record. tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1")) @@ -238,10 +238,10 @@ func (s *testSerialSuite) TestRestoreTableByJobID(c *C) { c.Assert(gcEnable, Equals, false) } -func (s *testSerialSuite) TestRestoreTableByTableName(c *C) { +func (s *testSerialSuite) TestRecoverTableByTableName(c *C) { tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_restore") - tk.MustExec("use test_restore") + tk.MustExec("create database if not exists test_recover") + tk.MustExec("use test_recover") tk.MustExec("drop table if exists t_recover, t_recover2") tk.MustExec("create table t_recover (a int);") defer func(originGC bool) { @@ -268,14 +268,14 @@ func (s *testSerialSuite) TestRestoreTableByTableName(c *C) { tk.MustExec("drop table t_recover") // if GC safe point is not exists in mysql.tidb - _, err := tk.Exec("admin restore table t_recover") + _, err := tk.Exec("recover table t_recover") c.Assert(err, NotNil) c.Assert(err.Error(), Equals, "can not get 'tikv_gc_safe_point'") // set GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // if GC enable is not exists in mysql.tidb - _, err = tk.Exec("admin restore table t_recover") + _, err = tk.Exec("recover table t_recover") c.Assert(err, NotNil) c.Assert(err.Error(), Equals, "[ddl:-1]can not get 'tikv_gc_enable'") @@ -284,7 +284,7 @@ func (s *testSerialSuite) TestRestoreTableByTableName(c *C) { // recover job is before GC safe point tk.MustExec(fmt.Sprintf(safePointSQL, timeAfterDrop)) - _, err = tk.Exec("admin restore table t_recover") + _, err = tk.Exec("recover table t_recover") c.Assert(err, NotNil) c.Assert(strings.Contains(err.Error(), "snapshot is older than GC safe point"), Equals, true) @@ -292,14 +292,14 @@ func (s *testSerialSuite) TestRestoreTableByTableName(c *C) { tk.MustExec(fmt.Sprintf(safePointSQL, timeBeforeDrop)) // if there is a new table with the same name, should return failed. tk.MustExec("create table t_recover (a int);") - _, err = tk.Exec("admin restore table t_recover") + _, err = tk.Exec("recover table t_recover") c.Assert(err.Error(), Equals, infoschema.ErrTableExists.GenWithStackByArgs("t_recover").Error()) - // drop the new table with the same name, then restore table. + // drop the new table with the same name, then recover table. tk.MustExec("rename table t_recover to t_recover2") - // do restore table. - tk.MustExec("admin restore table t_recover") + // do recover table. + tk.MustExec("recover table t_recover") // check recover table meta and data record. tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3")) @@ -309,8 +309,8 @@ func (s *testSerialSuite) TestRestoreTableByTableName(c *C) { // check rebase auto id. tk.MustQuery("select a,_tidb_rowid from t_recover;").Check(testkit.Rows("1 1", "2 2", "3 3", "4 5001", "5 5002", "6 5003")) - // restore table by none exits job. - _, err = tk.Exec(fmt.Sprintf("admin restore table by job %d", 10000000)) + // recover table by none exits job. + _, err = tk.Exec(fmt.Sprintf("recover table by job %d", 10000000)) c.Assert(err, NotNil) // Disable GC by manual first, then after recover table, the GC enable status should also be disabled. @@ -320,7 +320,7 @@ func (s *testSerialSuite) TestRestoreTableByTableName(c *C) { tk.MustExec("delete from t_recover where a > 1") tk.MustExec("drop table t_recover") - tk.MustExec("admin restore table t_recover") + tk.MustExec("recover table t_recover") // check recover table meta and data record. tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1")) @@ -333,10 +333,10 @@ func (s *testSerialSuite) TestRestoreTableByTableName(c *C) { c.Assert(gcEnable, Equals, false) } -func (s *testSerialSuite) TestRestoreTableByJobIDFail(c *C) { +func (s *testSerialSuite) TestRecoverTableByJobIDFail(c *C) { tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_restore") - tk.MustExec("use test_restore") + tk.MustExec("create database if not exists test_recover") + tk.MustExec("use test_recover") tk.MustExec("drop table if exists t_recover") tk.MustExec("create table t_recover (a int);") defer func(originGC bool) { @@ -364,7 +364,7 @@ func (s *testSerialSuite) TestRestoreTableByJobIDFail(c *C) { rows, err := session.GetRows4Test(context.Background(), tk.Se, rs) c.Assert(err, IsNil) row := rows[0] - c.Assert(row.GetString(1), Equals, "test_restore") + c.Assert(row.GetString(1), Equals, "test_recover") c.Assert(row.GetString(3), Equals, "drop table") jobID := row.GetInt64(0) @@ -376,21 +376,21 @@ func (s *testSerialSuite) TestRestoreTableByJobIDFail(c *C) { // set hook hook := &ddl.TestDDLCallback{} hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionRestoreTable { + if job.Type == model.ActionRecoverTable { gofail.Enable("github.com/pingcap/tidb/store/tikv/mockCommitError", `return(true)`) - gofail.Enable("github.com/pingcap/tidb/ddl/mockRestoreTableCommitErr", `return(true)`) + gofail.Enable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr", `return(true)`) } } origHook := s.dom.DDL().GetHook() defer s.dom.DDL().(ddl.DDLForTest).SetHook(origHook) s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - // do restore table. - tk.MustExec(fmt.Sprintf("admin restore table by job %d", jobID)) + // do recover table. + tk.MustExec(fmt.Sprintf("recover table by job %d", jobID)) gofail.Disable("github.com/pingcap/tidb/store/tikv/mockCommitError") - gofail.Disable("github.com/pingcap/tidb/ddl/mockRestoreTableCommitErr") + gofail.Disable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr") - // make sure enable GC after restore table. + // make sure enable GC after recover table. enable, err := gcutil.CheckGCEnable(tk.Se) c.Assert(err, IsNil) c.Assert(enable, Equals, true) @@ -402,10 +402,10 @@ func (s *testSerialSuite) TestRestoreTableByJobIDFail(c *C) { tk.MustQuery("select * from t_recover;").Check(testkit.Rows("1", "2", "3", "4", "5", "6")) } -func (s *testSerialSuite) TestRestoreTableByTableNameFail(c *C) { +func (s *testSerialSuite) TestRecoverTableByTableNameFail(c *C) { tk := testkit.NewTestKit(c, s.store) - tk.MustExec("create database if not exists test_restore") - tk.MustExec("use test_restore") + tk.MustExec("create database if not exists test_recover") + tk.MustExec("use test_recover") tk.MustExec("drop table if exists t_recover") tk.MustExec("create table t_recover (a int);") defer func(originGC bool) { @@ -436,21 +436,21 @@ func (s *testSerialSuite) TestRestoreTableByTableNameFail(c *C) { // set hook hook := &ddl.TestDDLCallback{} hook.OnJobRunBeforeExported = func(job *model.Job) { - if job.Type == model.ActionRestoreTable { + if job.Type == model.ActionRecoverTable { gofail.Enable("github.com/pingcap/tidb/store/tikv/mockCommitError", `return(true)`) - gofail.Enable("github.com/pingcap/tidb/ddl/mockRestoreTableCommitErr", `return(true)`) + gofail.Enable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr", `return(true)`) } } origHook := s.dom.DDL().GetHook() defer s.dom.DDL().(ddl.DDLForTest).SetHook(origHook) s.dom.DDL().(ddl.DDLForTest).SetHook(hook) - // do restore table. - tk.MustExec("admin restore table t_recover") + // do recover table. + tk.MustExec("recover table t_recover") gofail.Disable("github.com/pingcap/tidb/store/tikv/mockCommitError") - gofail.Disable("github.com/pingcap/tidb/ddl/mockRestoreTableCommitErr") + gofail.Disable("github.com/pingcap/tidb/ddl/mockRecoverTableCommitErr") - // make sure enable GC after restore table. + // make sure enable GC after recover table. enable, err := gcutil.CheckGCEnable(tk.Se) c.Assert(err, IsNil) c.Assert(enable, Equals, true) diff --git a/ddl/table.go b/ddl/table.go index 253d2482af2ae..d0dd67816d7db 100644 --- a/ddl/table.go +++ b/ddl/table.go @@ -167,17 +167,17 @@ func onDropTableOrView(t *meta.Meta, job *model.Job) (ver int64, _ error) { } const ( - restoreTableCheckFlagNone int64 = iota - restoreTableCheckFlagEnableGC - restoreTableCheckFlagDisableGC + recoverTableCheckFlagNone int64 = iota + recoverTableCheckFlagEnableGC + recoverTableCheckFlagDisableGC ) -func (w *worker) onRestoreTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { +func (w *worker) onRecoverTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err error) { schemaID := job.SchemaID tblInfo := &model.TableInfo{} - var autoID, dropJobID, restoreTableCheckFlag int64 + var autoID, dropJobID, recoverTableCheckFlag int64 var snapshotTS uint64 - if err = job.DecodeArgs(tblInfo, &autoID, &dropJobID, &snapshotTS, &restoreTableCheckFlag); err != nil { + if err = job.DecodeArgs(tblInfo, &autoID, &dropJobID, &snapshotTS, &recoverTableCheckFlag); err != nil { // Invalid arguments, cancel this job. job.State = model.JobStateCancelled return ver, errors.Trace(err) @@ -195,19 +195,19 @@ func (w *worker) onRestoreTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in return ver, errors.Trace(err) } - // Restore table divide into 2 steps: - // 1. Check GC enable status, to decided whether enable GC after restore table. + // Recover table divide into 2 steps: + // 1. Check GC enable status, to decided whether enable GC after recover table. // a. Why not disable GC before put the job to DDL job queue? - // Think about concurrency problem. If a restore job-1 is doing and already disabled GC, - // then, another restore table job-2 check GC enable will get disable before into the job queue. - // then, after restore table job-2 finished, the GC will be disabled. - // b. Why split into 2 steps? 1 step also can finish this job: check GC -> disable GC -> restore table -> finish job. + // Think about concurrency problem. If a recover job-1 is doing and already disabled GC, + // then, another recover table job-2 check GC enable will get disable before into the job queue. + // then, after recover table job-2 finished, the GC will be disabled. + // b. Why split into 2 steps? 1 step also can finish this job: check GC -> disable GC -> recover table -> finish job. // What if the transaction commit failed? then, the job will retry, but the GC already disabled when first running. // So, after this job retry succeed, the GC will be disabled. - // 2. Do restore table job. + // 2. Do recover table job. // a. Check whether GC enabled, if enabled, disable GC first. - // b. Check GC safe point. If drop table time if after safe point time, then can do restore. - // otherwise, can't restore table, because the records of the table may already delete by gc. + // b. Check GC safe point. If drop table time if after safe point time, then can do recover. + // otherwise, can't recover table, because the records of the table may already delete by gc. // c. Remove GC task of the table from gc_delete_range table. // d. Create table and rebase table auto ID. // e. Finish. @@ -216,9 +216,9 @@ func (w *worker) onRestoreTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in // none -> write only // check GC enable and update flag. if gcEnable { - job.Args[len(job.Args)-1] = restoreTableCheckFlagEnableGC + job.Args[len(job.Args)-1] = recoverTableCheckFlagEnableGC } else { - job.Args[len(job.Args)-1] = restoreTableCheckFlagDisableGC + job.Args[len(job.Args)-1] = recoverTableCheckFlagDisableGC } job.SchemaState = model.StateWriteOnly @@ -229,7 +229,7 @@ func (w *worker) onRestoreTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in } case model.StateWriteOnly: // write only -> public - // do restore table. + // do recover table. if gcEnable { err = disableGC(w) if err != nil { @@ -256,9 +256,9 @@ func (w *worker) onRestoreTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in return ver, errors.Trace(err) } - // gofail: var mockRestoreTableCommitErr bool - // if mockRestoreTableCommitErr && mockRestoreTableCommitErrOnce { - // mockRestoreTableCommitErrOnce = false + // gofail: var mockRecoverTableCommitErr bool + // if mockRecoverTableCommitErr && mockRecoverTableCommitErrOnce { + // mockRecoverTableCommitErrOnce = false // kv.MockCommitErrorEnable() // } @@ -270,13 +270,13 @@ func (w *worker) onRestoreTable(d *ddlCtx, t *meta.Meta, job *model.Job) (ver in // Finish this job. job.FinishTableJob(model.JobStateDone, model.StatePublic, ver, tblInfo) default: - return ver, ErrInvalidTableState.GenWithStack("invalid restore table state %v", tblInfo.State) + return ver, ErrInvalidTableState.GenWithStack("invalid recover table state %v", tblInfo.State) } return ver, nil } -// mockRestoreTableCommitErrOnce uses to make sure `mockRestoreTableCommitErr` only mock error once. -var mockRestoreTableCommitErrOnce = true +// mockRecoverTableCommitErrOnce uses to make sure `mockRecoverTableCommitErr` only mock error once. +var mockRecoverTableCommitErrOnce = true func enableGC(w *worker) error { ctx, err := w.sessPool.get() diff --git a/executor/builder.go b/executor/builder.go index 31ac09a75c354..1960fac2096bb 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -92,8 +92,6 @@ func (b *executorBuilder) build(p plannercore.Plan) Executor { return b.buildCheckIndexRange(v) case *plannercore.ChecksumTable: return b.buildChecksumTable(v) - case *plannercore.RestoreTable: - return b.buildRestoreTable(v) case *plannercore.DDL: return b.buildDDL(v) case *plannercore.Deallocate: @@ -357,16 +355,6 @@ func (b *executorBuilder) buildRecoverIndex(v *plannercore.RecoverIndex) Executo return e } -func (b *executorBuilder) buildRestoreTable(v *plannercore.RestoreTable) Executor { - e := &RestoreTableExec{ - baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ExplainID()), - jobID: v.JobID, - Table: v.Table, - JobNum: v.JobNum, - } - return e -} - func buildCleanupIndexCols(tblInfo *model.TableInfo, indexInfo *model.IndexInfo) []*model.ColumnInfo { columns := make([]*model.ColumnInfo, 0, len(indexInfo.Columns)+1) for _, idxCol := range indexInfo.Columns { diff --git a/executor/ddl.go b/executor/ddl.go index d1e5f582795d2..e157bce138775 100644 --- a/executor/ddl.go +++ b/executor/ddl.go @@ -105,6 +105,8 @@ func (e *DDLExec) Next(ctx context.Context, req *chunk.RecordBatch) (err error) err = e.executeAlterTable(x) case *ast.RenameTableStmt: err = e.executeRenameTable(x) + case *ast.RecoverTableStmt: + err = e.executeRecoverTable(x) } if err != nil { return e.toErr(err) @@ -296,46 +298,10 @@ func (e *DDLExec) executeAlterTable(s *ast.AlterTableStmt) error { return err } -// RestoreTableExec represents a recover table executor. -// It is built from "admin restore table by job" statement, +// executeRecoverTable represents a recover table executor. +// It is built from "recover table" statement, // is used to recover the table that deleted by mistake. -type RestoreTableExec struct { - baseExecutor - jobID int64 - Table *ast.TableName - JobNum int64 -} - -// Open implements the Executor Open interface. -func (e *RestoreTableExec) Open(ctx context.Context) error { - return e.baseExecutor.Open(ctx) -} - -// Next implements the Executor Open interface. -func (e *RestoreTableExec) Next(ctx context.Context, req *chunk.RecordBatch) (err error) { - // Should commit the previous transaction and create a new transaction. - if err = e.ctx.NewTxn(ctx); err != nil { - return err - } - defer func() { e.ctx.GetSessionVars().StmtCtx.IsDDLJobInQueue = false }() - - err = e.executeRestoreTable() - if err != nil { - return err - } - - dom := domain.GetDomain(e.ctx) - // Update InfoSchema in TxnCtx, so it will pass schema check. - is := dom.InfoSchema() - txnCtx := e.ctx.GetSessionVars().TxnCtx - txnCtx.InfoSchema = is - txnCtx.SchemaVersion = is.SchemaMetaVersion() - // DDL will force commit old transaction, after DDL, in transaction status should be false. - e.ctx.GetSessionVars().SetStatusFlag(mysql.ServerStatusInTrans, false) - return nil -} - -func (e *RestoreTableExec) executeRestoreTable() error { +func (e *DDLExec) executeRecoverTable(s *ast.RecoverTableStmt) error { txn, err := e.ctx.Txn(true) if err != nil { return err @@ -344,10 +310,10 @@ func (e *RestoreTableExec) executeRestoreTable() error { dom := domain.GetDomain(e.ctx) var job *model.Job var tblInfo *model.TableInfo - if e.jobID != 0 { - job, tblInfo, err = getRestoreTableByJobID(e, t, dom) + if s.JobID != 0 { + job, tblInfo, err = e.getRecoverTableByJobID(s, t, dom) } else { - job, tblInfo, err = getRestoreTableByTableName(e, t, dom) + job, tblInfo, err = e.getRecoverTableByTableName(s, t, dom) } if err != nil { return err @@ -361,18 +327,18 @@ func (e *RestoreTableExec) executeRestoreTable() error { if err != nil { return errors.Errorf("recover table_id: %d, get original autoID from snapshot meta err: %s", job.TableID, err.Error()) } - // Call DDL RestoreTable - err = domain.GetDomain(e.ctx).DDL().RestoreTable(e.ctx, tblInfo, job.SchemaID, autoID, job.ID, job.StartTS) + // Call DDL RecoverTable + err = domain.GetDomain(e.ctx).DDL().RecoverTable(e.ctx, tblInfo, job.SchemaID, autoID, job.ID, job.StartTS) return err } -func getRestoreTableByJobID(e *RestoreTableExec, t *meta.Meta, dom *domain.Domain) (*model.Job, *model.TableInfo, error) { - job, err := t.GetHistoryDDLJob(e.jobID) +func (e *DDLExec) getRecoverTableByJobID(s *ast.RecoverTableStmt, t *meta.Meta, dom *domain.Domain) (*model.Job, *model.TableInfo, error) { + job, err := t.GetHistoryDDLJob(s.JobID) if err != nil { return nil, nil, err } if job == nil { - return nil, nil, admin.ErrDDLJobNotFound.GenWithStackByArgs(e.jobID) + return nil, nil, admin.ErrDDLJobNotFound.GenWithStackByArgs(s.JobID) } if job.Type != model.ActionDropTable { return nil, nil, errors.Errorf("Job %v type is %v, not drop table", job.ID, job.Type) @@ -400,7 +366,7 @@ func getRestoreTableByJobID(e *RestoreTableExec, t *meta.Meta, dom *domain.Domai return job, table.Meta(), nil } -func getRestoreTableByTableName(e *RestoreTableExec, t *meta.Meta, dom *domain.Domain) (*model.Job, *model.TableInfo, error) { +func (e *DDLExec) getRecoverTableByTableName(s *ast.RecoverTableStmt, t *meta.Meta, dom *domain.Domain) (*model.Job, *model.TableInfo, error) { jobs, err := t.GetAllHistoryDDLJobs() if err != nil { return nil, nil, err @@ -411,7 +377,7 @@ func getRestoreTableByTableName(e *RestoreTableExec, t *meta.Meta, dom *domain.D if err != nil { return nil, nil, err } - schemaName := e.Table.Schema.L + schemaName := s.Table.Schema.L if schemaName == "" { schemaName = e.ctx.GetSessionVars().CurrentDB } @@ -442,7 +408,7 @@ func getRestoreTableByTableName(e *RestoreTableExec, t *meta.Meta, dom *domain.D fmt.Sprintf("(Table ID %d)", job.TableID), ) } - if table.Meta().Name.L == e.Table.Name.L { + if table.Meta().Name.L == s.Table.Name.L { schema, ok := dom.InfoSchema().SchemaByID(job.SchemaID) if !ok { return nil, nil, infoschema.ErrDatabaseNotExists.GenWithStackByArgs( @@ -456,7 +422,7 @@ func getRestoreTableByTableName(e *RestoreTableExec, t *meta.Meta, dom *domain.D } } if tblInfo == nil { - return nil, nil, errors.Errorf("Can't found drop table: %v in ddl history jobs", e.Table.Name) + return nil, nil, errors.Errorf("Can't found drop table: %v in ddl history jobs", s.Table.Name) } return job, tblInfo, nil } diff --git a/go.mod b/go.mod index 0e842c9ea0399..6fa5728227e4d 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562 github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596 - github.com/pingcap/parser v0.0.0-20190404052804-c29af83ede25 + github.com/pingcap/parser v0.0.0-20190408064140-cdceeb2c5476 github.com/pingcap/pd v2.1.0-rc.4+incompatible github.com/pingcap/tidb-tools v2.1.3-0.20190321065848-1e8b48f5c168+incompatible github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7 diff --git a/go.sum b/go.sum index b5cf095c86cf2..d482caa82c799 100644 --- a/go.sum +++ b/go.sum @@ -119,8 +119,8 @@ github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562 h1:32oF1/8lVnBR2JV github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562/go.mod h1:QMdbTAXCHzzygQzqcG9uVUgU2fKeSN1GmfMiykdSzzY= github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596 h1:t2OQTpPJnrPDGlvA+3FwJptMTt6MEPdzK1Wt99oaefQ= github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596/go.mod h1:WpHUKhNZ18v116SvGrmjkA9CBhYmuUTKL+p8JC9ANEw= -github.com/pingcap/parser v0.0.0-20190404052804-c29af83ede25 h1:K7DB0kOkSETe3/4rpbzF/Iv4IgfkGBNu5EfaXxaiBuc= -github.com/pingcap/parser v0.0.0-20190404052804-c29af83ede25/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= +github.com/pingcap/parser v0.0.0-20190408064140-cdceeb2c5476 h1:qKFG6B26Zfgpb7rUYB8PCGQzWB+USDCTmH+rR7rV+ow= +github.com/pingcap/parser v0.0.0-20190408064140-cdceeb2c5476/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE= github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= github.com/pingcap/tidb-tools v2.1.3-0.20190321065848-1e8b48f5c168+incompatible h1:MkWCxgZpJBgY2f4HtwWMMFzSBb3+JPzeJgF3VrXE/bU= diff --git a/infoschema/builder.go b/infoschema/builder.go index 42046820fa321..65eba8279c1b0 100644 --- a/infoschema/builder.go +++ b/infoschema/builder.go @@ -53,7 +53,7 @@ func (b *Builder) ApplyDiff(m *meta.Meta, diff *model.SchemaDiff) ([]int64, erro var oldTableID, newTableID int64 tblIDs := make([]int64, 0, 2) switch diff.Type { - case model.ActionCreateTable, model.ActionRestoreTable: + case model.ActionCreateTable, model.ActionRecoverTable: newTableID = diff.TableID tblIDs = append(tblIDs, newTableID) case model.ActionDropTable, model.ActionDropView: diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index b761b7ca6cada..a5b2312a57d87 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -84,14 +84,6 @@ type RecoverIndex struct { IndexName string } -// RestoreTable is used for recover deleted files by mistake. -type RestoreTable struct { - baseSchemaProducer - JobID int64 - Table *ast.TableName - JobNum int64 -} - // CleanupIndex is used to delete dangling index data. type CleanupIndex struct { baseSchemaProducer diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 737a2dc67aacb..85ffed504a5db 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -625,14 +625,6 @@ func (b *PlanBuilder) buildAdmin(as *ast.AdminStmt) (Plan, error) { p := &ShowSlow{ShowSlow: as.ShowSlow} p.SetSchema(buildShowSlowSchema()) ret = p - case ast.AdminRestoreTable: - if len(as.JobIDs) > 0 { - ret = &RestoreTable{JobID: as.JobIDs[0]} - } else if len(as.Tables) > 0 { - ret = &RestoreTable{Table: as.Tables[0], JobNum: as.JobNumber} - } else { - return nil, ErrUnsupportedType.GenWithStack("Unsupported ast.AdminStmt(%T) for buildAdmin", as) - } default: return nil, ErrUnsupportedType.GenWithStack("Unsupported ast.AdminStmt(%T) for buildAdmin", as) } @@ -1701,6 +1693,9 @@ func (b *PlanBuilder) buildDDL(node ast.DDLNode) (Plan, error) { } b.visitInfo = appendVisitInfo(b.visitInfo, mysql.InsertPriv, v.NewTable.Schema.L, v.NewTable.Name.L, "", authErr) + case *ast.RecoverTableStmt: + // Recover table command can only be executed by administrator. + b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SuperPriv, "", "", "", nil) } p := &DDL{Statement: node} return p, nil diff --git a/planner/core/preprocess.go b/planner/core/preprocess.go index f69d94b3111e7..3ebd9f3eb9de2 100644 --- a/planner/core/preprocess.go +++ b/planner/core/preprocess.go @@ -111,11 +111,11 @@ func (p *preprocessor) Enter(in ast.Node) (out ast.Node, skipChildren bool) { return in, true case *ast.Join: p.checkNonUniqTableAlias(node) - case *ast.AdminStmt: - // The specified table in admin restore syntax maybe already been dropped. - // So skip check table name here, otherwise, admin restore table [table_name] syntax will return - // table not exists error. But admin restore is use to restore the dropped table. So skip children here. - return in, node.Tp == ast.AdminRestoreTable + case *ast.RecoverTableStmt: + // The specified table in recover table statement maybe already been dropped. + // So skip check table name here, otherwise, recover table [table_name] syntax will return + // table not exists error. But recover table statement is use to recover the dropped table. So skip children here. + return in, true default: p.flag &= ^parentIsJoin }