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  }