mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 03:18:24 +00:00 
			
		
		
		
	* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
		
			
				
	
	
		
			241 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 PingCAP, Inc.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package terror
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"runtime"
 | |
| 	"strconv"
 | |
| 
 | |
| 	"github.com/juju/errors"
 | |
| 	"github.com/ngaut/log"
 | |
| 	"github.com/pingcap/tidb/mysql"
 | |
| )
 | |
| 
 | |
| // Common base error instances.
 | |
| var (
 | |
| 	CommitNotInTransaction   = ClassExecutor.New(CodeCommitNotInTransaction, "commit not in transaction")
 | |
| 	RollbackNotInTransaction = ClassExecutor.New(CodeRollbackNotInTransaction, "rollback not in transaction")
 | |
| 	ExecResultIsEmpty        = ClassExecutor.New(CodeExecResultIsEmpty, "exec result is empty")
 | |
| 
 | |
| 	MissConnectionID = ClassExpression.New(CodeMissConnectionID, "miss connection id information")
 | |
| )
 | |
| 
 | |
| // ErrCode represents a specific error type in a error class.
 | |
| // Same error code can be used in different error classes.
 | |
| type ErrCode int
 | |
| 
 | |
| // Executor error codes.
 | |
| const (
 | |
| 	CodeCommitNotInTransaction   ErrCode = 1
 | |
| 	CodeRollbackNotInTransaction         = 2
 | |
| 	CodeExecResultIsEmpty                = 3
 | |
| )
 | |
| 
 | |
| // Expression error codes.
 | |
| const (
 | |
| 	CodeMissConnectionID ErrCode = iota + 1
 | |
| )
 | |
| 
 | |
| // ErrClass represents a class of errors.
 | |
| type ErrClass int
 | |
| 
 | |
| // Error classes.
 | |
| const (
 | |
| 	ClassParser ErrClass = iota + 1
 | |
| 	ClassSchema
 | |
| 	ClassOptimizer
 | |
| 	ClassOptimizerPlan
 | |
| 	ClassExecutor
 | |
| 	ClassEvaluator
 | |
| 	ClassKV
 | |
| 	ClassServer
 | |
| 	ClassVariable
 | |
| 	ClassExpression
 | |
| 	// Add more as needed.
 | |
| )
 | |
| 
 | |
| // String implements fmt.Stringer interface.
 | |
| func (ec ErrClass) String() string {
 | |
| 	switch ec {
 | |
| 	case ClassParser:
 | |
| 		return "parser"
 | |
| 	case ClassSchema:
 | |
| 		return "schema"
 | |
| 	case ClassOptimizer:
 | |
| 		return "optimizer"
 | |
| 	case ClassExecutor:
 | |
| 		return "executor"
 | |
| 	case ClassKV:
 | |
| 		return "kv"
 | |
| 	case ClassServer:
 | |
| 		return "server"
 | |
| 	case ClassVariable:
 | |
| 		return "variable"
 | |
| 	case ClassExpression:
 | |
| 		return "expression"
 | |
| 	}
 | |
| 	return strconv.Itoa(int(ec))
 | |
| }
 | |
| 
 | |
| // EqualClass returns true if err is *Error with the same class.
 | |
| func (ec ErrClass) EqualClass(err error) bool {
 | |
| 	e := errors.Cause(err)
 | |
| 	if e == nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	if te, ok := e.(*Error); ok {
 | |
| 		return te.class == ec
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // NotEqualClass returns true if err is not *Error with the same class.
 | |
| func (ec ErrClass) NotEqualClass(err error) bool {
 | |
| 	return !ec.EqualClass(err)
 | |
| }
 | |
| 
 | |
| // New creates an *Error with an error code and an error message.
 | |
| // Usually used to create base *Error.
 | |
| func (ec ErrClass) New(code ErrCode, message string) *Error {
 | |
| 	return &Error{
 | |
| 		class:   ec,
 | |
| 		code:    code,
 | |
| 		message: message,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Error implements error interface and adds integer Class and Code, so
 | |
| // errors with different message can be compared.
 | |
| type Error struct {
 | |
| 	class   ErrClass
 | |
| 	code    ErrCode
 | |
| 	message string
 | |
| 	file    string
 | |
| 	line    int
 | |
| }
 | |
| 
 | |
| // Class returns ErrClass
 | |
| func (e *Error) Class() ErrClass {
 | |
| 	return e.class
 | |
| }
 | |
| 
 | |
| // Code returns ErrCode
 | |
| func (e *Error) Code() ErrCode {
 | |
| 	return e.code
 | |
| }
 | |
| 
 | |
| // Location returns the location where the error is created,
 | |
| // implements juju/errors locationer interface.
 | |
| func (e *Error) Location() (file string, line int) {
 | |
| 	return e.file, e.line
 | |
| }
 | |
| 
 | |
| // Error implements error interface.
 | |
| func (e *Error) Error() string {
 | |
| 	return fmt.Sprintf("[%s:%d]%s", e.class, e.code, e.message)
 | |
| }
 | |
| 
 | |
| // Gen generates a new *Error with the same class and code, and a new formatted message.
 | |
| func (e *Error) Gen(format string, args ...interface{}) *Error {
 | |
| 	err := *e
 | |
| 	err.message = fmt.Sprintf(format, args...)
 | |
| 	_, err.file, err.line, _ = runtime.Caller(1)
 | |
| 	return &err
 | |
| }
 | |
| 
 | |
| // Equal checks if err is equal to e.
 | |
| func (e *Error) Equal(err error) bool {
 | |
| 	originErr := errors.Cause(err)
 | |
| 	if originErr == nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	inErr, ok := originErr.(*Error)
 | |
| 	return ok && e.class == inErr.class && e.code == inErr.code
 | |
| }
 | |
| 
 | |
| // NotEqual checks if err is not equal to e.
 | |
| func (e *Error) NotEqual(err error) bool {
 | |
| 	return !e.Equal(err)
 | |
| }
 | |
| 
 | |
| // ToSQLError convert Error to mysql.SQLError.
 | |
| func (e *Error) ToSQLError() *mysql.SQLError {
 | |
| 	code := e.getMySQLErrorCode()
 | |
| 	return mysql.NewErrf(code, e.message)
 | |
| }
 | |
| 
 | |
| var defaultMySQLErrorCode uint16
 | |
| 
 | |
| func (e *Error) getMySQLErrorCode() uint16 {
 | |
| 	codeMap, ok := ErrClassToMySQLCodes[e.class]
 | |
| 	if !ok {
 | |
| 		log.Warnf("Unknown error class: %v", e.class)
 | |
| 		return defaultMySQLErrorCode
 | |
| 	}
 | |
| 	code, ok := codeMap[e.code]
 | |
| 	if !ok {
 | |
| 		log.Warnf("Unknown error class: %v code: %v", e.class, e.code)
 | |
| 		return defaultMySQLErrorCode
 | |
| 	}
 | |
| 	return code
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	// ErrCode to mysql error code map.
 | |
| 	parserMySQLErrCodes     = map[ErrCode]uint16{}
 | |
| 	executorMySQLErrCodes   = map[ErrCode]uint16{}
 | |
| 	serverMySQLErrCodes     = map[ErrCode]uint16{}
 | |
| 	expressionMySQLErrCodes = map[ErrCode]uint16{}
 | |
| 
 | |
| 	// ErrClassToMySQLCodes is the map of ErrClass to code-map.
 | |
| 	ErrClassToMySQLCodes map[ErrClass](map[ErrCode]uint16)
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	ErrClassToMySQLCodes = make(map[ErrClass](map[ErrCode]uint16))
 | |
| 	ErrClassToMySQLCodes[ClassParser] = parserMySQLErrCodes
 | |
| 	ErrClassToMySQLCodes[ClassExecutor] = executorMySQLErrCodes
 | |
| 	ErrClassToMySQLCodes[ClassServer] = serverMySQLErrCodes
 | |
| 	ErrClassToMySQLCodes[ClassExpression] = expressionMySQLErrCodes
 | |
| 	defaultMySQLErrorCode = mysql.ErrUnknown
 | |
| }
 | |
| 
 | |
| // ErrorEqual returns a boolean indicating whether err1 is equal to err2.
 | |
| func ErrorEqual(err1, err2 error) bool {
 | |
| 	e1 := errors.Cause(err1)
 | |
| 	e2 := errors.Cause(err2)
 | |
| 
 | |
| 	if e1 == e2 {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	if e1 == nil || e2 == nil {
 | |
| 		return e1 == e2
 | |
| 	}
 | |
| 
 | |
| 	te1, ok1 := e1.(*Error)
 | |
| 	te2, ok2 := e2.(*Error)
 | |
| 	if ok1 && ok2 {
 | |
| 		return te1.class == te2.class && te1.code == te2.code
 | |
| 	}
 | |
| 
 | |
| 	return e1.Error() == e2.Error()
 | |
| }
 | |
| 
 | |
| // ErrorNotEqual returns a boolean indicating whether err1 isn't equal to err2.
 | |
| func ErrorNotEqual(err1, err2 error) bool {
 | |
| 	return !ErrorEqual(err1, err2)
 | |
| }
 |