Documentation
¶
Overview ¶
Package sqlate is the session layer of the sqlate library, which every authored statement runs through. It wraps a plain *sql.DB behind the stdlib method set (ExecContext, QueryContext, PrepareContext), maps every driver error through the engine's dialect at that boundary, and owns the transaction runner. The package depends on the standard library alone; each engine lives in a sub-module (postgres) that supplies the dialect, so a consumer imports its engine once, where it opens its pool. The packages above it, query and migrate, take a Session and never a driver.
Wrapper ¶
Wrap builds the DB session over a pool with the engine's Dialect. Lifecycle (opening, readiness, closing) belongs to whoever owns the pool; DB adds error mapping, prepare, options on Begin, and pinned connections. It performs no I/O: a nil pool or dialect is a defect in the caller and panics. DB.Conn pins one connection for a protocol that needs session scope, such as a session-level lock or a run of non-transactional DDL; DB.Dialect returns the dialect statements are compiled against.
Sessions and transactions ¶
Session is the method set the query and migrate packages take, implemented by both DB and Tx, so the same statement runs against the pool or inside a transaction. The consumer owns the transaction boundary: DB.Begin opens a Tx with TxOption values applied, and DB.Transact runs one unit of work with a result: commit on success, rollback on the unit's error or panic. Tx.Commit routes its error through the dialect's MapError, the one place a violation deferred to COMMIT can be classified. ErrorMapper is the capability both sessions expose for errors that arise after a call returns, rows.Err and Scan, which the session cannot see.
Dialect ¶
Dialect is what the library needs from an engine: its name, how it renders the nth bind parameter, and how its driver's errors classify. An engine sub-module implements it. Capabilities beyond it are separate interfaces a protocol asserts: Locker, the named session-scoped lock a concurrent-starter protocol such as migration takes.
Errors ¶
The package owns the error taxonomy consumers match on. ErrConnectionFailed classifies a connectivity failure and ErrInvalidValue a data exception, each wrapped in the dual form fmt.Errorf("%w: %w", sentinel, err) so errors.Is classifies while the driver's error stays recoverable. The session classifies connectivity itself, before the dialect: a network error or driver.ErrBadConn from any call means the engine never saw the statement, so the dialect's vocabulary does not apply. A dialect's MapError returns the four constraint classes (ErrUniqueViolation, ErrForeignKeyViolation, ErrCheckViolation, ErrNotNullViolation) inside a ConstraintError, with the constraint name when the driver exposes it. sql.ErrNoRows is never mapped; MapError returns it unchanged.
Index ¶
- Variables
- type ConstraintError
- type DB
- func (d *DB) Begin(ctx context.Context, opts ...TxOption) (*Tx, error)
- func (d *DB) Conn(ctx context.Context) (*sql.Conn, error)
- func (d *DB) Dialect() Dialect
- func (d *DB) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
- func (d *DB) MapError(err error) error
- func (d *DB) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
- func (d *DB) QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
- func (d *DB) Transact[T any](ctx context.Context, fn func(*Tx) (T, error), opts ...TxOption) (T, error)
- type Dialect
- type ErrorMapper
- type Locker
- type Session
- type Tx
- func (t *Tx) Commit() error
- func (t *Tx) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
- func (t *Tx) MapError(err error) error
- func (t *Tx) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
- func (t *Tx) QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
- func (t *Tx) Rollback() error
- type TxOption
Constants ¶
This section is empty.
Variables ¶
var ( // ErrConnectionFailed classifies a failure to reach the engine: a // failure to obtain a connection or begin a transaction, and a network // error or driver.ErrBadConn raised by any session call. It is wrapped // as fmt.Errorf("%w: %w", ErrConnectionFailed, err) so errors.Is // matches it and the driver's error stays reachable. ErrConnectionFailed = errors.New("database connection failed") // ErrInvalidValue classifies a data exception: a bound value the engine // could not read as the type it was cast to (SQLSTATE class 22). It is // the engine-side half of request validation (a filter value that is // not a uuid, a date that is not a date), and a dialect maps its // engine's form to it, wrapped in the same dual form. ErrInvalidValue = errors.New("invalid value") // ErrUniqueViolation classifies a unique-constraint violation. A // dialect's MapError wraps it in a [ConstraintError]; errors.Is // matches the class. ErrUniqueViolation = errors.New("unique constraint violation") // ErrForeignKeyViolation classifies a foreign-key-constraint violation, // wrapped the same way as [ErrUniqueViolation]. ErrForeignKeyViolation = errors.New("foreign key constraint violation") // ErrCheckViolation classifies a check-constraint violation, wrapped // the same way as [ErrUniqueViolation]. ErrCheckViolation = errors.New("check constraint violation") // ErrNotNullViolation classifies a not-null-constraint violation, // wrapped the same way as [ErrUniqueViolation]. ErrNotNullViolation = errors.New("not-null constraint violation") // ErrDependentObjects classifies a refusal to drop an object another // object still depends on (SQLSTATE class 2BP01). A multi-set // migration's Down or Reset raises it when it reverts sets out of // order and a foreign key from a set above still references the set // being reverted. A dialect's MapError wraps it as // fmt.Errorf("%w: %w", ErrDependentObjects, err) so errors.Is matches // the class and the driver's error stays reachable. ErrDependentObjects = errors.New("dependent objects still exist") // ErrSerializationFailure classifies a serialization failure under // SERIALIZABLE isolation (SQLSTATE 40001). Two migrator starters // raise it when they race under the migration lock and the engine // offers no native advisory lock to serialize them. A dialect maps // its engine's form to it, wrapped in the same dual form as // [ErrDependentObjects]. ErrSerializationFailure = errors.New("serialization failure") )
Functions ¶
This section is empty.
Types ¶
type ConstraintError ¶
ConstraintError is a classified constraint violation: the class sentinel, the driver's own error, and the violated constraint's name, table, and column when the driver exposes them. A driver exposes them unevenly: a not-null violation names a column and no constraint, so Column is the only handle that case offers. Unwrap yields both wrapped errors, so errors.Is matches the class and errors.As finds the driver error, and a consumer maps the constraint name, or the column name when there is no constraint name, to its field.
func (*ConstraintError) Error ¶
func (e *ConstraintError) Error() string
func (*ConstraintError) Unwrap ¶
func (e *ConstraintError) Unwrap() []error
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB is the pool session over a plain *sql.DB. Lifecycle (opening, readiness, closing) belongs to whoever owns the pool; DB adds mapping, prepare, options on Begin, and pinned connections.
func Wrap ¶
Wrap builds the session over pool with dialect, the engine's or a capability-adding wrapper of it. Nil arguments are a defect in the caller and panic.
func (*DB) Begin ¶
Begin opens a transaction with the options applied; a failure to begin wraps ErrConnectionFailed.
func (*DB) Conn ¶
Conn pins one connection for a protocol that needs session scope: a session-level lock, a run of non-transactional DDL. The caller closes it.
func (*DB) ExecContext ¶
func (*DB) MapError ¶
MapError classifies a connectivity failure as ErrConnectionFailed and routes every other error through the dialect; nil stays nil.
func (*DB) PrepareContext ¶
func (*DB) QueryContext ¶
func (*DB) Transact ¶
func (d *DB) Transact[T any](ctx context.Context, fn func(*Tx) (T, error), opts ...TxOption) (T, error)
Transact runs fn as one unit of work with a result: begin with opts, fn, commit on success. On fn's error it rolls back and returns that error, with a rollback failure joined onto it. A panic in fn rolls back and re-panics, so no transaction leaks to the pool's reaper.
type Dialect ¶
type Dialect interface {
// Name identifies the engine.
Name() string
// Placeholder renders the 1-based nth bind parameter ("$1" for
// postgres, "@p1" for a future mssql).
Placeholder(n int) string
// MapError translates a driver error into the library's sentinels;
// it returns sql.ErrNoRows unchanged.
MapError(err error) error
}
Dialect is what the library needs from an engine: its name, how it renders the nth bind parameter, and how its driver's errors classify. An engine sub-module implements it; a provider library's dialect satisfies it structurally. Capabilities beyond it, Locker and ErrorMapper, are separate interfaces a protocol asserts.
type ErrorMapper ¶
ErrorMapper is the capability both sessions expose for errors that arise after a call returns, from rows.Err and Scan, which the session's methods cannot see. A runner type-asserts it on its Session.
type Locker ¶
type Locker interface {
Lock(ctx context.Context, conn *sql.Conn, name string) error
Unlock(ctx context.Context, conn *sql.Conn, name string) error
}
Locker is the dialect capability a concurrent-starter protocol takes: a session-scoped exclusive lock on a dedicated connection, identified by name. Locks are named, never numbered (<owner>.<structure>, such as migrate.schema_version or organization.tree), and the dialect maps the name to its engine's lock space. A provider without the capability cannot serialize migrations across processes.
type Session ¶
type Session interface {
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
}
Session is the stdlib method set a runner needs, implemented by *DB and *Tx, so the same statement handle runs against the pool or inside a transaction. Every method classifies a connectivity failure and maps every other driver error through the dialect; the dialect itself is not on the interface, because runners never need it at request time.
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Tx is one transaction, a Session whose errors are classified and mapped on every call and on commit.
func (*Tx) Commit ¶
Commit commits, mapping the error: the one place a violation deferred to COMMIT can be classified.
func (*Tx) ExecContext ¶
func (*Tx) MapError ¶
MapError classifies a connectivity failure as ErrConnectionFailed and routes every other error through the dialect; nil stays nil.
func (*Tx) PrepareContext ¶
func (*Tx) QueryContext ¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package header reads the declaration header of an authored SQL file: the leading run of blank lines, plain "--" comments (prose, skipped), and "--|" declaration lines of the form "--| key: value", ending at the first line that is none of those.
|
Package header reads the declaration header of an authored SQL file: the leading run of blank lines, plain "--" comments (prose, skipped), and "--|" declaration lines of the form "--| key: value", ending at the first line that is none of those. |
|
Package migrate is schema versioning over authored SQL: ordered sets of migrations, each migration SQL text plus a version, applied against a history table on one pinned connection under the dialect's lock capability.
|
Package migrate is schema versioning over authored SQL: ordered sets of migrations, each migration SQL text plus a version, applied against a history table on one pinned connection under the dialect's lock capability. |
|
postgres
module
|
|
|
Package query runs authored SQL files: Statements compiled from an fs.FS against a Catalog give a program its statements by name, each file's "--|" header declaring its tier, the engine feature a native file uses, whether it needs a transaction, and, for a projection base, its key and field contract.
|
Package query runs authored SQL files: Statements compiled from an fs.FS against a Catalog give a program its statements by name, each file's "--|" header declaring its tier, the engine feature a native file uses, whether it needs a transaction, and, for a projection base, its key and field contract. |
|
sqlint
module
|
|
|
Package sqltest is the scripted database/sql driver a consumer's hermetic tests run over: a connector whose connections consume scripted responses in call order and record every statement, prepare, and transaction call they receive.
|
Package sqltest is the scripted database/sql driver a consumer's hermetic tests run over: a connector whose connections consume scripted responses in call order and record every statement, prepare, and transaction call they receive. |