2023-05-22 18:08:14 +03:00
|
|
|
package postgres
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
"github.com/jackc/pgx/v5/pgconn"
|
2023-11-20 04:06:36 +03:00
|
|
|
|
|
|
|
"github.com/neilotoole/sq/libsq/core/errz"
|
2024-01-15 04:45:34 +03:00
|
|
|
"github.com/neilotoole/sq/libsq/driver"
|
2023-05-22 18:08:14 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// errw wraps any error from the db. It should be called at
|
|
|
|
// every interaction with the db. If err is nil, nil is returned.
|
|
|
|
// Certain errors will be wrapped in specific error types,
|
|
|
|
// e.g, errz.NotExistError.
|
|
|
|
func errw(err error) error {
|
|
|
|
switch {
|
|
|
|
case err == nil:
|
|
|
|
return nil
|
|
|
|
case hasErrCode(err, errCodeRelationNotExist):
|
2024-01-15 04:45:34 +03:00
|
|
|
return driver.NewNotExistError(err)
|
2023-05-22 18:08:14 +03:00
|
|
|
default:
|
|
|
|
return errz.Err(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
errCodeRelationNotExist = "42P01"
|
|
|
|
errCodeTooManyConnections = "53300"
|
|
|
|
)
|
|
|
|
|
|
|
|
// isErrTooManyConnections returns true if err is a postgres error
|
|
|
|
// with code 53300 (too_many_connections).
|
|
|
|
//
|
|
|
|
// See: https://www.postgresql.org/docs/14/errcodes-appendix.html
|
|
|
|
func isErrTooManyConnections(err error) bool {
|
|
|
|
return hasErrCode(err, errCodeTooManyConnections)
|
|
|
|
}
|
|
|
|
|
|
|
|
// isErrRelationNotExist returns true if err is a postgres error
|
|
|
|
// with code 42P01 (undefined_table).
|
|
|
|
//
|
|
|
|
// See: https://www.postgresql.org/docs/14/errcodes-appendix.html
|
|
|
|
func isErrRelationNotExist(err error) bool {
|
|
|
|
return hasErrCode(err, errCodeRelationNotExist)
|
|
|
|
}
|
|
|
|
|
|
|
|
// hasErrCode returns true if err (or its cause error)
|
|
|
|
// is of type *pgconn.PgError and err.Number equals code.
|
|
|
|
// See: isErrTooManyConnections.
|
|
|
|
func hasErrCode(err error, code string) bool {
|
|
|
|
if err == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
var pgErr *pgconn.PgError
|
|
|
|
|
|
|
|
if errors.As(err, &pgErr) {
|
|
|
|
return pgErr.Code == code
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|