package pgconn
import (
"context"
"errors"
"fmt"
"net"
"net/url"
"regexp"
"strings"
)
func SafeToRetry (err error ) bool {
if e , ok := err .(interface { SafeToRetry () bool }); ok {
return e .SafeToRetry ()
}
return false
}
func Timeout (err error ) bool {
var timeoutErr *errTimeout
return errors .As (err , &timeoutErr )
}
type PgError struct {
Severity string
Code string
Message string
Detail string
Hint string
Position int32
InternalPosition int32
InternalQuery string
Where string
SchemaName string
TableName string
ColumnName string
DataTypeName string
ConstraintName string
File string
Line int32
Routine string
}
func (pe *PgError ) Error () string {
return pe .Severity + ": " + pe .Message + " (SQLSTATE " + pe .Code + ")"
}
func (pe *PgError ) SQLState () string {
return pe .Code
}
type connectError struct {
config *Config
msg string
err error
}
func (e *connectError ) Error () string {
sb := &strings .Builder {}
fmt .Fprintf (sb , "failed to connect to `host=%s user=%s database=%s`: %s" , e .config .Host , e .config .User , e .config .Database , e .msg )
if e .err != nil {
fmt .Fprintf (sb , " (%s)" , e .err .Error())
}
return sb .String ()
}
func (e *connectError ) Unwrap () error {
return e .err
}
type connLockError struct {
status string
}
func (e *connLockError ) SafeToRetry () bool {
return true
}
func (e *connLockError ) Error () string {
return e .status
}
type parseConfigError struct {
connString string
msg string
err error
}
func (e *parseConfigError ) Error () string {
connString := redactPW (e .connString )
if e .err == nil {
return fmt .Sprintf ("cannot parse `%s`: %s" , connString , e .msg )
}
return fmt .Sprintf ("cannot parse `%s`: %s (%s)" , connString , e .msg , e .err .Error())
}
func (e *parseConfigError ) Unwrap () error {
return e .err
}
func normalizeTimeoutError(ctx context .Context , err error ) error {
if err , ok := err .(net .Error ); ok && err .Timeout () {
if ctx .Err () == context .Canceled {
return context .Canceled
} else if ctx .Err () == context .DeadlineExceeded {
return &errTimeout {err : ctx .Err ()}
} else {
return &errTimeout {err : err }
}
}
return err
}
type pgconnError struct {
msg string
err error
safeToRetry bool
}
func (e *pgconnError ) Error () string {
if e .msg == "" {
return e .err .Error()
}
if e .err == nil {
return e .msg
}
return fmt .Sprintf ("%s: %s" , e .msg , e .err .Error())
}
func (e *pgconnError ) SafeToRetry () bool {
return e .safeToRetry
}
func (e *pgconnError ) Unwrap () error {
return e .err
}
type errTimeout struct {
err error
}
func (e *errTimeout ) Error () string {
return fmt .Sprintf ("timeout: %s" , e .err .Error())
}
func (e *errTimeout ) SafeToRetry () bool {
return SafeToRetry (e .err )
}
func (e *errTimeout ) Unwrap () error {
return e .err
}
type contextAlreadyDoneError struct {
err error
}
func (e *contextAlreadyDoneError ) Error () string {
return fmt .Sprintf ("context already done: %s" , e .err .Error())
}
func (e *contextAlreadyDoneError ) SafeToRetry () bool {
return true
}
func (e *contextAlreadyDoneError ) Unwrap () error {
return e .err
}
func newContextAlreadyDoneError(ctx context .Context ) (err error ) {
return &errTimeout {&contextAlreadyDoneError {err : ctx .Err ()}}
}
func redactPW(connString string ) string {
if strings .HasPrefix (connString , "postgres://" ) || strings .HasPrefix (connString , "postgresql://" ) {
if u , err := url .Parse (connString ); err == nil {
return redactURL (u )
}
}
quotedDSN := regexp .MustCompile (`password='[^']*'` )
connString = quotedDSN .ReplaceAllLiteralString (connString , "password=xxxxx" )
plainDSN := regexp .MustCompile (`password=[^ ]*` )
connString = plainDSN .ReplaceAllLiteralString (connString , "password=xxxxx" )
brokenURL := regexp .MustCompile (`:[^:@]+?@` )
connString = brokenURL .ReplaceAllLiteralString (connString , ":xxxxxx@" )
return connString
}
func redactURL(u *url .URL ) string {
if u == nil {
return ""
}
if _ , pwSet := u .User .Password (); pwSet {
u .User = url .UserPassword (u .User .Username (), "xxxxx" )
}
return u .String ()
}
type NotPreferredError struct {
err error
safeToRetry bool
}
func (e *NotPreferredError ) Error () string {
return fmt .Sprintf ("standby server not found: %s" , e .err .Error())
}
func (e *NotPreferredError ) SafeToRetry () bool {
return e .safeToRetry
}
func (e *NotPreferredError ) Unwrap () error {
return e .err
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .