Skip to content
61 changes: 61 additions & 0 deletions go/mysql/sqlerror/sql_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,67 @@ func (se *SQLError) SQLState() string {
return se.State
}

// VtRpcErrorCode returns the vtrpcpb.Code for the error.
func (se *SQLError) VtRpcErrorCode() vtrpcpb.Code {
switch se.Number() {
case ERNotSupportedYet:
return vtrpcpb.Code_UNIMPLEMENTED
case ERDiskFull, EROutOfMemory, EROutOfSortMemory, ERConCount, EROutOfResources, ERRecordFileFull, ERHostIsBlocked,
ERCantCreateThread, ERTooManyDelayedThreads, ERNetPacketTooLarge, ERTooManyUserConnections, ERLockTableFull, ERUserLimitReached:
return vtrpcpb.Code_RESOURCE_EXHAUSTED
case ERLockWaitTimeout:
return vtrpcpb.Code_DEADLINE_EXCEEDED
case CRServerGone, ERServerShutdown, ERServerIsntAvailable, CRConnectionError, CRConnHostError:
return vtrpcpb.Code_UNAVAILABLE
case ERFormNotFound, ERKeyNotFound, ERBadFieldError, ERNoSuchThread, ERUnknownTable, ERCantFindUDF, ERNonExistingGrant,
ERNoSuchTable, ERNonExistingTableGrant, ERKeyDoesNotExist:
return vtrpcpb.Code_NOT_FOUND
case ERDBAccessDenied, ERAccessDeniedError, ERKillDenied, ERNoPermissionToCreateUsers:
return vtrpcpb.Code_PERMISSION_DENIED
case ERNoDb, ERNoSuchIndex, ERCantDropFieldOrKey, ERTableNotLockedForWrite, ERTableNotLocked, ERTooBigSelect, ERNotAllowedCommand,
ERTooLongString, ERDelayedInsertTableLocked, ERDupUnique, ERRequiresPrimaryKey, ERCantDoThisDuringAnTransaction, ERReadOnlyTransaction,
ERCannotAddForeign, ERNoReferencedRow, ERRowIsReferenced, ERCantUpdateWithReadLock, ERNoDefault, EROperandColumns,
ERSubqueryNo1Row, ERNonUpdateableTable, ERFeatureDisabled, ERDuplicatedValueInType, ERRowIsReferenced2,
ErNoReferencedRow2, ERWarnDataOutOfRange:
return vtrpcpb.Code_FAILED_PRECONDITION
case EROptionPreventsStatement:
return vtrpcpb.Code_CLUSTER_EVENT
case ERTableExists, ERDupEntry, ERFileExists, ERUDFExists:
return vtrpcpb.Code_ALREADY_EXISTS
case ERGotSignal, ERForcingClose, ERAbortingConnection, ERLockDeadlock:
// For ERLockDeadlock, a deadlock rolls back the transaction.
return vtrpcpb.Code_ABORTED
case ERUnknownComError, ERBadNullError, ERBadDb, ERBadTable, ERNonUniq, ERWrongFieldWithGroup, ERWrongGroupField,
ERWrongSumSelect, ERWrongValueCount, ERTooLongIdent, ERDupFieldName, ERDupKeyName, ERWrongFieldSpec, ERParseError,
EREmptyQuery, ERNonUniqTable, ERInvalidDefault, ERMultiplePriKey, ERTooManyKeys, ERTooManyKeyParts, ERTooLongKey,
ERKeyColumnDoesNotExist, ERBlobUsedAsKey, ERTooBigFieldLength, ERWrongAutoKey, ERWrongFieldTerminators, ERBlobsAndNoTerminated,
ERTextFileNotReadable, ERWrongSubKey, ERCantRemoveAllFields, ERUpdateTableUsed, ERNoTablesUsed, ERTooBigSet,
ERBlobCantHaveDefault, ERWrongDbName, ERWrongTableName, ERUnknownProcedure, ERWrongParamCountToProcedure,
ERWrongParametersToProcedure, ERFieldSpecifiedTwice, ERInvalidGroupFuncUse, ERTableMustHaveColumns, ERUnknownCharacterSet,
ERTooManyTables, ERTooManyFields, ERTooBigRowSize, ERWrongOuterJoin, ERNullColumnInIndex, ERFunctionNotDefined,
ERWrongValueCountOnRow, ERInvalidUseOfNull, ERRegexpError, ERMixOfGroupFuncAndFields, ERIllegalGrantForTable, ERSyntaxError,
ERWrongColumnName, ERWrongKeyColumn, ERBlobKeyWithoutLength, ERPrimaryCantHaveNull, ERTooManyRows, ERUnknownSystemVariable,
ERSetConstantsOnly, ERWrongArguments, ERWrongUsage, ERWrongNumberOfColumnsInSelect, ERDupArgument, ERLocalVariable,
ERGlobalVariable, ERWrongValueForVar, ERWrongTypeForVar, ERVarCantBeRead, ERCantUseOptionHere, ERIncorrectGlobalLocalVar,
ERWrongFKDef, ERKeyRefDoNotMatchTableRef, ERCyclicReference, ERCollationCharsetMismatch, ERCantAggregate2Collations,
ERCantAggregate3Collations, ERCantAggregateNCollations, ERVariableIsNotStruct, ERUnknownCollation, ERWrongNameForIndex,
ERWrongNameForCatalog, ERBadFTColumn, ERTruncatedWrongValue, ERTooMuchAutoTimestampCols, ERInvalidOnUpdate, ERUnknownTimeZone,
ERInvalidCharacterString, ERIllegalReference, ERDerivedMustHaveAlias, ERTableNameNotAllowedHere, ERDataTooLong, ERDataOutOfRange,
ERTruncatedWrongValueForField, ERIllegalValueForType, ERWrongValue:
return vtrpcpb.Code_INVALID_ARGUMENT
case ERSpecifiedAccessDenied:
if strings.Contains(se.Message, "failover in progress") {
return vtrpcpb.Code_FAILED_PRECONDITION
}
return vtrpcpb.Code_PERMISSION_DENIED
case CRServerLost:
// Query was killed.
return vtrpcpb.Code_CANCELED
default:
return vterrors.Code(se)
}
}

var errExtract = regexp.MustCompile(`\(errno ([0-9]*)\) \(sqlstate ([0-9a-zA-Z]{5})\)`)

// NewSQLErrorFromError returns a *SQLError from the provided error.
Expand Down
16 changes: 11 additions & 5 deletions go/vt/vttablet/tabletmanager/rpc_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@ limitations under the License.
package tabletmanager

import (
"fmt"

"vitess.io/vitess/go/vt/vterrors"

"context"
"fmt"

"vitess.io/vitess/go/mysql/sqlerror"
"vitess.io/vitess/go/tb"
"vitess.io/vitess/go/vt/callinfo"
"vitess.io/vitess/go/vt/log"
"vitess.io/vitess/go/vt/topo/topoproto"
"vitess.io/vitess/go/vt/vterrors"
)

// This file contains the RPC method helpers for the tablet manager.
Expand Down Expand Up @@ -69,8 +68,15 @@ func (tm *TabletManager) HandleRPCPanic(ctx context.Context, name string, args,

if *err != nil {
// error case
rootCause := vterrors.RootCause(*err)
if sqlErr, ok := rootCause.(*sqlerror.SQLError); ok {
// flatten the error and add appropriate error code because
// *sqlerror.SQLError does not have an .ErrorCode() method.
*err = vterrors.New(sqlErr.VtRpcErrorCode(), (*err).Error())
}

log.Warningf("TabletManager.%v(%v)(on %v from %v) error: %v", name, args, topoproto.TabletAliasString(tm.tabletAlias), from, (*err).Error())
*err = vterrors.Wrapf(*err, "TabletManager.%v on %v", name, topoproto.TabletAliasString(tm.tabletAlias))
*err = vterrors.ToGRPC(vterrors.Wrapf(*err, "TabletManager.%v on %v", name, topoproto.TabletAliasString(tm.tabletAlias)))
} else {
// success case
log.Infof("TabletManager.%v(%v)(on %v from %v): %#v", name, args, topoproto.TabletAliasString(tm.tabletAlias), from, reply)
Expand Down
66 changes: 3 additions & 63 deletions go/vt/vttablet/tabletserver/tabletserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1673,70 +1673,10 @@ func (tsv *TabletServer) convertAndLogError(ctx context.Context, sql string, bin
}

func convertErrorCode(err error) vtrpcpb.Code {
errCode := vterrors.Code(err)
sqlErr, ok := err.(*sqlerror.SQLError)
if !ok {
return errCode
}

switch sqlErr.Number() {
case sqlerror.ERNotSupportedYet:
errCode = vtrpcpb.Code_UNIMPLEMENTED
case sqlerror.ERDiskFull, sqlerror.EROutOfMemory, sqlerror.EROutOfSortMemory, sqlerror.ERConCount, sqlerror.EROutOfResources, sqlerror.ERRecordFileFull, sqlerror.ERHostIsBlocked,
sqlerror.ERCantCreateThread, sqlerror.ERTooManyDelayedThreads, sqlerror.ERNetPacketTooLarge, sqlerror.ERTooManyUserConnections, sqlerror.ERLockTableFull, sqlerror.ERUserLimitReached:
errCode = vtrpcpb.Code_RESOURCE_EXHAUSTED
case sqlerror.ERLockWaitTimeout:
errCode = vtrpcpb.Code_DEADLINE_EXCEEDED
case sqlerror.CRServerGone, sqlerror.ERServerShutdown, sqlerror.ERServerIsntAvailable, sqlerror.CRConnectionError, sqlerror.CRConnHostError:
errCode = vtrpcpb.Code_UNAVAILABLE
case sqlerror.ERFormNotFound, sqlerror.ERKeyNotFound, sqlerror.ERBadFieldError, sqlerror.ERNoSuchThread, sqlerror.ERUnknownTable, sqlerror.ERCantFindUDF, sqlerror.ERNonExistingGrant,
sqlerror.ERNoSuchTable, sqlerror.ERNonExistingTableGrant, sqlerror.ERKeyDoesNotExist:
errCode = vtrpcpb.Code_NOT_FOUND
case sqlerror.ERDBAccessDenied, sqlerror.ERAccessDeniedError, sqlerror.ERKillDenied, sqlerror.ERNoPermissionToCreateUsers:
errCode = vtrpcpb.Code_PERMISSION_DENIED
case sqlerror.ERNoDb, sqlerror.ERNoSuchIndex, sqlerror.ERCantDropFieldOrKey, sqlerror.ERTableNotLockedForWrite, sqlerror.ERTableNotLocked, sqlerror.ERTooBigSelect, sqlerror.ERNotAllowedCommand,
sqlerror.ERTooLongString, sqlerror.ERDelayedInsertTableLocked, sqlerror.ERDupUnique, sqlerror.ERRequiresPrimaryKey, sqlerror.ERCantDoThisDuringAnTransaction, sqlerror.ERReadOnlyTransaction,
sqlerror.ERCannotAddForeign, sqlerror.ERNoReferencedRow, sqlerror.ERRowIsReferenced, sqlerror.ERCantUpdateWithReadLock, sqlerror.ERNoDefault, sqlerror.EROperandColumns,
sqlerror.ERSubqueryNo1Row, sqlerror.ERNonUpdateableTable, sqlerror.ERFeatureDisabled, sqlerror.ERDuplicatedValueInType, sqlerror.ERRowIsReferenced2,
sqlerror.ErNoReferencedRow2, sqlerror.ERWarnDataOutOfRange:
errCode = vtrpcpb.Code_FAILED_PRECONDITION
case sqlerror.EROptionPreventsStatement:
errCode = vtrpcpb.Code_CLUSTER_EVENT
case sqlerror.ERTableExists, sqlerror.ERDupEntry, sqlerror.ERFileExists, sqlerror.ERUDFExists:
errCode = vtrpcpb.Code_ALREADY_EXISTS
case sqlerror.ERGotSignal, sqlerror.ERForcingClose, sqlerror.ERAbortingConnection, sqlerror.ERLockDeadlock:
// For ERLockDeadlock, a deadlock rolls back the transaction.
errCode = vtrpcpb.Code_ABORTED
case sqlerror.ERUnknownComError, sqlerror.ERBadNullError, sqlerror.ERBadDb, sqlerror.ERBadTable, sqlerror.ERNonUniq, sqlerror.ERWrongFieldWithGroup, sqlerror.ERWrongGroupField,
sqlerror.ERWrongSumSelect, sqlerror.ERWrongValueCount, sqlerror.ERTooLongIdent, sqlerror.ERDupFieldName, sqlerror.ERDupKeyName, sqlerror.ERWrongFieldSpec, sqlerror.ERParseError,
sqlerror.EREmptyQuery, sqlerror.ERNonUniqTable, sqlerror.ERInvalidDefault, sqlerror.ERMultiplePriKey, sqlerror.ERTooManyKeys, sqlerror.ERTooManyKeyParts, sqlerror.ERTooLongKey,
sqlerror.ERKeyColumnDoesNotExist, sqlerror.ERBlobUsedAsKey, sqlerror.ERTooBigFieldLength, sqlerror.ERWrongAutoKey, sqlerror.ERWrongFieldTerminators, sqlerror.ERBlobsAndNoTerminated,
sqlerror.ERTextFileNotReadable, sqlerror.ERWrongSubKey, sqlerror.ERCantRemoveAllFields, sqlerror.ERUpdateTableUsed, sqlerror.ERNoTablesUsed, sqlerror.ERTooBigSet,
sqlerror.ERBlobCantHaveDefault, sqlerror.ERWrongDbName, sqlerror.ERWrongTableName, sqlerror.ERUnknownProcedure, sqlerror.ERWrongParamCountToProcedure,
sqlerror.ERWrongParametersToProcedure, sqlerror.ERFieldSpecifiedTwice, sqlerror.ERInvalidGroupFuncUse, sqlerror.ERTableMustHaveColumns, sqlerror.ERUnknownCharacterSet,
sqlerror.ERTooManyTables, sqlerror.ERTooManyFields, sqlerror.ERTooBigRowSize, sqlerror.ERWrongOuterJoin, sqlerror.ERNullColumnInIndex, sqlerror.ERFunctionNotDefined,
sqlerror.ERWrongValueCountOnRow, sqlerror.ERInvalidUseOfNull, sqlerror.ERRegexpError, sqlerror.ERMixOfGroupFuncAndFields, sqlerror.ERIllegalGrantForTable, sqlerror.ERSyntaxError,
sqlerror.ERWrongColumnName, sqlerror.ERWrongKeyColumn, sqlerror.ERBlobKeyWithoutLength, sqlerror.ERPrimaryCantHaveNull, sqlerror.ERTooManyRows, sqlerror.ERUnknownSystemVariable,
sqlerror.ERSetConstantsOnly, sqlerror.ERWrongArguments, sqlerror.ERWrongUsage, sqlerror.ERWrongNumberOfColumnsInSelect, sqlerror.ERDupArgument, sqlerror.ERLocalVariable,
sqlerror.ERGlobalVariable, sqlerror.ERWrongValueForVar, sqlerror.ERWrongTypeForVar, sqlerror.ERVarCantBeRead, sqlerror.ERCantUseOptionHere, sqlerror.ERIncorrectGlobalLocalVar,
sqlerror.ERWrongFKDef, sqlerror.ERKeyRefDoNotMatchTableRef, sqlerror.ERCyclicReference, sqlerror.ERCollationCharsetMismatch, sqlerror.ERCantAggregate2Collations,
sqlerror.ERCantAggregate3Collations, sqlerror.ERCantAggregateNCollations, sqlerror.ERVariableIsNotStruct, sqlerror.ERUnknownCollation, sqlerror.ERWrongNameForIndex,
sqlerror.ERWrongNameForCatalog, sqlerror.ERBadFTColumn, sqlerror.ERTruncatedWrongValue, sqlerror.ERTooMuchAutoTimestampCols, sqlerror.ERInvalidOnUpdate, sqlerror.ERUnknownTimeZone,
sqlerror.ERInvalidCharacterString, sqlerror.ERIllegalReference, sqlerror.ERDerivedMustHaveAlias, sqlerror.ERTableNameNotAllowedHere, sqlerror.ERDataTooLong, sqlerror.ERDataOutOfRange,
sqlerror.ERTruncatedWrongValueForField, sqlerror.ERIllegalValueForType:
errCode = vtrpcpb.Code_INVALID_ARGUMENT
case sqlerror.ERSpecifiedAccessDenied:
errCode = vtrpcpb.Code_PERMISSION_DENIED
// This code is also utilized for Google internal failover error code.
if strings.Contains(err.Error(), "failover in progress") {
errCode = vtrpcpb.Code_FAILED_PRECONDITION
}
case sqlerror.CRServerLost:
// Query was killed.
errCode = vtrpcpb.Code_CANCELED
if sqlErr, ok := err.(*sqlerror.SQLError); ok {
return sqlErr.VtRpcErrorCode()
}

return errCode
return vterrors.Code(err)
}

// StreamHealth streams the health status to callback.
Expand Down
Loading