func (err ChainContext) Error() string {
	return err.Top.Error()
}
Error satisfies the Error interface
package errcode
import (
	"fmt"
	"github.com/pingcap/errors"
)
func ErrorCodes(err error) []ErrorCode {
	errors := errors.Errors(err)
	errorCodes := make([]ErrorCode, len(errors))
	for i, errItem := range errors {
		if errcode, ok := errItem.(ErrorCode); ok {
			errorCodes[i] = errcode
		}
	}
	return errorCodes
}
type MultiErrCode struct {
	ErrCode ErrorCode
	rest    []error
}
func Combine(initial ErrorCode, others ...ErrorCode) MultiErrCode {
	var rest []error
	if group, ok := initial.(errors.ErrorGroup); ok {
		rest = group.Errors()
	}
	for _, other := range others {
		rest = append(rest, errors.Errors(other)...)
	}
	return MultiErrCode{
		ErrCode: initial,
		rest:    rest,
	}
}
var _ ErrorCode = (*MultiErrCode)(nil)          
var _ HasClientData = (*MultiErrCode)(nil)      
var _ Causer = (*MultiErrCode)(nil)             
var _ errors.ErrorGroup = (*MultiErrCode)(nil)  
var _ fmt.Formatter = (*MultiErrCode)(nil)      
func (e MultiErrCode) Error() string {
	output := e.ErrCode.Error()
	for _, item := range e.rest {
		output += "; " + item.Error()
	}
	return output
}
func (e MultiErrCode) Errors() []error {
	return append([]error{e.ErrCode.(error)}, e.rest...)
}
func (e MultiErrCode) Code() Code {
	return e.ErrCode.Code()
}
func (e MultiErrCode) Cause() error {
	return e.ErrCode
}
func (e MultiErrCode) GetClientData() interface{} {
	return ClientData(e.ErrCode)
}
func CodeChain(err error) ErrorCode {
	var code ErrorCode
	currentErr := err
	chainErrCode := func(errcode ErrorCode) {
		if errcode.(error) != currentErr {
			if chained, ok := errcode.(ChainContext); ok {
				chained.Top = currentErr
				errcode = chained
			} else {
				errcode = ChainContext{currentErr, errcode}
			}
		}
		if code == nil {
			code = errcode
		} else {
			code = MultiErrCode{code, []error{code.(error), errcode.(error)}}
		}
		currentErr = errcode.(error)
	}
	for err != nil {
		if errcode, ok := err.(ErrorCode); ok {
			if code == nil || code.Code() != errcode.Code() {
				chainErrCode(errcode)
			}
		} else if eg, ok := err.(errors.ErrorGroup); ok {
			group := []ErrorCode{}
			for _, errItem := range eg.Errors() {
				if itemCode := CodeChain(errItem); itemCode != nil {
					group = append(group, itemCode)
				}
			}
			if len(group) > 0 {
				var codeGroup ErrorCode
				if len(group) == 1 {
					codeGroup = group[0]
				} else {
					codeGroup = Combine(group[0], group[1:]...)
				}
				chainErrCode(codeGroup)
			}
		}
		err = errors.Unwrap(err)
	}
	return code
}
type ChainContext struct {
	Top     error
	ErrCode ErrorCode
}
func (err ChainContext) Code() Code {
	return err.ErrCode.Code()
}