diff --git a/go/mysql/sqlerror/sql_error.go b/go/mysql/sqlerror/sql_error.go index fc201be82ef..c7bd75940ef 100644 --- a/go/mysql/sqlerror/sql_error.go +++ b/go/mysql/sqlerror/sql_error.go @@ -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. diff --git a/go/vt/vttablet/tabletmanager/rpc_server.go b/go/vt/vttablet/tabletmanager/rpc_server.go index 78beed43dad..770d21ef4dd 100644 --- a/go/vt/vttablet/tabletmanager/rpc_server.go +++ b/go/vt/vttablet/tabletmanager/rpc_server.go @@ -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. @@ -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) diff --git a/go/vt/vttablet/tabletserver/tabletserver.go b/go/vt/vttablet/tabletserver/tabletserver.go index 79b736f0498..79c5499817d 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -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.