vitess.io/vitess@v0.16.2/go/vt/vtgate/semantics/errors.go (about) 1 /* 2 Copyright 2022 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package semantics 18 19 import ( 20 "fmt" 21 22 vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" 23 "vitess.io/vitess/go/vt/sqlparser" 24 "vitess.io/vitess/go/vt/vterrors" 25 ) 26 27 type ( 28 ErrorCode int 29 30 Error struct { 31 Code ErrorCode 32 args []any 33 } 34 ErrType int 35 36 info struct { 37 format string 38 state vterrors.State 39 code vtrpcpb.Code 40 id string 41 typ ErrType 42 } 43 ) 44 45 const ( 46 Other ErrType = iota 47 Unsupported 48 Bug 49 ) 50 51 const ( 52 UnionColumnsDoNotMatch ErrorCode = iota 53 UnsupportedMultiTablesInUpdate 54 UnsupportedNaturalJoin 55 TableNotUpdatable 56 UnionWithSQLCalcFoundRows 57 SQLCalcFoundRowsUsage 58 CantUseOptionHere 59 MissingInVSchema 60 NotSequenceTable 61 NextWithMultipleTables 62 LockOnlyWithDual 63 QualifiedOrderInUnion 64 JSONTables 65 Buggy 66 ColumnNotFound 67 AmbiguousColumn 68 ) 69 70 func NewError(code ErrorCode, args ...any) *Error { 71 return &Error{ 72 Code: code, 73 args: args, 74 } 75 } 76 77 var errors = map[ErrorCode]info{ 78 UnionColumnsDoNotMatch: { 79 format: "The used SELECT statements have a different number of columns", 80 state: vterrors.WrongNumberOfColumnsInSelect, 81 code: vtrpcpb.Code_FAILED_PRECONDITION, 82 }, 83 UnsupportedMultiTablesInUpdate: { 84 format: "multiple tables in update", 85 typ: Unsupported, 86 }, 87 TableNotUpdatable: { 88 format: "The target table %s of the UPDATE is not updatable", 89 state: vterrors.NonUpdateableTable, 90 code: vtrpcpb.Code_INVALID_ARGUMENT, 91 }, 92 UnsupportedNaturalJoin: { 93 format: "%s", 94 typ: Unsupported, 95 }, 96 UnionWithSQLCalcFoundRows: { 97 format: "SQL_CALC_FOUND_ROWS not supported with union", 98 typ: Unsupported, 99 }, 100 SQLCalcFoundRowsUsage: { 101 format: "Incorrect usage/placement of 'SQL_CALC_FOUND_ROWS'", 102 code: vtrpcpb.Code_INVALID_ARGUMENT, 103 }, 104 CantUseOptionHere: { 105 format: "Incorrect usage/placement of '%s'", 106 state: vterrors.CantUseOptionHere, 107 code: vtrpcpb.Code_INVALID_ARGUMENT, 108 }, 109 MissingInVSchema: { 110 format: "Table information is not provided in vschema", 111 code: vtrpcpb.Code_INVALID_ARGUMENT, 112 }, 113 NotSequenceTable: { 114 format: "NEXT used on a non-sequence table", 115 code: vtrpcpb.Code_INVALID_ARGUMENT, 116 }, 117 NextWithMultipleTables: { 118 format: "Next statement should not contain multiple tables", 119 typ: Bug, 120 }, 121 LockOnlyWithDual: { 122 format: "%v allowed only with dual", 123 code: vtrpcpb.Code_UNIMPLEMENTED, 124 }, 125 QualifiedOrderInUnion: { 126 format: "Table %s from one of the SELECTs cannot be used in global ORDER clause", 127 }, 128 JSONTables: { 129 format: "json_table expressions", 130 typ: Unsupported, 131 }, 132 Buggy: { 133 format: "%s", 134 typ: Bug, 135 }, 136 ColumnNotFound: { 137 format: "symbol %s not found", 138 state: vterrors.BadFieldError, 139 code: vtrpcpb.Code_INVALID_ARGUMENT, 140 }, 141 AmbiguousColumn: { 142 format: "Column '%s' in field list is ambiguous", 143 state: vterrors.BadFieldError, 144 code: vtrpcpb.Code_INVALID_ARGUMENT, 145 }, 146 } 147 148 func (n *Error) Error() string { 149 f, ok := errors[n.Code] 150 if !ok { 151 return "unknown error" 152 } 153 154 format := f.format 155 156 if f.id != "" { 157 format = fmt.Sprintf("%s: %s", f.id, format) 158 } 159 160 switch f.typ { 161 case Unsupported: 162 format = "VT12001: unsupported: " + format 163 case Bug: 164 format = "VT13001: [BUG] " + format 165 } 166 167 var args []any 168 for _, arg := range n.args { 169 ast, isAST := arg.(sqlparser.SQLNode) 170 if isAST { 171 args = append(args, sqlparser.String(ast)) 172 } else { 173 args = append(args, arg) 174 } 175 } 176 177 return fmt.Sprintf(format, args...) 178 } 179 180 func (n *Error) ErrorState() vterrors.State { 181 f, ok := errors[n.Code] 182 if !ok { 183 return vterrors.Undefined 184 } 185 186 return f.state 187 } 188 189 func (n *Error) ErrorCode() vtrpcpb.Code { 190 f, ok := errors[n.Code] 191 if !ok { 192 return vtrpcpb.Code_UNKNOWN 193 } 194 195 switch f.typ { 196 case Unsupported: 197 return vtrpcpb.Code_UNIMPLEMENTED 198 case Bug: 199 return vtrpcpb.Code_INTERNAL 200 default: 201 return f.code 202 } 203 }