Documentation ¶
Overview ¶
Package db contains a variety of tools for working safely with databases.
There are tools for: - transactions (including rollbacks on error or panic) - observability (both for queries and connection info) - health checks
Index ¶
- Variables
- func EscapeLike(s string) string
- func New(ctx context.Context, dbName, appName string, options Config) (db *sqlx.DB, err error)
- func PqError(err error) *pq.Error
- func Span(ctx context.Context, entity, queryName string) (context.Context, o11y.Span)
- type Config
- type Error
- type HealthCheck
- type Querier
- type TxManager
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrNop = o11y.NewWarning("no update or results") ErrConstrained = errors.New("violates constraints") ErrException = errors.New("exception") ErrCanceled = o11y.NewWarning("statement canceled") ErrBadConn = o11y.NewWarning("bad connection") )
Functions ¶
func EscapeLike ¶
func New ¶
New connects to a database. The context passed in is expected to carry an o11y provider and is only used for reporting (not for cancellation),
func PqError ¶
Example ¶
package main import ( "errors" "fmt" "github.com/circleci/ex/db" ) func main() { err := errors.New("im not the right error") // An example of how to extract the constraint that failed if errors.Is(err, db.ErrConstrained) && db.PqError(err).Constraint == "my_fk" { fmt.Println("do your constraint behaviour") } else { fmt.Println("not the error you are looking for") } // Alternatively you may want to go direct if db.PqError(err) != nil && db.PqError(err).Constraint == "my_fk" { // you may need to map the code here - which would be bad. // but you could check the db error mapping here ... if errors.Is(err, db.ErrConstrained) { fmt.Println("do your constraint behaviour") } } // Or with As and the PqError method e := &db.Error{} if errors.As(err, &e) && e.PqError() != nil && e.PqError().Constraint == "my_fk" { // do some special constraint violation handling } }
Output: not the error you are looking for
Types ¶
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error wraps a pq.Error to make it available to the caller. The sentinel is included for easier testing of the existing error vars. for example errors.Is(err, ErrConstrained)
func (*Error) Error ¶
Error returns the standard sentinel error format and then the underlying pq.Error if one exists
type HealthCheck ¶
func (*HealthCheck) HealthChecks ¶
func (h *HealthCheck) HealthChecks() (name string, ready, live func(ctx context.Context) error)
func (*HealthCheck) MetricName ¶
func (h *HealthCheck) MetricName() string
type Querier ¶
type Querier interface { // ExecContext executes the query with placeholder parameters that match the args. // Use this if the query does not use named parameters (for that use NamedExecContext), // and you do not care about the data the query generates. ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) // GetContext expects placeholder parameters in the query and will bind args to them. // A single row result will be mapped to dest which must be a pointer to a struct. // In the case of no result the error returned will be sql.ErrNoRows. GetContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error // NamedGetContext expect a query with named parameters, fields from the arg struct will be mapped // to the named parameters. A single row result will be mapped to dest which must be a pointer to a struct. NamedGetContext(ctx context.Context, dest interface{}, query string, arg interface{}) error // NamedExecContext expect a query with named parameters, fields from the arg struct will be mapped // to the named parameters. Use this if you do not care about the data the query generates, and // you don't want to use placeholder parameters (see ExecContext) NamedExecContext(ctx context.Context, query string, arg interface{}) (sql.Result, error) // SelectContext expects placeholder parameters in the query and will bind args to them. // Each resultant row will be scanned into dest, which must be a slice. // (If you expect (or want) a single row in the response use GetContext instead.) // This method never returns sql.ErrNoRows, instead the dest slice will be empty. SelectContext(ctx context.Context, dest interface{}, query string, args ...interface{}) error }
Querier can either be a *sqlx.DB or *sqlx.Tx
type TxManager ¶
type TxManager struct {
// contains filtered or unexported fields
}
func NewTxManager ¶
func (*TxManager) WithTransaction ¶
WithTransaction simply delegates to WithTx. Deprecated
func (*TxManager) WithTx ¶
WithTx wraps f in an explicit o11y'd transaction, handling rollback if f returns an error. It will retry the transaction a few times in the face of ErrBadConn errors. The length here is due to the internalised func, which we want to encapsulate to avoid reuse, since it is highly coupled to the retry behaviour.