github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/sqlparse/tidbparser/dependency/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 "encoding/json" 18 "fmt" 19 "runtime" 20 "strconv" 21 22 "github.com/bingoohuang/gg/pkg/sqlparse/tidbparser/dependency/mysql" 23 "github.com/juju/errors" 24 ) 25 26 // Global error instances. 27 var ( 28 ErrCritical = ClassGlobal.New(CodeExecResultIsEmpty, "critical error %v") 29 ErrResultUndetermined = ClassGlobal.New(CodeResultUndetermined, "execution result undetermined") 30 ) 31 32 // ErrCode represents a specific error type in a error class. 33 // Same error code can be used in different error classes. 34 type ErrCode int 35 36 const ( 37 // Executor error codes. 38 39 // CodeUnknown is for errors of unknown reason. 40 CodeUnknown ErrCode = -1 41 // CodeExecResultIsEmpty indicates execution result is empty. 42 CodeExecResultIsEmpty ErrCode = 3 43 44 // Expression error codes. 45 46 // CodeMissConnectionID indicates connection id is missing. 47 CodeMissConnectionID ErrCode = 1 48 49 // Special error codes. 50 51 // CodeResultUndetermined indicates the sql execution result is undetermined. 52 CodeResultUndetermined ErrCode = 2 53 ) 54 55 // ErrClass represents a class of errors. 56 type ErrClass int 57 58 // Error classes. 59 const ( 60 ClassAutoid ErrClass = iota + 1 61 ClassDDL 62 ClassDomain 63 ClassEvaluator 64 ClassExecutor 65 ClassExpression 66 ClassAdmin 67 ClassKV 68 ClassMeta 69 ClassOptimizer 70 ClassOptimizerPlan 71 ClassParser 72 ClassPerfSchema 73 ClassPrivilege 74 ClassSchema 75 ClassServer 76 ClassStructure 77 ClassVariable 78 ClassXEval 79 ClassTable 80 ClassTypes 81 ClassGlobal 82 ClassMockTikv 83 ClassJSON 84 ClassTiKV 85 // Add more as needed. 86 ) 87 88 var errClz2Str = map[ErrClass]string{ 89 ClassAutoid: "autoid", 90 ClassDDL: "ddl", 91 ClassDomain: "domain", 92 ClassExecutor: "executor", 93 ClassExpression: "expression", 94 ClassAdmin: "admin", 95 ClassMeta: "meta", 96 ClassKV: "kv", 97 ClassOptimizer: "optimizer", 98 ClassOptimizerPlan: "plan", 99 ClassParser: "parser", 100 ClassPerfSchema: "perfschema", 101 ClassPrivilege: "privilege", 102 ClassSchema: "schema", 103 ClassServer: "server", 104 ClassStructure: "structure", 105 ClassVariable: "variable", 106 ClassTable: "table", 107 ClassTypes: "types", 108 ClassGlobal: "global", 109 ClassMockTikv: "mocktikv", 110 ClassJSON: "json", 111 ClassTiKV: "tikv", 112 } 113 114 // String implements fmt.Stringer interface. 115 func (ec ErrClass) String() string { 116 if s, exists := errClz2Str[ec]; exists { 117 return s 118 } 119 return strconv.Itoa(int(ec)) 120 } 121 122 // EqualClass returns true if err is *Error with the same class. 123 func (ec ErrClass) EqualClass(err error) bool { 124 e := errors.Cause(err) 125 if e == nil { 126 return false 127 } 128 if te, ok := e.(*Error); ok { 129 return te.class == ec 130 } 131 return false 132 } 133 134 // NotEqualClass returns true if err is not *Error with the same class. 135 func (ec ErrClass) NotEqualClass(err error) bool { 136 return !ec.EqualClass(err) 137 } 138 139 // New creates an *Error with an error code and an error message. 140 // Usually used to create base *Error. 141 func (ec ErrClass) New(code ErrCode, message string) *Error { 142 return &Error{ 143 class: ec, 144 code: code, 145 message: message, 146 } 147 } 148 149 // Error implements error interface and adds integer Class and Code, so 150 // errors with different message can be compared. 151 type Error struct { 152 class ErrClass 153 code ErrCode 154 message string 155 args []interface{} 156 file string 157 line int 158 } 159 160 // Class returns ErrClass 161 func (e *Error) Class() ErrClass { 162 return e.class 163 } 164 165 // Code returns ErrCode 166 func (e *Error) Code() ErrCode { 167 return e.code 168 } 169 170 // MarshalJSON implements json.Marshaler interface. 171 func (e *Error) MarshalJSON() ([]byte, error) { 172 return json.Marshal(&struct { 173 Class ErrClass `json:"class"` 174 Code ErrCode `json:"code"` 175 Msg string `json:"message"` 176 }{ 177 Class: e.class, 178 Code: e.code, 179 Msg: e.getMsg(), 180 }) 181 } 182 183 // UnmarshalJSON implements json.Unmarshaler interface. 184 func (e *Error) UnmarshalJSON(data []byte) error { 185 err := &struct { 186 Class ErrClass `json:"class"` 187 Code ErrCode `json:"code"` 188 Msg string `json:"message"` 189 }{} 190 191 if err := json.Unmarshal(data, &err); err != nil { 192 return errors.Trace(err) 193 } 194 195 e.class = err.Class 196 e.code = err.Code 197 e.message = err.Msg 198 return nil 199 } 200 201 // Location returns the location where the error is created, 202 // implements juju/errors locationer interface. 203 func (e *Error) Location() (file string, line int) { 204 return e.file, e.line 205 } 206 207 // Error implements error interface. 208 func (e *Error) Error() string { 209 return fmt.Sprintf("[%s:%d]%s", e.class, e.code, e.getMsg()) 210 } 211 212 func (e *Error) getMsg() string { 213 if len(e.args) > 0 { 214 return fmt.Sprintf(e.message, e.args...) 215 } 216 return e.message 217 } 218 219 // Gen generates a new *Error with the same class and code, and a new formatted message. 220 func (e *Error) Gen(format string, args ...interface{}) *Error { 221 err := *e 222 err.message = format 223 err.args = args 224 _, err.file, err.line, _ = runtime.Caller(1) 225 return &err 226 } 227 228 // GenByArgs generates a new *Error with the same class and code, and new arguments. 229 func (e *Error) GenByArgs(args ...interface{}) *Error { 230 err := *e 231 err.args = args 232 _, err.file, err.line, _ = runtime.Caller(1) 233 return &err 234 } 235 236 // FastGen generates a new *Error with the same class and code, and a new formatted message. 237 // This will not call runtime.Caller to get file and line. 238 func (e *Error) FastGen(format string, args ...interface{}) *Error { 239 err := *e 240 err.message = format 241 err.args = args 242 return &err 243 } 244 245 // Equal checks if err is equal to e. 246 func (e *Error) Equal(err error) bool { 247 originErr := errors.Cause(err) 248 if originErr == nil { 249 return false 250 } 251 252 if error(e) == originErr { 253 return true 254 } 255 inErr, ok := originErr.(*Error) 256 return ok && e.class == inErr.class && e.code == inErr.code 257 } 258 259 // NotEqual checks if err is not equal to e. 260 func (e *Error) NotEqual(err error) bool { 261 return !e.Equal(err) 262 } 263 264 // ToSQLError convert Error to mysql.SQLError. 265 func (e *Error) ToSQLError() *mysql.SQLError { 266 code := e.getMySQLErrorCode() 267 return mysql.NewErrf(code, "%s", e.getMsg()) 268 } 269 270 var defaultMySQLErrorCode uint16 271 272 func (e *Error) getMySQLErrorCode() uint16 { 273 codeMap, ok := ErrClassToMySQLCodes[e.class] 274 if !ok { 275 // log.Warnf("Unknown error class: %v", e.class) 276 return defaultMySQLErrorCode 277 } 278 code, ok := codeMap[e.code] 279 if !ok { 280 // log.Warnf("Unknown error class: %v code: %v", e.class, e.code) 281 return defaultMySQLErrorCode 282 } 283 return code 284 } 285 286 // ErrClassToMySQLCodes is the map of ErrClass to code-map. 287 var ErrClassToMySQLCodes map[ErrClass]map[ErrCode]uint16 288 289 func init() { 290 ErrClassToMySQLCodes = make(map[ErrClass]map[ErrCode]uint16) 291 defaultMySQLErrorCode = mysql.ErrUnknown 292 } 293 294 // ErrorEqual returns a boolean indicating whether err1 is equal to err2. 295 func ErrorEqual(err1, err2 error) bool { 296 e1 := errors.Cause(err1) 297 e2 := errors.Cause(err2) 298 299 if e1 == e2 { 300 return true 301 } 302 303 if e1 == nil || e2 == nil { 304 return e1 == e2 305 } 306 307 te1, ok1 := e1.(*Error) 308 te2, ok2 := e2.(*Error) 309 if ok1 && ok2 { 310 return te1.class == te2.class && te1.code == te2.code 311 } 312 313 return e1.Error() == e2.Error() 314 } 315 316 // ErrorNotEqual returns a boolean indicating whether err1 isn't equal to err2. 317 func ErrorNotEqual(err1, err2 error) bool { 318 return !ErrorEqual(err1, err2) 319 } 320 321 // MustNil fatals if err is not nil. 322 func MustNil(err error) { 323 if err != nil { 324 // log.Fatalf(errors.ErrorStack(err)) 325 } 326 } 327 328 // Call executes a function and checks the returned err. 329 func Call(fn func() error) { 330 err := fn() 331 if err != nil { 332 // log.Error(errors.ErrorStack(err)) 333 } 334 } 335 336 // Log logs the error if it is not nil. 337 func Log(err error) { 338 if err != nil { 339 // log.Error(errors.ErrorStack(err)) 340 } 341 }