github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/ddl/table.go (about) 1 // Copyright 2015 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package ddl 15 16 import ( 17 "github.com/insionng/yougam/libraries/juju/errors" 18 "github.com/insionng/yougam/libraries/pingcap/tidb/infoschema" 19 "github.com/insionng/yougam/libraries/pingcap/tidb/meta" 20 "github.com/insionng/yougam/libraries/pingcap/tidb/meta/autoid" 21 "github.com/insionng/yougam/libraries/pingcap/tidb/model" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/table" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/terror" 24 ) 25 26 func (d *ddl) onCreateTable(t *meta.Meta, job *model.Job) error { 27 schemaID := job.SchemaID 28 tbInfo := &model.TableInfo{} 29 if err := job.DecodeArgs(tbInfo); err != nil { 30 // arg error, cancel this job. 31 job.State = model.JobCancelled 32 return errors.Trace(err) 33 } 34 35 tbInfo.State = model.StateNone 36 37 tables, err := t.ListTables(schemaID) 38 if terror.ErrorEqual(err, meta.ErrDBNotExists) { 39 job.State = model.JobCancelled 40 return errors.Trace(infoschema.ErrDatabaseNotExists) 41 } else if err != nil { 42 return errors.Trace(err) 43 } 44 45 for _, tbl := range tables { 46 if tbl.Name.L == tbInfo.Name.L { 47 if tbl.ID != tbInfo.ID { 48 // table exists, can't create, we should cancel this job now. 49 job.State = model.JobCancelled 50 return errors.Trace(infoschema.ErrTableExists) 51 } 52 53 tbInfo = tbl 54 } 55 } 56 57 _, err = t.GenSchemaVersion() 58 if err != nil { 59 return errors.Trace(err) 60 } 61 62 switch tbInfo.State { 63 case model.StateNone: 64 // none -> public 65 job.SchemaState = model.StatePublic 66 tbInfo.State = model.StatePublic 67 err = t.CreateTable(schemaID, tbInfo) 68 if err != nil { 69 return errors.Trace(err) 70 } 71 // finish this job 72 job.State = model.JobDone 73 return nil 74 default: 75 return ErrInvalidTableState.Gen("invalid table state %v", tbInfo.State) 76 } 77 } 78 79 func (d *ddl) delReorgTable(t *meta.Meta, job *model.Job) error { 80 tblInfo := &model.TableInfo{} 81 err := job.DecodeArgs(tblInfo) 82 if err != nil { 83 // arg error, cancel this job. 84 job.State = model.JobCancelled 85 return errors.Trace(err) 86 } 87 tblInfo.State = model.StateDeleteReorganization 88 tbl, err := d.getTable(job.SchemaID, tblInfo) 89 if err != nil { 90 return errors.Trace(err) 91 } 92 93 err = d.dropTableData(tbl) 94 if err != nil { 95 return errors.Trace(err) 96 } 97 98 // finish this background job 99 job.SchemaState = model.StateNone 100 job.State = model.JobDone 101 102 return nil 103 } 104 105 func (d *ddl) onDropTable(t *meta.Meta, job *model.Job) error { 106 schemaID := job.SchemaID 107 tableID := job.TableID 108 109 tblInfo, err := t.GetTable(schemaID, tableID) 110 if terror.ErrorEqual(err, meta.ErrDBNotExists) { 111 job.State = model.JobCancelled 112 return errors.Trace(infoschema.ErrDatabaseNotExists) 113 } else if err != nil { 114 return errors.Trace(err) 115 } 116 117 if tblInfo == nil { 118 job.State = model.JobCancelled 119 return errors.Trace(infoschema.ErrTableNotExists) 120 } 121 122 _, err = t.GenSchemaVersion() 123 if err != nil { 124 return errors.Trace(err) 125 } 126 127 switch tblInfo.State { 128 case model.StatePublic: 129 // public -> write only 130 job.SchemaState = model.StateWriteOnly 131 tblInfo.State = model.StateWriteOnly 132 err = t.UpdateTable(schemaID, tblInfo) 133 case model.StateWriteOnly: 134 // write only -> delete only 135 job.SchemaState = model.StateDeleteOnly 136 tblInfo.State = model.StateDeleteOnly 137 err = t.UpdateTable(schemaID, tblInfo) 138 case model.StateDeleteOnly: 139 tblInfo.State = model.StateNone 140 err = t.UpdateTable(schemaID, tblInfo) 141 if err = t.DropTable(job.SchemaID, job.TableID); err != nil { 142 break 143 } 144 // finish this job 145 job.Args = []interface{}{tblInfo} 146 job.State = model.JobDone 147 job.SchemaState = model.StateNone 148 default: 149 err = ErrInvalidTableState.Gen("invalid table state %v", tblInfo.State) 150 } 151 152 return errors.Trace(err) 153 } 154 155 func (d *ddl) getTable(schemaID int64, tblInfo *model.TableInfo) (table.Table, error) { 156 alloc := autoid.NewAllocator(d.store, schemaID) 157 tbl, err := table.TableFromMeta(alloc, tblInfo) 158 return tbl, errors.Trace(err) 159 } 160 161 func (d *ddl) getTableInfo(t *meta.Meta, job *model.Job) (*model.TableInfo, error) { 162 schemaID := job.SchemaID 163 tableID := job.TableID 164 tblInfo, err := t.GetTable(schemaID, tableID) 165 if terror.ErrorEqual(err, meta.ErrDBNotExists) { 166 job.State = model.JobCancelled 167 return nil, errors.Trace(infoschema.ErrDatabaseNotExists) 168 } else if err != nil { 169 return nil, errors.Trace(err) 170 } else if tblInfo == nil { 171 job.State = model.JobCancelled 172 return nil, errors.Trace(infoschema.ErrTableNotExists) 173 } 174 175 if tblInfo.State != model.StatePublic { 176 job.State = model.JobCancelled 177 return nil, ErrInvalidTableState.Gen("table %s is not in public, but %s", tblInfo.Name.L, tblInfo.State) 178 } 179 180 return tblInfo, nil 181 } 182 183 func (d *ddl) dropTableData(t table.Table) error { 184 // delete table data 185 err := d.delKeysWithPrefix(t.RecordPrefix()) 186 if err != nil { 187 return errors.Trace(err) 188 } 189 190 // delete table index 191 err = d.delKeysWithPrefix(t.IndexPrefix()) 192 193 return errors.Trace(err) 194 }