db

package
v1.0.10184-822ca07 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2024 License: MIT Imports: 15 Imported by: 4

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

Examples

Constants

This section is empty.

Variables

View Source
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 EscapeLike(s string) string

func New

func New(ctx context.Context, dbName, appName string, options Config) (db *sqlx.DB, err error)

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

func PqError(err error) *pgconn.PgError
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).ConstraintName == "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).ConstraintName == "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().ConstraintName == "my_fk" {
		// do some special constraint violation handling
	}

}
Output:

not the error you are looking for

func Span

func Span(ctx context.Context, entity, queryName string) (context.Context, o11y.Span)

Types

type Config

type Config struct {
	Host string
	Port int
	User string
	Pass secret.String
	Name string
	SSL  bool

	// If these are unset, then defaults will be chosen
	ConnMaxLifetime time.Duration
	MaxOpenConns    int
	MaxIdleConns    int
}

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

func (e *Error) Error() string

Error returns the standard sentinel error format and then the underlying pq.Error if one exists

func (*Error) Is

func (e *Error) Is(target error) bool

Is checks that this error is being checked for the special o11y error that is not added to the trace as an error. If the error is due to relatively expected failure response codes return true so it does not appear in the traces as an error.

func (Error) PqError

func (e Error) PqError() *pgconn.PgError

PqError will return any wrapped pqError is e has one

type HealthCheck

type HealthCheck struct {
	Name string
	DB   *sqlx.DB
}

func (*HealthCheck) Gauges

func (h *HealthCheck) Gauges(_ context.Context) map[string]float64

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 db.ErrNop.
	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.
	// In the case of no result the error returned will be db.ErrNop.
	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 Load

func Load(ctx context.Context, dbName, appName string, cfg Config, sys *system.System) (*TxManager, error)

func NewTxManager

func NewTxManager(db *sqlx.DB) *TxManager

func NewTxManagerWithTestQuerier

func NewTxManagerWithTestQuerier(db *sqlx.DB, tq func(Querier) Querier) *TxManager

func (*TxManager) NoTx

func (t *TxManager) NoTx() Querier

func (*TxManager) WithTransaction

func (t *TxManager) WithTransaction(ctx context.Context, f queryFn) (err error)

WithTransaction simply delegates to WithTx. Deprecated

func (*TxManager) WithTx

func (t *TxManager) WithTx(ctx context.Context, f queryFn) (err error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL