diff --git a/go/mysql/constants.go b/go/mysql/constants.go index 4ce06953732..673a7f6dc72 100644 --- a/go/mysql/constants.go +++ b/go/mysql/constants.go @@ -177,7 +177,8 @@ const ( ) // Error codes for client-side errors. -// Originally found in include/mysql/errmsg.h +// Originally found in include/mysql/errmsg.h and +// https://dev.mysql.com/doc/refman/5.7/en/error-messages-client.html const ( // CRUnknownError is CR_UNKNOWN_ERROR CRUnknownError = 2000 @@ -227,113 +228,194 @@ const ( ) // Error codes for server-side errors. -// Originally found in include/mysql/mysqld_error.h +// Originally found in include/mysql/mysqld_error.h and +// https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html +// The below are in sorted order by value, grouped by vterror code they should be bucketed into. +// See above reference for more information on each code. const ( - // ERAccessDeniedError is ER_ACCESS_DENIED_ERROR - ERAccessDeniedError = 1045 - - // ERUnknownComError is ER_UNKNOWN_COM_ERROR - ERUnknownComError = 1047 - - // ERBadNullError is ER_BAD_NULL_ERROR - ERBadNullError = 1048 - - // ERServerShutdown is ER_SERVER_SHUTDOWN - ERServerShutdown = 1053 - - // ERDupEntry is ER_DUP_ENTRY - ERDupEntry = 1062 - - // ERUnknownError is ER_UNKNOWN_ERROR + // unknown ERUnknownError = 1105 - // ERBadFieldError is ER_BAD_FIELD_ERROR - ERBadFieldError = 1054 - - // ERRowIsReferenced is ER_ROW_IS_REFERENCED - ERRowIsReferenced = 1217 - - // ERRowIsReferenced2 is ER_ROW_IS_REFERENCED_2 - ERRowIsReferenced2 = 1451 - - // ERNoReferencedRow is ER_NO_REFERENCED_ROW - ERNoReferencedRow = 1216 - - // ErNoReferencedRow2 is ER_NO_REFERENCED_ROW_2 - ErNoReferencedRow2 = 1452 - - // EROperandColumns is ER_OPERAND_COLUMNS - EROperandColumns = 1241 - - // ERSubqueryNo1Row is ER_SUBQUERY_NO_1_ROW - ERSubqueryNo1Row = 1242 - - // ERCyclicReference is ER_CYCLIC_REFERENCE - ERCyclicReference = 1245 - - // ERIllegalReference is ER_ILLEGAL_REFERENCE - ERIllegalReference = 1247 - - // ERDerivedMustHaveAlias is ER_DERIVED_MUST_HAVE_ALIAS - ERDerivedMustHaveAlias = 1248 - - // ERTableNameNotAllowedHere is ER_TABLENAME_NOT_ALLOWED_HERE - ERTableNameNotAllowedHere = 1250 - - // ERTooManyTables is ER_TOO_MANY_TABLES - ERTooManyTables = 1116 - - // ERTooManyFields is ER_TOO_MANY_FIELDS - ERTooManyFields = 1117 - - // ERInvalidGroupFuncUse is ER_INVALID_GROUP_FUNC_USE - ERInvalidGroupFuncUse = 1111 - - // ERNoSuchTable is ER_NO_SUCH_TABLE - ERNoSuchTable = 1146 - - // ERUnknownTable is ER_UNKNOWN_TABLE - ERUnknownTable = 1109 - - // ERWrongTableName is ER_WRONG_TABLE_NAME - ERWrongTableName = 1103 - - // ERWrongDbName is ER_WRONG_DB_NAME - ERWrongDbName = 1102 - - // ERTableNotLockedForWrite is ER_TABLE_NOT_LOCKED_FOR_WRITE - ERTableNotLockedForWrite = 1099 - - // ERTooBigSet is ER_TOO_BIG_SET - ERTooBigSet = 1097 - - // ERUpdateTableUsed is ER_UPDATE_TABLE_USED - ERUpdateTableUsed = 1093 - - // ERSyntaxError is ER_SYNTAX_ERROR - ERSyntaxError = 1149 - - // ERCantDoThisDuringAnTransaction is - // ER_CANT_DO_THIS_DURING_AN_TRANSACTION - ERCantDoThisDuringAnTransaction = 1179 - - // ERLockWaitTimeout is ER_LOCK_WAIT_TIMEOUT + // unimplemented + ERNotSupportedYet = 1235 + + // resource exhausted + ERDiskFull = 1021 + EROutOfMemory = 1037 + EROutOfSortMemory = 1038 + ERConCount = 1040 + EROutOfResources = 1041 + ERRecordFileFull = 1114 + ERHostIsBlocked = 1129 + ERCantCreateThread = 1135 + ERTooManyDelayedThreads = 1151 + ERNetPacketTooLarge = 1153 + ERTooManyUserConnections = 1203 + ERLockTableFull = 1206 + ERUserLimitReached = 1226 + + // deadline exceeded ERLockWaitTimeout = 1205 - // ERLockDeadlock is ER_LOCK_DEADLOCK - ERLockDeadlock = 1213 - - // EROptionPreventsStatement is ER_OPTION_PREVENTS_STATEMENT - EROptionPreventsStatement = 1290 - - // ERDataTooLong is ER_DATA_TOO_LONG - ERDataTooLong = 1406 - - // ERDataOutOfRange is ER_DATA_OUT_OF_RANGE - ERDataOutOfRange = 1690 + // unavailable + ERServerShutdown = 1053 - // ERTruncatedWrongValueForField is ER_TRUNCATED_WRONG_VALUE_FOR_FIELD - ERTruncatedWrongValueForField = 1366 + // not found + ERFormNotFound = 1029 + ERKeyNotFound = 1032 + ERBadFieldError = 1054 + ERNoSuchThread = 1094 + ERUnknownTable = 1109 + ERCantFindUDF = 1122 + ERNonExistingGrant = 1141 + ERNoSuchTable = 1146 + ERNonExistingTableGrant = 1147 + ERKeyDoesNotExist = 1176 + + // permissions + ERDBAccessDenied = 1044 + ERAccessDeniedError = 1045 + ERKillDenied = 1095 + ERNoPermissionToCreateUsers = 1211 + ERSpecifiedAccessDenied = 1227 + + // failed precondition + ERNoDb = 1046 + ERNoSuchIndex = 1082 + ERCantDropFieldOrKey = 1091 + ERTableNotLockedForWrite = 1099 + ERTableNotLocked = 1100 + ERTooBigSelect = 1104 + ERNotAllowedCommand = 1148 + ERTooLongString = 1162 + ERDelayedInsertTableLocked = 1165 + ERDupUnique = 1169 + ERRequiresPrimaryKey = 1173 + ERCantDoThisDuringAnTransaction = 1179 + ERReadOnlyTransaction = 1207 + ERCannotAddForeign = 1215 + ERNoReferencedRow = 1216 + ERRowIsReferenced = 1217 + ERCantUpdateWithReadLock = 1223 + ERNoDefault = 1230 + EROperandColumns = 1241 + ERSubqueryNo1Row = 1242 + ERNonUpdateableTable = 1288 + ERFeatureDisabled = 1289 + EROptionPreventsStatement = 1290 + ERDuplicatedValueInType = 1291 + ERRowIsReferenced2 = 1451 + ErNoReferencedRow2 = 1452 + + // already exists + ERTableExists = 1050 + ERDupEntry = 1062 + ERFileExists = 1086 + ERUDFExists = 1125 + + // aborted + ERGotSignal = 1078 + ERForcingClose = 1080 + ERAbortingConnection = 1152 + ERLockDeadlock = 1213 + + // invalid arg + ERUnknownComError = 1047 + ERBadNullError = 1048 + ERBadDb = 1049 + ERBadTable = 1051 + ERNonUniq = 1052 + ERWrongFieldWithGroup = 1055 + ERWrongGroupField = 1056 + ERWrongSumSelect = 1057 + ERWrongValueCount = 1058 + ERTooLongIdent = 1059 + ERDupFieldName = 1060 + ERDupKeyName = 1061 + ERWrongFieldSpec = 1063 + ERParseError = 1064 + EREmptyQuery = 1065 + ERNonUniqTable = 1066 + ERInvalidDefault = 1067 + ERMultiplePriKey = 1068 + ERTooManyKeys = 1069 + ERTooManyKeyParts = 1070 + ERTooLongKey = 1071 + ERKeyColumnDoesNotExist = 1072 + ERBlobUsedAsKey = 1073 + ERTooBigFieldLength = 1074 + ERWrongAutoKey = 1075 + ERWrongFieldTerminators = 1083 + ERBlobsAndNoTerminated = 1084 + ERTextFileNotReadable = 1085 + ERWrongSubKey = 1089 + ERCantRemoveAllFields = 1090 + ERUpdateTableUsed = 1093 + ERNoTablesUsed = 1096 + ERTooBigSet = 1097 + ERBlobCantHaveDefault = 1101 + ERWrongDbName = 1102 + ERWrongTableName = 1103 + ERUnknownProcedure = 1106 + ERWrongParamCountToProcedure = 1107 + ERWrongParametersToProcedure = 1108 + ERFieldSpecifiedTwice = 1110 + ERInvalidGroupFuncUse = 1111 + ERTableMustHaveColumns = 1113 + ERUnknownCharacterSet = 1115 + ERTooManyTables = 1116 + ERTooManyFields = 1117 + ERTooBigRowSize = 1118 + ERWrongOuterJoin = 1120 + ERNullColumnInIndex = 1121 + ERFunctionNotDefined = 1128 + ERWrongValueCountOnRow = 1136 + ERInvalidUseOfNull = 1138 + ERRegexpError = 1139 + ERMixOfGroupFuncAndFields = 1140 + ERIllegalGrantForTable = 1144 + ERSyntaxError = 1149 + ERWrongColumnName = 1166 + ERWrongKeyColumn = 1167 + ERBlobKeyWithoutLength = 1170 + ERPrimaryCantHaveNull = 1171 + ERTooManyRows = 1172 + ERUnknownSystemVariable = 1193 + ERSetConstantsOnly = 1204 + ERWrongArguments = 1210 + ERWrongUsage = 1221 + ERWrongNumberOfColumnsInSelect = 1222 + ERDupArgument = 1225 + ERLocalVariable = 1228 + ERGlobalVariable = 1229 + ERWrongValueForVar = 1231 + ERWrongTypeForVar = 1232 + ERVarCantBeRead = 1233 + ERCantUseOptionHere = 1234 + ERIncorrectGlobalLocalVar = 1238 + ERWrongFKDef = 1239 + ERKeyRefDoNotMatchTableRef = 1240 + ERCyclicReference = 1245 + ERCollationCharsetMismatch = 1253 + ERCantAggregate2Collations = 1267 + ERCantAggregate3Collations = 1270 + ERCantAggregateNCollations = 1271 + ERVariableIsNotStruct = 1272 + ERUnknownCollation = 1273 + ERWrongNameForIndex = 1280 + ERWrongNameForCatalog = 1281 + ERBadFTColumn = 1283 + ERTruncatedWrongValue = 1292 + ERTooMuchAutoTimestampCols = 1293 + ERInvalidOnUpdate = 1294 + ERUnknownTimeZone = 1298 + ERInvalidCharacterString = 1300 + ERIllegalReference = 1247 + ERDerivedMustHaveAlias = 1248 + ERTableNameNotAllowedHere = 1250 + ERDataTooLong = 1406 + ERDataOutOfRange = 1690 + ERTruncatedWrongValueForField = 1366 ) // Sql states for errors. diff --git a/go/sqltypes/arithmetic.go b/go/sqltypes/arithmetic.go index 3d0d1fcf75e..70d5aa54b08 100644 --- a/go/sqltypes/arithmetic.go +++ b/go/sqltypes/arithmetic.go @@ -22,6 +22,8 @@ import ( "strconv" querypb "github.com/youtube/vitess/go/vt/proto/query" + vtrpcpb "github.com/youtube/vitess/go/vt/proto/vtrpc" + "github.com/youtube/vitess/go/vt/vterrors" ) // numeric represents a numeric value extracted from @@ -158,7 +160,7 @@ func Cast(v Value, typ querypb.Type) (Value, error) { // Explicitly disallow Expression. if v.Type() == Expression { - return NULL, fmt.Errorf("%v cannot be cast to %v", v, typ) + return NULL, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%v cannot be cast to %v", v, typ) } // If the above fast-paths were not possible, @@ -175,7 +177,7 @@ func ToUint64(v Value) (uint64, error) { switch num.typ { case Int64: if num.ival < 0 { - return 0, fmt.Errorf("negative number cannot be converted to unsigned: %d", num.ival) + return 0, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "negative number cannot be converted to unsigned: %d", num.ival) } return uint64(num.ival), nil case Uint64: @@ -196,7 +198,7 @@ func ToInt64(v Value) (int64, error) { case Uint64: ival := int64(num.uval) if ival < 0 { - return 0, fmt.Errorf("unsigned number overflows int64 value: %d", num.uval) + return 0, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unsigned number overflows int64 value: %d", num.uval) } return ival, nil } @@ -237,7 +239,7 @@ func ToNative(v Value) (interface{}, error) { case v.IsQuoted() || v.Type() == Decimal: out = v.val case v.Type() == Expression: - err = fmt.Errorf("%v cannot be converted to a go type", v) + err = vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%v cannot be converted to a go type", v) } return out, err } @@ -271,7 +273,7 @@ func newNumeric(v Value) (result numeric, err error) { result.typ = Float64 return } - err = fmt.Errorf("could not parse value: %s", str) + err = vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "could not parse value: %s", str) return } @@ -282,6 +284,7 @@ func newIntegralNumeric(v Value) (result numeric, err error) { case v.IsSigned(): result.ival, err = strconv.ParseInt(str, 10, 64) if err != nil { + err = vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%v", err) return } result.typ = Int64 @@ -289,6 +292,7 @@ func newIntegralNumeric(v Value) (result numeric, err error) { case v.IsUnsigned(): result.uval, err = strconv.ParseUint(str, 10, 64) if err != nil { + err = vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%v", err) return } result.typ = Uint64 @@ -308,7 +312,7 @@ func newIntegralNumeric(v Value) (result numeric, err error) { result.typ = Uint64 return } - err = fmt.Errorf("could not parse value: %s", str) + err = vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "could not parse value: %s", str) return } @@ -362,7 +366,7 @@ overflow: func uintPlusInt(v1 uint64, v2 int64) (numeric, error) { if v2 < 0 { - return numeric{}, fmt.Errorf("cannot add a negative number to an unsigned integer: %d, %d", v1, v2) + return numeric{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "cannot add a negative number to an unsigned integer: %d, %d", v1, v2) } return uintPlusUint(v1, uint64(v2)), nil } @@ -392,14 +396,14 @@ func castFromNumeric(v numeric, resultType querypb.Type) (Value, error) { case Int64: return MakeTrusted(resultType, strconv.AppendInt(nil, v.ival, 10)), nil case Uint64, Float64: - return NULL, fmt.Errorf("unexpected type conversion: %v to %v", v.typ, resultType) + return NULL, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unexpected type conversion: %v to %v", v.typ, resultType) } case IsUnsigned(resultType): switch v.typ { case Uint64: return MakeTrusted(resultType, strconv.AppendUint(nil, v.uval, 10)), nil case Int64, Float64: - return NULL, fmt.Errorf("unexpected type conversion: %v to %v", v.typ, resultType) + return NULL, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unexpected type conversion: %v to %v", v.typ, resultType) } case IsFloat(resultType) || resultType == Decimal: switch v.typ { @@ -415,7 +419,7 @@ func castFromNumeric(v numeric, resultType querypb.Type) (Value, error) { return MakeTrusted(resultType, strconv.AppendFloat(nil, v.fval, format, -1, 64)), nil } } - return NULL, fmt.Errorf("unexpected type conversion to non-numeric: %v", resultType) + return NULL, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unexpected type conversion to non-numeric: %v", resultType) } func compareNumeric(v1, v2 numeric) int { diff --git a/go/sqltypes/plan_value.go b/go/sqltypes/plan_value.go index f7dfde7d368..4745241ef0e 100644 --- a/go/sqltypes/plan_value.go +++ b/go/sqltypes/plan_value.go @@ -18,10 +18,10 @@ package sqltypes import ( "encoding/json" - "errors" - "fmt" querypb "github.com/youtube/vitess/go/vt/proto/query" + vtrpcpb "github.com/youtube/vitess/go/vt/proto/vtrpc" + "github.com/youtube/vitess/go/vt/vterrors" ) // PlanValue represents a value or a list of values for @@ -87,7 +87,7 @@ func (pv PlanValue) ResolveValue(bindVars map[string]*querypb.BindVariable) (Val case pv.ListKey != "" || pv.Values != nil: // This code is unreachable because the parser does not allow // multi-value constructs where a single value is expected. - return NULL, errors.New("a list was supplied where a single value was expected") + return NULL, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "a list was supplied where a single value was expected") } return NULL, nil } @@ -95,10 +95,10 @@ func (pv PlanValue) ResolveValue(bindVars map[string]*querypb.BindVariable) (Val func (pv PlanValue) lookupValue(bindVars map[string]*querypb.BindVariable) (*querypb.BindVariable, error) { bv, ok := bindVars[pv.Key] if !ok { - return nil, fmt.Errorf("missing bind var %s", pv.Key) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "missing bind var %s", pv.Key) } if bv.Type == querypb.Type_TUPLE { - return nil, fmt.Errorf("TUPLE was supplied for single value bind var %s", pv.ListKey) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "TUPLE was supplied for single value bind var %s", pv.ListKey) } return bv, nil } @@ -129,16 +129,16 @@ func (pv PlanValue) ResolveList(bindVars map[string]*querypb.BindVariable) ([]Va } // This code is unreachable because the parser does not allow // single value constructs where multiple values are expected. - return nil, errors.New("a single value was supplied where a list was expected") + return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "a single value was supplied where a list was expected") } func (pv PlanValue) lookupList(bindVars map[string]*querypb.BindVariable) (*querypb.BindVariable, error) { bv, ok := bindVars[pv.ListKey] if !ok { - return nil, fmt.Errorf("missing bind var %s", pv.ListKey) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "missing bind var %s", pv.ListKey) } if bv.Type != querypb.Type_TUPLE { - return nil, fmt.Errorf("single value was supplied for TUPLE bind var %s", pv.ListKey) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "single value was supplied for TUPLE bind var %s", pv.ListKey) } return bv, nil } @@ -171,7 +171,7 @@ func rowCount(pvs []PlanValue, bindVars map[string]*querypb.BindVariable) (int, case l: return nil default: - return errors.New("mismatch in number of column values") + return vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "mismatch in number of column values") } } diff --git a/go/vt/sqlparser/analyzer.go b/go/vt/sqlparser/analyzer.go index 99ce713f270..8b7ac5009e6 100644 --- a/go/vt/sqlparser/analyzer.go +++ b/go/vt/sqlparser/analyzer.go @@ -19,13 +19,14 @@ package sqlparser // analyzer.go contains utility analysis functions. import ( - "errors" "fmt" "strconv" "strings" "unicode" "github.com/youtube/vitess/go/sqltypes" + vtrpcpb "github.com/youtube/vitess/go/vt/proto/vtrpc" + "github.com/youtube/vitess/go/vt/vterrors" ) // These constants are used to identify the SQL statement type. @@ -168,7 +169,7 @@ func NewPlanValue(node Expr) (sqltypes.PlanValue, error) { case IntVal: n, err := sqltypes.NewIntegral(string(node.Val)) if err != nil { - return sqltypes.PlanValue{}, err + return sqltypes.PlanValue{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%v", err) } return sqltypes.PlanValue{Value: n}, nil case StrVal: @@ -176,7 +177,7 @@ func NewPlanValue(node Expr) (sqltypes.PlanValue, error) { case HexVal: v, err := node.HexDecode() if err != nil { - return sqltypes.PlanValue{}, err + return sqltypes.PlanValue{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%v", err) } return sqltypes.PlanValue{Value: sqltypes.MakeTrusted(sqltypes.VarBinary, v)}, nil } @@ -192,7 +193,7 @@ func NewPlanValue(node Expr) (sqltypes.PlanValue, error) { return sqltypes.PlanValue{}, err } if innerpv.ListKey != "" || innerpv.Values != nil { - return sqltypes.PlanValue{}, errors.New("unsupported: nested lists") + return sqltypes.PlanValue{}, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: nested lists") } pv.Values = append(pv.Values, innerpv) } @@ -200,7 +201,7 @@ func NewPlanValue(node Expr) (sqltypes.PlanValue, error) { case *NullVal: return sqltypes.PlanValue{}, nil } - return sqltypes.PlanValue{}, fmt.Errorf("expression is too complex '%v'", String(node)) + return sqltypes.PlanValue{}, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "expression is too complex '%v'", String(node)) } // StringIn is a convenience function that returns diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index 131ea9e6c0f..3a587b65f47 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -55,7 +55,7 @@ func Parse(sql string) (Statement, error) { tokenizer.ParseTree = tokenizer.partialDDL return tokenizer.ParseTree, nil } - return nil, errors.New(tokenizer.LastError) + return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, tokenizer.LastError) } return tokenizer.ParseTree, nil } diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index ef3f2945ba2..c603d34c226 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -395,7 +395,7 @@ func (e *Executor) handleShow(ctx context.Context, session *vtgatepb.Session, sq } ks, ok := e.VSchema().Keyspaces[target.Keyspace] if !ok { - return nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "keyspace %s not found in vschema", target.Keyspace) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "keyspace %s not found in vschema", target.Keyspace) } var tables []string diff --git a/go/vt/vtgate/vcursor_impl.go b/go/vt/vtgate/vcursor_impl.go index c8f92e11c2a..3c0f7285aec 100644 --- a/go/vt/vtgate/vcursor_impl.go +++ b/go/vt/vtgate/vcursor_impl.go @@ -82,7 +82,7 @@ func (vc *vcursorImpl) DefaultKeyspace() (*vindexes.Keyspace, error) { } ks, ok := vc.executor.VSchema().Keyspaces[vc.target.Keyspace] if !ok { - return nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "keyspace %s not found in vschema", vc.target.Keyspace) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "keyspace %s not found in vschema", vc.target.Keyspace) } return ks.Keyspace, nil } diff --git a/go/vt/vttablet/tabletserver/messager/engine.go b/go/vt/vttablet/tabletserver/messager/engine.go index 875d31e504d..8eb2d4d8017 100644 --- a/go/vt/vttablet/tabletserver/messager/engine.go +++ b/go/vt/vttablet/tabletserver/messager/engine.go @@ -182,7 +182,7 @@ func (me *Engine) GenerateLoadMessagesQuery(name string) (*sqlparser.ParsedQuery defer me.mu.Unlock() mm := me.managers[name] if mm == nil { - return nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "message table %s not found in schema", name) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "message table %s not found in schema", name) } return mm.loadMessagesQuery, nil } @@ -193,7 +193,7 @@ func (me *Engine) GenerateAckQuery(name string, ids []string) (string, map[strin defer me.mu.Unlock() mm := me.managers[name] if mm == nil { - return "", nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "message table %s not found in schema", name) + return "", nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "message table %s not found in schema", name) } query, bv := mm.GenerateAckQuery(ids) return query, bv, nil @@ -205,7 +205,7 @@ func (me *Engine) GeneratePostponeQuery(name string, ids []string) (string, map[ defer me.mu.Unlock() mm := me.managers[name] if mm == nil { - return "", nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "message table %s not found in schema", name) + return "", nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "message table %s not found in schema", name) } query, bv := mm.GeneratePostponeQuery(ids) return query, bv, nil @@ -217,7 +217,7 @@ func (me *Engine) GeneratePurgeQuery(name string, timeCutoff int64) (string, map defer me.mu.Unlock() mm := me.managers[name] if mm == nil { - return "", nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "message table %s not found in schema", name) + return "", nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "message table %s not found in schema", name) } query, bv := mm.GeneratePurgeQuery(timeCutoff) return query, bv, nil diff --git a/go/vt/vttablet/tabletserver/planbuilder/dml.go b/go/vt/vttablet/tabletserver/planbuilder/dml.go index 20e36df475f..d639785bcd8 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/dml.go +++ b/go/vt/vttablet/tabletserver/planbuilder/dml.go @@ -337,7 +337,7 @@ func analyzeInsertNoType(ins *sqlparser.Insert, plan *Plan, table *schema.Table) for _, col := range ins.Columns { colIndex := table.FindColumn(col) if colIndex == -1 { - return nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "column %v not found in table %s", col, table.Name) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "column %v not found in table %s", col, table.Name) } plan.ColumnNumbers = append(plan.ColumnNumbers, colIndex) } @@ -469,7 +469,6 @@ func analyzeInsertMessage(ins *sqlparser.Insert, plan *Plan, table *schema.Table // time_created should always be now. col = sqlparser.NewColIdent("time_created") if num := ins.Columns.FindColumn(col); num >= 0 { - return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "%s must not be specified for message insert", col.String()) } _ = addVal(ins, col, timeNow) diff --git a/go/vt/vttablet/tabletserver/planbuilder/plan.go b/go/vt/vttablet/tabletserver/planbuilder/plan.go index 065e60dda9b..75ef1ff9a83 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/plan.go +++ b/go/vt/vttablet/tabletserver/planbuilder/plan.go @@ -18,11 +18,10 @@ package planbuilder import ( "encoding/json" - "errors" "fmt" "github.com/youtube/vitess/go/sqltypes" - "github.com/youtube/vitess/go/vt/proto/vtrpc" + vtrpcpb "github.com/youtube/vitess/go/vt/proto/vtrpc" "github.com/youtube/vitess/go/vt/sqlparser" "github.com/youtube/vitess/go/vt/tableacl" "github.com/youtube/vitess/go/vt/vterrors" @@ -31,7 +30,7 @@ import ( var ( // ErrTooComplex indicates given sql query is too complex. - ErrTooComplex = errors.New("Complex") + ErrTooComplex = vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "Complex") execLimit = &sqlparser.Limit{Rowcount: sqlparser.NewValArg([]byte(":#maxLimit"))} ) @@ -250,7 +249,7 @@ func (plan *Plan) TableName() sqlparser.TableIdent { func (plan *Plan) setTable(tableName sqlparser.TableIdent, tables map[string]*schema.Table) (*schema.Table, error) { if plan.Table = tables[tableName.String()]; plan.Table == nil { - return nil, vterrors.Errorf(vtrpc.Code_NOT_FOUND, "table %s not found in schema", tableName) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "table %s not found in schema", tableName) } return plan.Table, nil } @@ -287,7 +286,8 @@ func Build(sql string, tables map[string]*schema.Table) (*Plan, error) { case *sqlparser.OtherAdmin: return &Plan{PlanID: PlanOtherAdmin}, nil } - return nil, errors.New("invalid SQL") + + return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "invalid SQL") } // BuildStreaming builds a streaming plan based on the schema. @@ -305,7 +305,7 @@ func BuildStreaming(sql string, tables map[string]*schema.Table) (*Plan, error) switch stmt := statement.(type) { case *sqlparser.Select: if stmt.Lock != "" { - return nil, errors.New("select with lock not allowed for streaming") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "select with lock not allowed for streaming") } if tableName := analyzeFrom(stmt.From); !tableName.IsEmpty() { plan.setTable(tableName, tables) @@ -313,7 +313,7 @@ func BuildStreaming(sql string, tables map[string]*schema.Table) (*Plan, error) case *sqlparser.OtherRead, *sqlparser.Show, *sqlparser.Union: // pass default: - return nil, fmt.Errorf("'%v' not allowed for streaming", sqlparser.String(stmt)) + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "'%v' not allowed for streaming", sqlparser.String(stmt)) } return plan, nil @@ -326,10 +326,10 @@ func BuildMessageStreaming(name string, tables map[string]*schema.Table) (*Plan, Table: tables[name], } if plan.Table == nil { - return nil, fmt.Errorf("table %s not found in schema", name) + return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "table %s not found in schema", name) } if plan.Table.Type != schema.Message { - return nil, fmt.Errorf("'%s' is not a message table", name) + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "'%s' is not a message table", name) } return plan, nil } diff --git a/go/vt/vttablet/tabletserver/query_engine.go b/go/vt/vttablet/tabletserver/query_engine.go index 8260cd6f382..687dd0d83f7 100644 --- a/go/vt/vttablet/tabletserver/query_engine.go +++ b/go/vt/vttablet/tabletserver/query_engine.go @@ -39,7 +39,6 @@ import ( "github.com/youtube/vitess/go/vt/sqlparser" "github.com/youtube/vitess/go/vt/tableacl" tacl "github.com/youtube/vitess/go/vt/tableacl/acl" - "github.com/youtube/vitess/go/vt/vterrors" "github.com/youtube/vitess/go/vt/vttablet/tabletserver/connpool" "github.com/youtube/vitess/go/vt/vttablet/tabletserver/planbuilder" "github.com/youtube/vitess/go/vt/vttablet/tabletserver/rules" @@ -48,7 +47,6 @@ import ( "github.com/youtube/vitess/go/vt/vttablet/tabletserver/txserializer" querypb "github.com/youtube/vitess/go/vt/proto/query" - vtrpcpb "github.com/youtube/vitess/go/vt/proto/vtrpc" ) //_______________________________________________ @@ -301,8 +299,7 @@ func (qe *QueryEngine) GetPlan(ctx context.Context, logStats *tabletenv.LogStats defer qe.mu.RUnlock() splan, err := planbuilder.Build(sql, qe.tables) if err != nil { - // TODO(sougou): Inspect to see if Build can return coded error. - return nil, vterrors.New(vtrpcpb.Code_UNKNOWN, err.Error()) + return nil, err } plan := &TabletPlan{Plan: splan} plan.Rules = qe.queryRuleSources.FilterByPlan(sql, plan.PlanID, plan.TableName().String()) @@ -340,8 +337,7 @@ func (qe *QueryEngine) GetStreamPlan(sql string) (*TabletPlan, error) { defer qe.mu.RUnlock() splan, err := planbuilder.BuildStreaming(sql, qe.tables) if err != nil { - // TODO(sougou): Inspect to see if BuildStreaming can return coded error. - return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, err.Error()) + return nil, err } plan := &TabletPlan{Plan: splan} plan.Rules = qe.queryRuleSources.FilterByPlan(sql, plan.PlanID, plan.TableName().String()) @@ -355,8 +351,7 @@ func (qe *QueryEngine) GetMessageStreamPlan(name string) (*TabletPlan, error) { defer qe.mu.RUnlock() splan, err := planbuilder.BuildMessageStreaming(name, qe.tables) if err != nil { - // TODO(sougou): Inspect to see if BuildMessageStreaming can return coded error. - return nil, vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, err.Error()) + return nil, err } plan := &TabletPlan{Plan: splan} plan.Rules = qe.queryRuleSources.FilterByPlan("stream from "+name, plan.PlanID, plan.TableName().String()) diff --git a/go/vt/vttablet/tabletserver/tabletserver.go b/go/vt/vttablet/tabletserver/tabletserver.go index 5635d018981..f7f3f932b20 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -1339,38 +1339,67 @@ func (tsv *TabletServer) convertError(ctx context.Context, sql string, bindVaria errstr := err.Error() errnum := sqlErr.Number() sqlState := sqlErr.SQLState() + switch errnum { + case mysql.ERNotSupportedYet: + errCode = vtrpcpb.Code_UNIMPLEMENTED + case mysql.ERDiskFull, mysql.EROutOfMemory, mysql.EROutOfSortMemory, mysql.ERConCount, mysql.EROutOfResources, mysql.ERRecordFileFull, mysql.ERHostIsBlocked, + mysql.ERCantCreateThread, mysql.ERTooManyDelayedThreads, mysql.ERNetPacketTooLarge, mysql.ERTooManyUserConnections, mysql.ERLockTableFull, mysql.ERUserLimitReached: + errCode = vtrpcpb.Code_RESOURCE_EXHAUSTED + case mysql.ERLockWaitTimeout: + errCode = vtrpcpb.Code_DEADLINE_EXCEEDED + case mysql.CRServerGone, mysql.ERServerShutdown: + errCode = vtrpcpb.Code_UNAVAILABLE + case mysql.ERFormNotFound, mysql.ERKeyNotFound, mysql.ERBadFieldError, mysql.ERNoSuchThread, mysql.ERUnknownTable, mysql.ERCantFindUDF, mysql.ERNonExistingGrant, + mysql.ERNoSuchTable, mysql.ERNonExistingTableGrant, mysql.ERKeyDoesNotExist: + errCode = vtrpcpb.Code_NOT_FOUND + case mysql.ERDBAccessDenied, mysql.ERAccessDeniedError, mysql.ERKillDenied, mysql.ERNoPermissionToCreateUsers: + errCode = vtrpcpb.Code_PERMISSION_DENIED + case mysql.ERNoDb, mysql.ERNoSuchIndex, mysql.ERCantDropFieldOrKey, mysql.ERTableNotLockedForWrite, mysql.ERTableNotLocked, mysql.ERTooBigSelect, mysql.ERNotAllowedCommand, + mysql.ERTooLongString, mysql.ERDelayedInsertTableLocked, mysql.ERDupUnique, mysql.ERRequiresPrimaryKey, mysql.ERCantDoThisDuringAnTransaction, mysql.ERReadOnlyTransaction, + mysql.ERCannotAddForeign, mysql.ERNoReferencedRow, mysql.ERRowIsReferenced, mysql.ERCantUpdateWithReadLock, mysql.ERNoDefault, mysql.EROperandColumns, + mysql.ERSubqueryNo1Row, mysql.ERNonUpdateableTable, mysql.ERFeatureDisabled, mysql.ERDuplicatedValueInType, mysql.ERRowIsReferenced2, + mysql.ErNoReferencedRow2: + errCode = vtrpcpb.Code_FAILED_PRECONDITION case mysql.EROptionPreventsStatement: // Special-case this error code. It's probably because // there was a failover and there are old clients still connected. if strings.Contains(errstr, "read-only") { errCode = vtrpcpb.Code_FAILED_PRECONDITION } - case 1227: // Google internal failover error code. + case mysql.ERTableExists, mysql.ERDupEntry, mysql.ERFileExists, mysql.ERUDFExists: + errCode = vtrpcpb.Code_ALREADY_EXISTS + case mysql.ERGotSignal, mysql.ERForcingClose, mysql.ERAbortingConnection, mysql.ERLockDeadlock: + // For ERLockDeadlock, a deadlock rolls back the transaction. + errCode = vtrpcpb.Code_ABORTED + case mysql.ERUnknownComError, mysql.ERBadNullError, mysql.ERBadDb, mysql.ERBadTable, mysql.ERNonUniq, mysql.ERWrongFieldWithGroup, mysql.ERWrongGroupField, + mysql.ERWrongSumSelect, mysql.ERWrongValueCount, mysql.ERTooLongIdent, mysql.ERDupFieldName, mysql.ERDupKeyName, mysql.ERWrongFieldSpec, mysql.ERParseError, + mysql.EREmptyQuery, mysql.ERNonUniqTable, mysql.ERInvalidDefault, mysql.ERMultiplePriKey, mysql.ERTooManyKeys, mysql.ERTooManyKeyParts, mysql.ERTooLongKey, + mysql.ERKeyColumnDoesNotExist, mysql.ERBlobUsedAsKey, mysql.ERTooBigFieldLength, mysql.ERWrongAutoKey, mysql.ERWrongFieldTerminators, mysql.ERBlobsAndNoTerminated, + mysql.ERTextFileNotReadable, mysql.ERWrongSubKey, mysql.ERCantRemoveAllFields, mysql.ERUpdateTableUsed, mysql.ERNoTablesUsed, mysql.ERTooBigSet, + mysql.ERBlobCantHaveDefault, mysql.ERWrongDbName, mysql.ERWrongTableName, mysql.ERUnknownProcedure, mysql.ERWrongParamCountToProcedure, + mysql.ERWrongParametersToProcedure, mysql.ERFieldSpecifiedTwice, mysql.ERInvalidGroupFuncUse, mysql.ERTableMustHaveColumns, mysql.ERUnknownCharacterSet, + mysql.ERTooManyTables, mysql.ERTooManyFields, mysql.ERTooBigRowSize, mysql.ERWrongOuterJoin, mysql.ERNullColumnInIndex, mysql.ERFunctionNotDefined, + mysql.ERWrongValueCountOnRow, mysql.ERInvalidUseOfNull, mysql.ERRegexpError, mysql.ERMixOfGroupFuncAndFields, mysql.ERIllegalGrantForTable, mysql.ERSyntaxError, + mysql.ERWrongColumnName, mysql.ERWrongKeyColumn, mysql.ERBlobKeyWithoutLength, mysql.ERPrimaryCantHaveNull, mysql.ERTooManyRows, mysql.ERUnknownSystemVariable, + mysql.ERSetConstantsOnly, mysql.ERWrongArguments, mysql.ERWrongUsage, mysql.ERWrongNumberOfColumnsInSelect, mysql.ERDupArgument, mysql.ERLocalVariable, + mysql.ERGlobalVariable, mysql.ERWrongValueForVar, mysql.ERWrongTypeForVar, mysql.ERVarCantBeRead, mysql.ERCantUseOptionHere, mysql.ERIncorrectGlobalLocalVar, + mysql.ERWrongFKDef, mysql.ERKeyRefDoNotMatchTableRef, mysql.ERCyclicReference, mysql.ERCollationCharsetMismatch, mysql.ERCantAggregate2Collations, + mysql.ERCantAggregate3Collations, mysql.ERCantAggregateNCollations, mysql.ERVariableIsNotStruct, mysql.ERUnknownCollation, mysql.ERWrongNameForIndex, + mysql.ERWrongNameForCatalog, mysql.ERBadFTColumn, mysql.ERTruncatedWrongValue, mysql.ERTooMuchAutoTimestampCols, mysql.ERInvalidOnUpdate, mysql.ERUnknownTimeZone, + mysql.ERInvalidCharacterString, mysql.ERIllegalReference, mysql.ERDerivedMustHaveAlias, mysql.ERTableNameNotAllowedHere, mysql.ERDataTooLong, mysql.ERDataOutOfRange, + mysql.ERTruncatedWrongValueForField: + errCode = vtrpcpb.Code_INVALID_ARGUMENT + case mysql.ERSpecifiedAccessDenied: + // This code is also utilized for Google internal failover error code. if strings.Contains(errstr, "failover in progress") { errCode = vtrpcpb.Code_FAILED_PRECONDITION + } else { + errCode = vtrpcpb.Code_PERMISSION_DENIED } - case mysql.ERDupEntry: - errCode = vtrpcpb.Code_ALREADY_EXISTS - case mysql.ERDataTooLong, mysql.ERDataOutOfRange, mysql.ERBadNullError, mysql.ERSyntaxError, mysql.ERUpdateTableUsed, mysql.ERTooBigSet, - mysql.ERWrongDbName, mysql.ERWrongTableName, mysql.ERInvalidGroupFuncUse, mysql.ERTooManyFields, mysql.ERTooManyTables, - mysql.ERTableNameNotAllowedHere, mysql.ERDerivedMustHaveAlias, mysql.ERIllegalReference, mysql.ERCyclicReference, mysql.ERTruncatedWrongValueForField: - errCode = vtrpcpb.Code_INVALID_ARGUMENT - case mysql.ERLockWaitTimeout: - errCode = vtrpcpb.Code_DEADLINE_EXCEEDED - case mysql.ERLockDeadlock: - // A deadlock rolls back the transaction. - errCode = vtrpcpb.Code_ABORTED case mysql.CRServerLost: // Query was killed. errCode = vtrpcpb.Code_DEADLINE_EXCEEDED - case mysql.CRServerGone, mysql.ERServerShutdown: - errCode = vtrpcpb.Code_UNAVAILABLE - case mysql.ERBadFieldError, mysql.ERUnknownTable, mysql.ERNoSuchTable: - errCode = vtrpcpb.Code_NOT_FOUND - case mysql.ERNoReferencedRow, mysql.ErNoReferencedRow2, mysql.ERRowIsReferenced, mysql.ERRowIsReferenced2, mysql.ERTableNotLockedForWrite, - mysql.ERSubqueryNo1Row, mysql.EROperandColumns, mysql.ERCantDoThisDuringAnTransaction: - errCode = vtrpcpb.Code_FAILED_PRECONDITION } // If TerseErrors is on, strip the error message returned by MySQL and only