func IsDuplicate(err error) bool
IsDuplicate is a utility function for determining if an error wrap MySQL's Error 1062: Duplicate entry. This error is returned when inserting a row would violate a unique key constraint.
func IsNoRows(err error) bool
IsNoRows is a utility function for determining if an error wraps the go sql package's ErrNoRows, which is returned when a Scan operation has no more results to return, and as such is returned by many borp methods.
func QuestionMarks(n int) string
QuestionMarks returns a string consisting of N question marks, joined by commas. If n is <= 0, panics.
func WithTransaction(ctx context.Context, dbMap DatabaseMap, f txFunc) (interface{}, error)
WithTransaction runs the given function in a transaction, rolling back if it returns an error and committing if not. The provided context is also attached to the transaction. WithTransaction also passes through a value returned by `f`, if there is no error.
DatabaseMap offers the full combination of OneSelector, Inserter, SelectExecer, and a Begin function for creating a Transaction.
type DatabaseMap interface { OneSelector Inserter SelectExecer BeginTx(context.Context) (Transaction, error) }
ErrDatabaseOp wraps an underlying err with a description of the operation that was being performed when the error occurred (insert, select, select one, exec, etc) and the table that the operation was being performed on.
type ErrDatabaseOp struct { Op string Table string Err error }
func (e ErrDatabaseOp) Error() string
Error for an ErrDatabaseOp composes a message with context about the operation and table as well as the underlying Err's error message.
func (e ErrDatabaseOp) Unwrap() error
Unwrap returns the inner error to allow inspection of error chains.
A Execer is anything that provides an `ExecContext` function
type Execer interface { ExecContext(context.Context, string, ...interface{}) (sql.Result, error) }
Executor offers the full combination of OneSelector, Inserter, SelectExecer and adds a handful of other high level borp methods we use in Boulder.
type Executor interface { OneSelector Inserter SelectExecer Queryer Delete(context.Context, ...interface{}) (int64, error) Get(context.Context, interface{}, ...interface{}) (interface{}, error) Update(context.Context, ...interface{}) (int64, error) }
A Inserter is anything that provides an `Insert` function
type Inserter interface { Insert(context.Context, ...interface{}) error }
MappedExecutor is anything that can map types to tables
type MappedExecutor interface { TableFor(reflect.Type, bool) (*borp.TableMap, error) QueryContext(ctx context.Context, clauses string, args ...interface{}) (*sql.Rows, error) }
MappedSelector is anything that can execute various kinds of SQL statements against a table automatically determined from the parameterized type.
type MappedSelector[T any] interface { QueryContext(ctx context.Context, clauses string, args ...interface{}) (Rows[T], error) QueryFrom(ctx context.Context, tablename string, clauses string, args ...interface{}) (Rows[T], error) }
func NewMappedSelector[T any](executor MappedExecutor) (MappedSelector[T], error)
NewMappedSelector returns an object which can be used to automagically query the provided type-mapped database for rows of the parameterized type.
MockSqlExecutor implement SqlExecutor by returning errors from every call.
TODO: To mock out WithContext, we needed to be able to return objects that satisfy borp.SqlExecutor. That's a pretty big interface, so we specify one no-op mock that we can embed everywhere we need to satisfy it. Note: MockSqlExecutor does *not* implement WithContext. The expectation is that structs that embed MockSqlExecutor will define their own WithContext that returns a reference to themselves. That makes it easy for those structs to override the specific methods they need to implement (e.g. SelectOne).
type MockSqlExecutor struct{}
func (mse MockSqlExecutor) Delete(ctx context.Context, list ...interface{}) (int64, error)
func (mse MockSqlExecutor) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
func (mse MockSqlExecutor) Get(ctx context.Context, i interface{}, keys ...interface{}) (interface{}, error)
func (mse MockSqlExecutor) Insert(ctx context.Context, list ...interface{}) error
func (mse MockSqlExecutor) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
func (mse MockSqlExecutor) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
func (mse MockSqlExecutor) Select(ctx context.Context, i interface{}, query string, args ...interface{}) ([]interface{}, error)
func (mse MockSqlExecutor) SelectFloat(ctx context.Context, query string, args ...interface{}) (float64, error)
func (mse MockSqlExecutor) SelectInt(ctx context.Context, query string, args ...interface{}) (int64, error)
func (mse MockSqlExecutor) SelectNullFloat(ctx context.Context, query string, args ...interface{}) (sql.NullFloat64, error)
func (mse MockSqlExecutor) SelectNullInt(ctx context.Context, query string, args ...interface{}) (sql.NullInt64, error)
func (mse MockSqlExecutor) SelectNullStr(ctx context.Context, query string, args ...interface{}) (sql.NullString, error)
func (mse MockSqlExecutor) SelectOne(ctx context.Context, holder interface{}, query string, args ...interface{}) error
func (mse MockSqlExecutor) SelectStr(ctx context.Context, query string, args ...interface{}) (string, error)
func (mse MockSqlExecutor) Update(ctx context.Context, list ...interface{}) (int64, error)
MultiInserter makes it easy to construct a `INSERT INTO table (...) VALUES ... RETURNING id;` query which inserts multiple rows into the same table. It can also execute the resulting query.
type MultiInserter struct {
// contains filtered or unexported fields
}
func NewMultiInserter(table string, fields []string, returningColumn string) (*MultiInserter, error)
NewMultiInserter creates a new MultiInserter, checking for reasonable table name and list of fields. returningColumn is the name of a column to be used in a `RETURNING xyz` clause at the end. If it is empty, no `RETURNING xyz` clause is used. If returningColumn is present, it must refer to a column that can be parsed into an int64. Safety: `table`, `fields`, and `returningColumn` must contain only strings that are known at compile time. They must not contain user-controlled strings.
func (mi *MultiInserter) Add(row []interface{}) error
Add registers another row to be included in the Insert query.
func (mi *MultiInserter) Insert(ctx context.Context, queryer Queryer) ([]int64, error)
Insert inserts all the collected rows into the database represented by `queryer`. If a non-empty returningColumn was provided, then it returns the list of values from that column returned by the query.
A OneSelector is anything that provides a `SelectOne` function.
type OneSelector interface { SelectOne(context.Context, interface{}, string, ...interface{}) error }
Queryer offers the QueryContext method. Note that this is not read-only (i.e. not Selector), since a QueryContext can be `INSERT`, `UPDATE`, etc. The difference between QueryContext and ExecContext is that QueryContext can return rows. So for instance it is suitable for inserting rows and getting back ids.
type Queryer interface { QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) }
RollbackError is a combination of a database error and the error, if any, encountered while trying to rollback the transaction.
type RollbackError struct { Err error RollbackErr error }
func (re *RollbackError) Error() string
Error implements the error interface
Rows is anything which lets you iterate over the result rows of a SELECT query. It is similar to sql.Rows, but generic.
type Rows[T any] interface { Next() bool Get() (*T, error) Err() error Close() error }
SelectExecer offers a subset of borp.SqlExecutor's methods: Select and ExecContext.
type SelectExecer interface { Selector Execer }
A Selector is anything that provides a `Select` function.
type Selector interface { Select(context.Context, interface{}, string, ...interface{}) ([]interface{}, error) }
Transaction extends an Executor and adds Rollback and Commit
type Transaction interface { Executor Rollback() error Commit() error }
WrappedExecutor wraps a borp.SqlExecutor such that its major functions wrap error results in ErrDatabaseOp instances before returning them to the caller.
type WrappedExecutor struct {
// contains filtered or unexported fields
}
func (we WrappedExecutor) Delete(ctx context.Context, list ...interface{}) (int64, error)
func (we WrappedExecutor) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
func (we WrappedExecutor) Get(ctx context.Context, holder interface{}, keys ...interface{}) (interface{}, error)
func (we WrappedExecutor) Insert(ctx context.Context, list ...interface{}) error
func (we WrappedExecutor) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
func (we WrappedExecutor) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
func (we WrappedExecutor) Select(ctx context.Context, holder interface{}, query string, args ...interface{}) ([]interface{}, error)
func (we WrappedExecutor) SelectNullInt(ctx context.Context, query string, args ...interface{}) (sql.NullInt64, error)
func (we WrappedExecutor) SelectOne(ctx context.Context, holder interface{}, query string, args ...interface{}) error
func (we WrappedExecutor) SelectStr(ctx context.Context, query string, args ...interface{}) (string, error)
func (we WrappedExecutor) Update(ctx context.Context, list ...interface{}) (int64, error)
WrappedMap wraps a *borp.DbMap such that its major functions wrap error results in ErrDatabaseOp instances before returning them to the caller.
type WrappedMap struct {
// contains filtered or unexported fields
}
func NewWrappedMap(dbMap *borp.DbMap) *WrappedMap
func (m *WrappedMap) BeginTx(ctx context.Context) (Transaction, error)
func (m *WrappedMap) Delete(ctx context.Context, list ...interface{}) (int64, error)
func (m *WrappedMap) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
func (m *WrappedMap) Get(ctx context.Context, holder interface{}, keys ...interface{}) (interface{}, error)
func (m *WrappedMap) Insert(ctx context.Context, list ...interface{}) error
func (m *WrappedMap) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
func (m *WrappedMap) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
func (m *WrappedMap) Select(ctx context.Context, holder interface{}, query string, args ...interface{}) ([]interface{}, error)
func (m *WrappedMap) SelectNullInt(ctx context.Context, query string, args ...interface{}) (sql.NullInt64, error)
func (m *WrappedMap) SelectOne(ctx context.Context, holder interface{}, query string, args ...interface{}) error
func (m *WrappedMap) SelectStr(ctx context.Context, query string, args ...interface{}) (string, error)
func (m *WrappedMap) TableFor(t reflect.Type, checkPK bool) (*borp.TableMap, error)
func (m *WrappedMap) Update(ctx context.Context, list ...interface{}) (int64, error)
WrappedTransaction wraps a *borp.Transaction such that its major functions wrap error results in ErrDatabaseOp instances before returning them to the caller.
type WrappedTransaction struct {
// contains filtered or unexported fields
}
func (tx WrappedTransaction) Commit() error
func (tx WrappedTransaction) Delete(ctx context.Context, list ...interface{}) (int64, error)
func (tx WrappedTransaction) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
func (tx WrappedTransaction) Get(ctx context.Context, holder interface{}, keys ...interface{}) (interface{}, error)
func (tx WrappedTransaction) Insert(ctx context.Context, list ...interface{}) error
func (tx WrappedTransaction) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
func (tx WrappedTransaction) Rollback() error
func (tx WrappedTransaction) Select(ctx context.Context, holder interface{}, query string, args ...interface{}) ([]interface{}, error)
func (tx WrappedTransaction) SelectOne(ctx context.Context, holder interface{}, query string, args ...interface{}) error
func (tx WrappedTransaction) Update(ctx context.Context, list ...interface{}) (int64, error)