github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/terror/terror.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 terror 15 16 import ( 17 "fmt" 18 "runtime" 19 "strconv" 20 21 "github.com/insionng/yougam/libraries/juju/errors" 22 "github.com/insionng/yougam/libraries/ngaut/log" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/mysql" 24 ) 25 26 // Common base error instances. 27 var ( 28 CommitNotInTransaction = ClassExecutor.New(CodeCommitNotInTransaction, "commit not in transaction") 29 RollbackNotInTransaction = ClassExecutor.New(CodeRollbackNotInTransaction, "rollback not in transaction") 30 ExecResultIsEmpty = ClassExecutor.New(CodeExecResultIsEmpty, "exec result is empty") 31 32 MissConnectionID = ClassExpression.New(CodeMissConnectionID, "miss connection id information") 33 ) 34 35 // ErrCode represents a specific error type in a error class. 36 // Same error code can be used in different error classes. 37 type ErrCode int 38 39 // Executor error codes. 40 const ( 41 CodeCommitNotInTransaction ErrCode = 1 42 CodeRollbackNotInTransaction = 2 43 CodeExecResultIsEmpty = 3 44 ) 45 46 // Expression error codes. 47 const ( 48 CodeMissConnectionID ErrCode = iota + 1 49 ) 50 51 // ErrClass represents a class of errors. 52 type ErrClass int 53 54 // Error classes. 55 const ( 56 ClassAutoid ErrClass = iota + 1 57 ClassDDL 58 ClassDomain 59 ClassEvaluator 60 ClassExecutor 61 ClassExpression 62 ClassInspectkv 63 ClassKV 64 ClassMeta 65 ClassOptimizer 66 ClassOptimizerPlan 67 ClassParser 68 ClassPerfSchema 69 ClassPrivilege 70 ClassSchema 71 ClassServer 72 ClassStructure 73 ClassVariable 74 ClassXEval 75 // Add more as needed. 76 ) 77 78 // String implements fmt.Stringer interface. 79 func (ec ErrClass) String() string { 80 switch ec { 81 case ClassAutoid: 82 return "autoid" 83 case ClassDDL: 84 return "ddl" 85 case ClassDomain: 86 return "domain" 87 case ClassExecutor: 88 return "executor" 89 case ClassExpression: 90 return "expression" 91 case ClassInspectkv: 92 return "inspectkv" 93 case ClassMeta: 94 return "meta" 95 case ClassKV: 96 return "kv" 97 case ClassOptimizer: 98 return "optimizer" 99 case ClassParser: 100 return "parser" 101 case ClassPerfSchema: 102 return "perfschema" 103 case ClassPrivilege: 104 return "privilege" 105 case ClassSchema: 106 return "schema" 107 case ClassServer: 108 return "server" 109 case ClassStructure: 110 return "structure" 111 case ClassVariable: 112 return "variable" 113 } 114 return strconv.Itoa(int(ec)) 115 } 116 117 // EqualClass returns true if err is *Error with the same class. 118 func (ec ErrClass) EqualClass(err error) bool { 119 e := errors.Cause(err) 120 if e == nil { 121 return false 122 } 123 if te, ok := e.(*Error); ok { 124 return te.class == ec 125 } 126 return false 127 } 128 129 // NotEqualClass returns true if err is not *Error with the same class. 130 func (ec ErrClass) NotEqualClass(err error) bool { 131 return !ec.EqualClass(err) 132 } 133 134 // New creates an *Error with an error code and an error message. 135 // Usually used to create base *Error. 136 func (ec ErrClass) New(code ErrCode, message string) *Error { 137 return &Error{ 138 class: ec, 139 code: code, 140 message: message, 141 } 142 } 143 144 // Error implements error interface and adds integer Class and Code, so 145 // errors with different message can be compared. 146 type Error struct { 147 class ErrClass 148 code ErrCode 149 message string 150 file string 151 line int 152 } 153 154 // Class returns ErrClass 155 func (e *Error) Class() ErrClass { 156 return e.class 157 } 158 159 // Code returns ErrCode 160 func (e *Error) Code() ErrCode { 161 return e.code 162 } 163 164 // Location returns the location where the error is created, 165 // implements juju/errors locationer interface. 166 func (e *Error) Location() (file string, line int) { 167 return e.file, e.line 168 } 169 170 // Error implements error interface. 171 func (e *Error) Error() string { 172 return fmt.Sprintf("[%s:%d]%s", e.class, e.code, e.message) 173 } 174 175 // Gen generates a new *Error with the same class and code, and a new formatted message. 176 func (e *Error) Gen(format string, args ...interface{}) *Error { 177 err := *e 178 err.message = fmt.Sprintf(format, args...) 179 _, err.file, err.line, _ = runtime.Caller(1) 180 return &err 181 } 182 183 // Equal checks if err is equal to e. 184 func (e *Error) Equal(err error) bool { 185 originErr := errors.Cause(err) 186 if originErr == nil { 187 return false 188 } 189 inErr, ok := originErr.(*Error) 190 return ok && e.class == inErr.class && e.code == inErr.code 191 } 192 193 // NotEqual checks if err is not equal to e. 194 func (e *Error) NotEqual(err error) bool { 195 return !e.Equal(err) 196 } 197 198 // ToSQLError convert Error to mysql.SQLError. 199 func (e *Error) ToSQLError() *mysql.SQLError { 200 code := e.getMySQLErrorCode() 201 return mysql.NewErrf(code, e.message) 202 } 203 204 var defaultMySQLErrorCode uint16 205 206 func (e *Error) getMySQLErrorCode() uint16 { 207 codeMap, ok := ErrClassToMySQLCodes[e.class] 208 if !ok { 209 log.Warnf("Unknown error class: %v", e.class) 210 return defaultMySQLErrorCode 211 } 212 code, ok := codeMap[e.code] 213 if !ok { 214 log.Warnf("Unknown error class: %v code: %v", e.class, e.code) 215 return defaultMySQLErrorCode 216 } 217 return code 218 } 219 220 var ( 221 // ErrCode to mysql error code map. 222 parserMySQLErrCodes = map[ErrCode]uint16{} 223 executorMySQLErrCodes = map[ErrCode]uint16{} 224 serverMySQLErrCodes = map[ErrCode]uint16{} 225 expressionMySQLErrCodes = map[ErrCode]uint16{} 226 227 // ErrClassToMySQLCodes is the map of ErrClass to code-map. 228 ErrClassToMySQLCodes map[ErrClass](map[ErrCode]uint16) 229 ) 230 231 func init() { 232 ErrClassToMySQLCodes = make(map[ErrClass](map[ErrCode]uint16)) 233 ErrClassToMySQLCodes[ClassExecutor] = executorMySQLErrCodes 234 ErrClassToMySQLCodes[ClassExpression] = expressionMySQLErrCodes 235 ErrClassToMySQLCodes[ClassParser] = parserMySQLErrCodes 236 ErrClassToMySQLCodes[ClassServer] = serverMySQLErrCodes 237 defaultMySQLErrorCode = mysql.ErrUnknown 238 } 239 240 // ErrorEqual returns a boolean indicating whether err1 is equal to err2. 241 func ErrorEqual(err1, err2 error) bool { 242 e1 := errors.Cause(err1) 243 e2 := errors.Cause(err2) 244 245 if e1 == e2 { 246 return true 247 } 248 249 if e1 == nil || e2 == nil { 250 return e1 == e2 251 } 252 253 te1, ok1 := e1.(*Error) 254 te2, ok2 := e2.(*Error) 255 if ok1 && ok2 { 256 return te1.class == te2.class && te1.code == te2.code 257 } 258 259 return e1.Error() == e2.Error() 260 } 261 262 // ErrorNotEqual returns a boolean indicating whether err1 isn't equal to err2. 263 func ErrorNotEqual(err1, err2 error) bool { 264 return !ErrorEqual(err1, err2) 265 }