func (b *Builder) applyCreateTable(m *meta.Meta, roDBInfo *model.DBInfo, tableID int64, alloc autoid.Allocator) error { tblInfo, err := m.GetTable(roDBInfo.ID, tableID) if err != nil { return errors.Trace(err) } if tblInfo == nil { // When we apply an old schema diff, the table may has been dropped already, so we need to fall back to // full load. return ErrTableNotExists } if alloc == nil { alloc = autoid.NewAllocator(b.handle.store, roDBInfo.ID) } tbl, err := tables.TableFromMeta(alloc, tblInfo) if err != nil { return errors.Trace(err) } tableNames := b.is.schemaMap[roDBInfo.Name.L] tableNames.tables[tblInfo.Name.L] = tbl bucketIdx := tableBucketIdx(tableID) sortedTables := b.is.sortedTablesBuckets[bucketIdx] sortedTables = append(sortedTables, tbl) sort.Sort(sortedTables) b.is.sortedTablesBuckets[bucketIdx] = sortedTables return nil }
func (d *ddl) onDropTable(t *meta.Meta, job *model.Job) error { schemaID := job.SchemaID tableID := job.TableID // Check this table's database. 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) } // Check the table. if tblInfo == nil { job.State = model.JobCancelled return errors.Trace(infoschema.ErrTableNotExists) } ver, err := updateSchemaVersion(t, job) if err != nil { return errors.Trace(err) } switch tblInfo.State { case model.StatePublic: // public -> write only job.SchemaState = model.StateWriteOnly tblInfo.State = model.StateWriteOnly err = t.UpdateTable(schemaID, tblInfo) case model.StateWriteOnly: // write only -> delete only job.SchemaState = model.StateDeleteOnly tblInfo.State = model.StateDeleteOnly err = t.UpdateTable(schemaID, tblInfo) case model.StateDeleteOnly: tblInfo.State = model.StateNone err = t.UpdateTable(schemaID, tblInfo) if err = t.DropTable(job.SchemaID, job.TableID); err != nil { break } // Finish this job. job.State = model.JobDone job.SchemaState = model.StateNone addTableHistoryInfo(job, ver, tblInfo) startKey := tablecodec.EncodeTablePrefix(tableID) job.Args = append(job.Args, startKey) default: err = ErrInvalidTableState.Gen("invalid table state %v", tblInfo.State) } return errors.Trace(err) }
func (d *ddl) onDropTable(t *meta.Meta, job *model.Job) error { schemaID := job.SchemaID tableID := job.TableID 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.GenSchemaVersion() if err != nil { return errors.Trace(err) } switch tblInfo.State { case model.StatePublic: // public -> write only job.SchemaState = model.StateWriteOnly tblInfo.State = model.StateWriteOnly err = t.UpdateTable(schemaID, tblInfo) case model.StateWriteOnly: // write only -> delete only job.SchemaState = model.StateDeleteOnly tblInfo.State = model.StateDeleteOnly err = t.UpdateTable(schemaID, tblInfo) case model.StateDeleteOnly: tblInfo.State = model.StateNone err = t.UpdateTable(schemaID, tblInfo) if err = t.DropTable(job.SchemaID, job.TableID); err != nil { break } // finish this job job.Args = []interface{}{tblInfo} job.State = model.JobDone job.SchemaState = model.StateNone default: err = ErrInvalidTableState.Gen("invalid table state %v", tblInfo.State) } return errors.Trace(err) }
// 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) getTableInfo(t *meta.Meta, job *model.Job) (*model.TableInfo, error) { schemaID := job.SchemaID tableID := job.TableID tblInfo, err := t.GetTable(schemaID, tableID) if terror.ErrorEqual(err, meta.ErrDBNotExists) { job.State = model.JobCancelled return nil, errors.Trace(infoschema.ErrDatabaseNotExists) } else if err != nil { return nil, errors.Trace(err) } else if tblInfo == nil { job.State = model.JobCancelled return nil, errors.Trace(infoschema.ErrTableNotExists) } if tblInfo.State != model.StatePublic { job.State = model.JobCancelled return nil, ErrInvalidTableState.Gen("table %s is not in public, but %s", tblInfo.Name.L, tblInfo.State) } return tblInfo, nil }
func (b *Builder) applyCreateTable(m *meta.Meta, roDBInfo *model.DBInfo, tableID int64, alloc autoid.Allocator) error { tblInfo, err := m.GetTable(roDBInfo.ID, tableID) if err != nil { return errors.Trace(err) } if tblInfo == nil { // When we apply an old schema diff, the table may has been dropped already, so we need to fall back to // full load. return ErrTableNotExists } if alloc == nil { alloc = autoid.NewAllocator(b.handle.store, roDBInfo.ID) } tbl, err := tables.TableFromMeta(alloc, tblInfo) if err != nil { return errors.Trace(err) } b.is.tables[tblInfo.ID] = tbl tn := makeTableName(roDBInfo.Name.L, tblInfo.Name.L) b.is.tableNameToID[string(tn)] = tblInfo.ID return nil }
func (d *ddl) onDropTable(t *meta.Meta, job *model.Job) error { schemaID := job.SchemaID tableID := job.TableID tblInfo, err := t.GetTable(schemaID, tableID) if terror.ErrorEqual(err, meta.ErrDBNotExists) { job.State = model.JobCancelled return errors.Trace(terror.DatabaseNotExists) } else if err != nil { return errors.Trace(err) } if tblInfo == nil { job.State = model.JobCancelled return errors.Trace(ErrNotExists) } _, err = t.GenSchemaVersion() if err != nil { return errors.Trace(err) } switch tblInfo.State { case model.StatePublic: // public -> write only job.SchemaState = model.StateWriteOnly tblInfo.State = model.StateWriteOnly err = t.UpdateTable(schemaID, tblInfo) return errors.Trace(err) case model.StateWriteOnly: // write only -> delete only job.SchemaState = model.StateDeleteOnly tblInfo.State = model.StateDeleteOnly err = t.UpdateTable(schemaID, tblInfo) return errors.Trace(err) case model.StateDeleteOnly: // delete only -> reorganization job.SchemaState = model.StateDeleteReorganization tblInfo.State = model.StateDeleteReorganization err = t.UpdateTable(schemaID, tblInfo) return errors.Trace(err) case model.StateDeleteReorganization: // reorganization -> absent var tbl table.Table tbl, err = d.getTable(t, schemaID, tblInfo) if err != nil { return errors.Trace(err) } err = d.runReorgJob(func() error { return d.dropTableData(tbl) }) if terror.ErrorEqual(err, errWaitReorgTimeout) { // if timeout, we should return, check for the owner and re-wait job done. return nil } if err != nil { return errors.Trace(err) } // all reorganization jobs done, drop this database if err = t.DropTable(schemaID, tableID); err != nil { return errors.Trace(err) } // finish this job job.SchemaState = model.StateNone job.State = model.JobDone return nil default: return errors.Errorf("invalid table state %v", tblInfo.State) } }