github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/sqlparse/tidbparser/dependency/model/ddl.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 model 15 16 import ( 17 "encoding/json" 18 "fmt" 19 "sync" 20 "time" 21 22 "github.com/bingoohuang/gg/pkg/sqlparse/tidbparser/dependency/terror" 23 "github.com/juju/errors" 24 ) 25 26 // ActionType is the type for DDL action. 27 type ActionType byte 28 29 // List DDL actions. 30 const ( 31 ActionNone ActionType = 0 32 ActionCreateSchema ActionType = 1 33 ActionDropSchema ActionType = 2 34 ActionCreateTable ActionType = 3 35 ActionDropTable ActionType = 4 36 ActionAddColumn ActionType = 5 37 ActionDropColumn ActionType = 6 38 ActionAddIndex ActionType = 7 39 ActionDropIndex ActionType = 8 40 ActionAddForeignKey ActionType = 9 41 ActionDropForeignKey ActionType = 10 42 ActionTruncateTable ActionType = 11 43 ActionModifyColumn ActionType = 12 44 ActionRebaseAutoID ActionType = 13 45 ActionRenameTable ActionType = 14 46 ActionSetDefaultValue ActionType = 15 47 ActionShardRowID ActionType = 16 48 ) 49 50 var actionMap = map[ActionType]string{ 51 ActionCreateSchema: "create schema", 52 ActionDropSchema: "drop schema", 53 ActionCreateTable: "create table", 54 ActionDropTable: "drop table", 55 ActionAddColumn: "add column", 56 ActionDropColumn: "drop column", 57 ActionAddIndex: "add index", 58 ActionDropIndex: "drop index", 59 ActionAddForeignKey: "add foreign key", 60 ActionDropForeignKey: "drop foreign key", 61 ActionTruncateTable: "truncate table", 62 ActionModifyColumn: "modify column", 63 ActionRebaseAutoID: "rebase auto_increment ID", 64 ActionRenameTable: "rename table", 65 ActionSetDefaultValue: "set default value", 66 ActionShardRowID: "shard row ID", 67 } 68 69 // String return current ddl action in string 70 func (action ActionType) String() string { 71 if v, ok := actionMap[action]; ok { 72 return v 73 } 74 return "none" 75 } 76 77 // HistoryInfo is used for binlog. 78 type HistoryInfo struct { 79 SchemaVersion int64 80 DBInfo *DBInfo 81 TableInfo *TableInfo 82 } 83 84 // AddDBInfo adds schema version and schema information that are used for binlog. 85 // dbInfo is added in the following operations: create database, drop database. 86 func (h *HistoryInfo) AddDBInfo(schemaVer int64, dbInfo *DBInfo) { 87 h.SchemaVersion = schemaVer 88 h.DBInfo = dbInfo 89 } 90 91 // AddTableInfo adds schema version and table information that are used for binlog. 92 // tblInfo is added except for the following operations: create database, drop database. 93 func (h *HistoryInfo) AddTableInfo(schemaVer int64, tblInfo *TableInfo) { 94 h.SchemaVersion = schemaVer 95 h.TableInfo = tblInfo 96 } 97 98 // Clean cleans history information. 99 func (h *HistoryInfo) Clean() { 100 h.SchemaVersion = 0 101 h.DBInfo = nil 102 h.TableInfo = nil 103 } 104 105 // Job is for a DDL operation. 106 type Job struct { 107 ID int64 `json:"id"` 108 Type ActionType `json:"type"` 109 SchemaID int64 `json:"schema_id"` 110 TableID int64 `json:"table_id"` 111 State JobState `json:"state"` 112 Error *terror.Error `json:"err"` 113 // ErrorCount will be increased, every time we meet an error when running job. 114 ErrorCount int64 `json:"err_count"` 115 // RowCount means the number of rows that are processed. 116 RowCount int64 `json:"row_count"` 117 Mu sync.Mutex `json:"-"` 118 Args []interface{} `json:"-"` 119 // RawArgs : We must use json raw message to delay parsing special args. 120 RawArgs json.RawMessage `json:"raw_args"` 121 SchemaState SchemaState `json:"schema_state"` 122 // SnapshotVer means snapshot version for this job. 123 SnapshotVer uint64 `json:"snapshot_ver"` 124 // StartTS uses timestamp allocated by TSO. 125 // Now it's the TS when we put the job to TiKV queue. 126 StartTS uint64 `json:"start_ts"` 127 // Query string of the ddl job. 128 Query string `json:"query"` 129 BinlogInfo *HistoryInfo `json:"binlog"` 130 131 // Version indicates the DDL job version. For old jobs, it will be 0. 132 Version int64 `json:"version"` 133 } 134 135 // FinishTableJob is called when a job is finished. 136 // It updates the job's state information and adds tblInfo to the binlog. 137 func (job *Job) FinishTableJob(jobState JobState, schemaState SchemaState, ver int64, tblInfo *TableInfo) { 138 job.State = jobState 139 job.SchemaState = schemaState 140 job.BinlogInfo.AddTableInfo(ver, tblInfo) 141 } 142 143 // FinishDBJob is called when a job is finished. 144 // It updates the job's state information and adds dbInfo the binlog. 145 func (job *Job) FinishDBJob(jobState JobState, schemaState SchemaState, ver int64, dbInfo *DBInfo) { 146 job.State = jobState 147 job.SchemaState = schemaState 148 job.BinlogInfo.AddDBInfo(ver, dbInfo) 149 } 150 151 // tsConvert2Time converts timestamp to time. 152 func tsConvert2Time(ts uint64) time.Time { 153 t := int64(ts >> 18) // 18 is for the logical time. 154 return time.Unix(t/1e3, (t%1e3)*1e6) 155 } 156 157 // SetRowCount sets the number of rows. Make sure it can pass `make race`. 158 func (job *Job) SetRowCount(count int64) { 159 job.Mu.Lock() 160 defer job.Mu.Unlock() 161 162 job.RowCount = count 163 } 164 165 // GetRowCount gets the number of rows. Make sure it can pass `make race`. 166 func (job *Job) GetRowCount() int64 { 167 job.Mu.Lock() 168 defer job.Mu.Unlock() 169 170 return job.RowCount 171 } 172 173 // Encode encodes job with json format. 174 // updateRawArgs is used to determine whether to update the raw args. 175 func (job *Job) Encode(updateRawArgs bool) ([]byte, error) { 176 var err error 177 if updateRawArgs { 178 job.RawArgs, err = json.Marshal(job.Args) 179 if err != nil { 180 return nil, errors.Trace(err) 181 } 182 } 183 184 var b []byte 185 job.Mu.Lock() 186 defer job.Mu.Unlock() 187 b, err = json.Marshal(job) 188 189 return b, errors.Trace(err) 190 } 191 192 // Decode decodes job from the json buffer, we must use DecodeArgs later to 193 // decode special args for this job. 194 func (job *Job) Decode(b []byte) error { 195 err := json.Unmarshal(b, job) 196 return errors.Trace(err) 197 } 198 199 // DecodeArgs decodes job args. 200 func (job *Job) DecodeArgs(args ...interface{}) error { 201 job.Args = args 202 err := json.Unmarshal(job.RawArgs, &job.Args) 203 return errors.Trace(err) 204 } 205 206 // String implements fmt.Stringer interface. 207 func (job *Job) String() string { 208 rowCount := job.GetRowCount() 209 return fmt.Sprintf("ID:%d, Type:%s, State:%s, SchemaState:%s, SchemaID:%d, TableID:%d, RowCount:%d, ArgLen:%d, start time: %v", 210 job.ID, job.Type, job.State, job.SchemaState, job.SchemaID, job.TableID, rowCount, len(job.Args), tsConvert2Time(job.StartTS)) 211 } 212 213 // IsFinished returns whether job is finished or not. 214 // If the job state is Done or Cancelled, it is finished. 215 func (job *Job) IsFinished() bool { 216 return job.State == JobStateDone || job.State == JobStateRollbackDone || job.State == JobStateCancelled 217 } 218 219 // IsCancelled returns whether the job is cancelled or not. 220 func (job *Job) IsCancelled() bool { 221 return job.State == JobStateCancelled || job.State == JobStateRollbackDone 222 } 223 224 // IsRollingback returns whether the job is rolling back or not. 225 func (job *Job) IsRollingback() bool { 226 return job.State == JobStateRollingback 227 } 228 229 // IsCancelling returns whether the job is cancelling or not. 230 func (job *Job) IsCancelling() bool { 231 return job.State == JobStateCancelling 232 } 233 234 // IsSynced returns whether the DDL modification is synced among all TiDB servers. 235 func (job *Job) IsSynced() bool { 236 return job.State == JobStateSynced 237 } 238 239 // IsDone returns whether job is done. 240 func (job *Job) IsDone() bool { 241 return job.State == JobStateDone 242 } 243 244 // IsRunning returns whether job is still running or not. 245 func (job *Job) IsRunning() bool { 246 return job.State == JobStateRunning 247 } 248 249 // JobState is for job state. 250 type JobState byte 251 252 // List job states. 253 const ( 254 JobStateNone JobState = 0 255 JobStateRunning JobState = 1 256 // When DDL encountered an unrecoverable error at reorganization state, 257 // some keys has been added already, we need to remove them. 258 // JobStateRollingback is the state to do the rolling back job. 259 JobStateRollingback JobState = 2 260 JobStateRollbackDone JobState = 3 261 JobStateDone JobState = 4 262 JobStateCancelled JobState = 5 263 // JobStateSynced is used to mark the information about the completion of this job 264 // has been synchronized to all servers. 265 JobStateSynced JobState = 6 266 // JobStateCancelling is used to mark the DDL job is cancelled by the client, but the DDL work hasn't handle it. 267 JobStateCancelling JobState = 7 268 ) 269 270 // String implements fmt.Stringer interface. 271 func (s JobState) String() string { 272 switch s { 273 case JobStateRunning: 274 return "running" 275 case JobStateRollingback: 276 return "rollingback" 277 case JobStateRollbackDone: 278 return "rollback done" 279 case JobStateDone: 280 return "done" 281 case JobStateCancelled: 282 return "cancelled" 283 case JobStateCancelling: 284 return "cancelling" 285 case JobStateSynced: 286 return "synced" 287 default: 288 return "none" 289 } 290 } 291 292 // SchemaDiff contains the schema modification at a particular schema version. 293 // It is used to reduce schema reload cost. 294 type SchemaDiff struct { 295 Version int64 `json:"version"` 296 Type ActionType `json:"type"` 297 SchemaID int64 `json:"schema_id"` 298 TableID int64 `json:"table_id"` 299 300 // OldTableID is the table ID before truncate, only used by truncate table DDL. 301 OldTableID int64 `json:"old_table_id"` 302 // OldSchemaID is the schema ID before rename table, only used by rename table DDL. 303 OldSchemaID int64 `json:"old_schema_id"` 304 }