func (d *ddl) onCreateTable(t *meta.Meta, job *model.Job) error { schemaID := job.SchemaID tbInfo := &model.TableInfo{} if err := job.DecodeArgs(tbInfo); err != nil { // arg error, cancel this job. job.State = model.JobCancelled return errors.Trace(err) } tbInfo.State = model.StateNone tables, err := t.ListTables(schemaID) if terror.ErrorEqual(err, meta.ErrDBNotExists) { job.State = model.JobCancelled return errors.Trace(infoschema.ErrDatabaseNotExists) } else if err != nil { return errors.Trace(err) } for _, tbl := range tables { if tbl.Name.L == tbInfo.Name.L { if tbl.ID != tbInfo.ID { // table exists, can't create, we should cancel this job now. job.State = model.JobCancelled return errors.Trace(infoschema.ErrTableExists) } tbInfo = tbl } } ver, err := updateSchemaVersion(t, job) if err != nil { return errors.Trace(err) } switch tbInfo.State { case model.StateNone: // none -> public job.SchemaState = model.StatePublic tbInfo.State = model.StatePublic err = t.CreateTable(schemaID, tbInfo) if err != nil { return errors.Trace(err) } // finish this job job.State = model.JobDone addTableHistoryInfo(job, ver, tbInfo) return nil default: return ErrInvalidTableState.Gen("invalid table state %v", tbInfo.State) } }
// onTruncateTable delete old table meta, and creates a new table identical to old table except for table ID. // As all the old data is encoded with old table ID, it can not be accessed any more. // A background job will be created to delete old data. func (d *ddl) onTruncateTable(t *meta.Meta, job *model.Job) error { schemaID := job.SchemaID tableID := job.TableID var newTableID int64 err := job.DecodeArgs(&newTableID) if err != nil { job.State = model.JobCancelled return errors.Trace(err) } tblInfo, err := t.GetTable(schemaID, tableID) if terror.ErrorEqual(err, meta.ErrDBNotExists) { job.State = model.JobCancelled return errors.Trace(infoschema.ErrDatabaseNotExists) } else if err != nil { return errors.Trace(err) } if tblInfo == nil { job.State = model.JobCancelled return errors.Trace(infoschema.ErrTableNotExists) } err = t.DropTable(schemaID, tableID) if err != nil { job.State = model.JobCancelled return errors.Trace(err) } tblInfo.ID = newTableID err = t.CreateTable(schemaID, tblInfo) if err != nil { job.State = model.JobCancelled return errors.Trace(err) } ver, err := updateSchemaVersion(t, job) if err != nil { return errors.Trace(err) } job.State = model.JobDone addTableHistoryInfo(job, ver, tblInfo) startKey := tablecodec.EncodeTablePrefix(tableID) job.Args = append(job.Args, startKey) return nil }
func (d *ddl) onCreateTable(t *meta.Meta, job *model.Job) error { schemaID := job.SchemaID tbInfo := &model.TableInfo{} if err := job.DecodeArgs(tbInfo); err != nil { // arg error, cancel this job. job.State = model.JobCancelled return errors.Trace(err) } tbInfo.State = model.StateNone tables, err := t.ListTables(schemaID) if terror.ErrorEqual(err, meta.ErrDBNotExists) { job.State = model.JobCancelled return errors.Trace(terror.DatabaseNotExists) } else if err != nil { return errors.Trace(err) } for _, tbl := range tables { if tbl.Name.L == tbInfo.Name.L { if tbl.ID != tbInfo.ID { // table exists, can't create, we should cancel this job now. job.State = model.JobCancelled return errors.Trace(ErrExists) } tbInfo = tbl } } _, err = t.GenSchemaVersion() if err != nil { return errors.Trace(err) } switch tbInfo.State { case model.StateNone: // none -> delete only job.SchemaState = model.StateDeleteOnly tbInfo.State = model.StateDeleteOnly err = t.CreateTable(schemaID, tbInfo) return errors.Trace(err) case model.StateDeleteOnly: // delete only -> write only job.SchemaState = model.StateWriteOnly tbInfo.State = model.StateWriteOnly err = t.UpdateTable(schemaID, tbInfo) return errors.Trace(err) case model.StateWriteOnly: // write only -> public job.SchemaState = model.StatePublic tbInfo.State = model.StatePublic err = t.UpdateTable(schemaID, tbInfo) if err != nil { return errors.Trace(err) } // finish this job job.State = model.JobDone return nil default: return errors.Errorf("invalid table state %v", tbInfo.State) } }