github.com/mitranim/sqlb@v0.7.2/sqlb_err.go (about) 1 package sqlb 2 3 import ( 4 "fmt" 5 "io" 6 r "reflect" 7 ) 8 9 /* 10 String typedef that implements `error`. Errors of this type can be defined as 11 constants. 12 */ 13 type ErrStr string 14 15 // Implement `error`. 16 func (self ErrStr) Error() string { return string(self) } 17 18 // Implement `fmt.Stringer`. 19 func (self ErrStr) String() string { return string(self) } 20 21 // Marginally more efficient than `fmt.Errorf` due to 1 less indirection. 22 func errf(src string, arg ...any) ErrStr { return ErrStr(fmt.Sprintf(src, arg...)) } 23 24 /* 25 Used by `StructAssign` to indicate that no fields were provided, and therefore 26 it was unable to generate valid SQL for an "update set" clause. This can happen 27 because the input struct was missing or empty, or because all fields were 28 excluded through the use of `Sparse`. User code should detect this error to 29 skip the DB request altogether. 30 */ 31 var ErrEmptyAssign = error(ErrEmptyExpr{Err{ 32 `building SQL assignment expression`, 33 ErrStr(`assignment must have at least one field`), 34 }}) 35 36 /* 37 All errors generated by this package have this type, usually wrapped into a more 38 specialized one: `ErrInvalidInput{Err{...}}`. 39 */ 40 type Err struct { 41 While string 42 Cause error 43 } 44 45 var _ = error(Err{}) 46 47 // Implement the `error` interface. 48 func (self Err) Error() string { return self.formatSimple(``) } 49 50 // Implement a hidden interface in "errors". 51 func (self Err) Unwrap() error { return self.Cause } 52 53 var _ = fmt.Formatter(Err{}) 54 55 /* 56 Implement the `fmt.Formatter` interface. Similar to `Err.Error`, but when 57 formatting `.Cause`, uses `%+v`. By convention used by various libraries, this 58 may print the cause's stack trace, if any. 59 */ 60 func (self Err) Format(out fmt.State, verb rune) { self.format(``, out, verb) } 61 62 func (self Err) formatSimple(typ string) string { 63 out := make(formatState, 0, 128) 64 self.format(typ, &out, 0) 65 return out.String() 66 } 67 68 func (self Err) format(typ string, out fmt.State, verb rune) { 69 if self == (Err{}) { 70 return 71 } 72 73 try1(io.WriteString(out, `[sqlb] error`)) 74 75 if typ != `` { 76 try1(io.WriteString(out, ` `)) 77 try1(io.WriteString(out, Ident(typ).String())) 78 } 79 80 if self.While != `` { 81 try1(io.WriteString(out, ` while `)) 82 try1(io.WriteString(out, self.While)) 83 } 84 85 cause := self.Cause 86 if cause != nil { 87 try1(io.WriteString(out, `: `)) 88 89 impl, _ := cause.(fmt.Formatter) 90 if impl != nil { 91 impl.Format(out, verb) 92 } else if out.Flag('+') { 93 fmt.Fprintf(out, `%+v`, cause) 94 } else { 95 try1(io.WriteString(out, cause.Error())) 96 } 97 } 98 } 99 100 // Specialized type for errors reported by some functions. 101 type ErrInvalidInput struct{ Err } 102 103 // Implement the `error` interface. 104 func (self ErrInvalidInput) Error() string { 105 return self.formatSimple(typeNameOf(self)) 106 } 107 108 // Implement the `fmt.Formatter` interface. 109 func (self ErrInvalidInput) Format(out fmt.State, verb rune) { 110 self.format(typeNameOf(self), out, verb) 111 } 112 113 // Specialized type for errors reported by some functions. 114 type ErrMissingArgument struct{ Err } 115 116 // Implement the `error` interface. 117 func (self ErrMissingArgument) Error() string { 118 return self.formatSimple(typeNameOf(self)) 119 } 120 121 // Implement the `fmt.Formatter` interface. 122 func (self ErrMissingArgument) Format(out fmt.State, verb rune) { 123 self.format(typeNameOf(self), out, verb) 124 } 125 126 // Specialized type for errors reported by some functions. 127 type ErrUnexpectedParameter struct{ Err } 128 129 // Implement the `error` interface. 130 func (self ErrUnexpectedParameter) Error() string { 131 return self.formatSimple(typeNameOf(self)) 132 } 133 134 // Implement the `fmt.Formatter` interface. 135 func (self ErrUnexpectedParameter) Format(out fmt.State, verb rune) { 136 self.format(typeNameOf(self), out, verb) 137 } 138 139 // Specialized type for errors reported by some functions. 140 type ErrUnusedArgument struct{ Err } 141 142 // Implement the `error` interface. 143 func (self ErrUnusedArgument) Error() string { 144 return self.formatSimple(typeNameOf(self)) 145 } 146 147 // Implement the `fmt.Formatter` interface. 148 func (self ErrUnusedArgument) Format(out fmt.State, verb rune) { 149 self.format(typeNameOf(self), out, verb) 150 } 151 152 // Specialized type for errors reported by some functions. 153 type ErrOrdinalOutOfBounds struct{ Err } 154 155 // Implement the `error` interface. 156 func (self ErrOrdinalOutOfBounds) Error() string { 157 return self.formatSimple(typeNameOf(self)) 158 } 159 160 // Implement the `fmt.Formatter` interface. 161 func (self ErrOrdinalOutOfBounds) Format(out fmt.State, verb rune) { 162 self.format(typeNameOf(self), out, verb) 163 } 164 165 // Specialized type for errors reported by some functions. 166 type ErrUnknownField struct{ Err } 167 168 // Implement the `error` interface. 169 func (self ErrUnknownField) Error() string { 170 return self.formatSimple(typeNameOf(self)) 171 } 172 173 // Implement the `fmt.Formatter` interface. 174 func (self ErrUnknownField) Format(out fmt.State, verb rune) { 175 self.format(typeNameOf(self), out, verb) 176 } 177 178 // Specialized type for errors reported by some functions. 179 type ErrInternal struct{ Err } 180 181 // Implement the `error` interface. 182 func (self ErrInternal) Error() string { 183 return self.formatSimple(typeNameOf(self)) 184 } 185 186 // Implement the `fmt.Formatter` interface. 187 func (self ErrInternal) Format(out fmt.State, verb rune) { 188 self.format(typeNameOf(self), out, verb) 189 } 190 191 // Specialized type for errors reported by some functions. 192 type ErrUnexpectedEOF struct{ Err } 193 194 // Implement the `error` interface. 195 func (self ErrUnexpectedEOF) Error() string { 196 return self.formatSimple(typeNameOf(self)) 197 } 198 199 // Implement the `fmt.Formatter` interface. 200 func (self ErrUnexpectedEOF) Format(out fmt.State, verb rune) { 201 self.format(typeNameOf(self), out, verb) 202 } 203 204 // Specialized type for errors reported by some functions. 205 type ErrEmptyExpr struct{ Err } 206 207 // Implement the `error` interface. 208 func (self ErrEmptyExpr) Error() string { 209 return self.formatSimple(typeNameOf(self)) 210 } 211 212 // Implement the `fmt.Formatter` interface. 213 func (self ErrEmptyExpr) Format(out fmt.State, verb rune) { 214 self.format(typeNameOf(self), out, verb) 215 } 216 217 func errOrdinal(err error) error { 218 if err == nil { 219 return nil 220 } 221 return ErrInternal{Err{`parsing ordinal parameter`, err}} 222 } 223 224 func errNamed(err error) error { 225 if err == nil { 226 return nil 227 } 228 return ErrInternal{Err{`parsing named parameter`, err}} 229 } 230 231 func errMissingOrdinal(val OrdinalParam) ErrMissingArgument { 232 return ErrMissingArgument{Err{ 233 `building SQL expression`, 234 errf(`missing ordinal argument %q (index %v)`, val, val.Index()), 235 }} 236 } 237 238 func errMissingNamed(val NamedParam) ErrMissingArgument { 239 return ErrMissingArgument{Err{ 240 `building SQL expression`, 241 errf(`missing named argument %q (key %q)`, val, val.Key()), 242 }} 243 } 244 245 func errUnusedOrdinal(val OrdinalParam) ErrUnusedArgument { 246 return ErrUnusedArgument{Err{ 247 `building SQL expression`, 248 errf(`unused ordinal argument %q (index %v)`, val, val.Index()), 249 }} 250 } 251 252 func errUnusedNamed(val NamedParam) ErrUnusedArgument { 253 return ErrUnusedArgument{Err{ 254 `building SQL expression`, 255 errf(`unused named argument %q (key %q)`, val, val.Key()), 256 }} 257 } 258 259 func errExpectedX(desc, while string, val any) ErrInvalidInput { 260 return ErrInvalidInput{Err{ 261 while, 262 errf(`expected %v, found %v`, desc, val), 263 }} 264 } 265 266 func errExpectedSlice(while string, val any) ErrInvalidInput { 267 return errExpectedX(`slice`, while, val) 268 } 269 270 func errExpectedStruct(while string, val any) ErrInvalidInput { 271 return errExpectedX(`struct`, while, val) 272 } 273 274 func errUnexpectedArgs(desc, input any) ErrInvalidInput { 275 return ErrInvalidInput{Err{ 276 `building SQL expression`, 277 errf(`%v expected no arguments, got %#v`, desc, input), 278 }} 279 } 280 281 func errMissingArgs(desc any) ErrInvalidInput { 282 return ErrInvalidInput{Err{ 283 `building SQL expression`, 284 errf(`%v expected arguments, got none`, desc), 285 }} 286 } 287 288 func errUnknownField(while, jsonPath, typeName string) ErrUnknownField { 289 return ErrUnknownField{Err{ 290 while, 291 errf(`no DB path corresponding to JSON path %q in type %v`, jsonPath, typeName), 292 }} 293 } 294 295 func errUnsupportedType(while string, typ r.Type) ErrInvalidInput { 296 return ErrInvalidInput{Err{ 297 while, 298 errf(`unsupported type %q of kind %q`, typ, typ.Kind()), 299 }} 300 } 301 302 func errInvalidOrd(src string) ErrInvalidInput { 303 return ErrInvalidInput{Err{ 304 `parsing ordering expression`, 305 errf( 306 `%q is not a valid ordering string; expected formatSimple: "<ident> (asc|desc)? (nulls (?:first|last))?"`, 307 src, 308 ), 309 }} 310 }