Documentation
¶
Overview ¶
Package database owns execution and transaction contracts shared by Foundry's generated query APIs and infrastructure adapters. SQL strings and scan targets are explicit raw boundaries; model-specific compile-time guarantees belong to generated APIs rather than arbitrary SQL.
Index ¶
- Constants
- func FieldEncryption(row Row) (context.Context, *encryption.Keyring, error)
- func ForEach[T any](ctx context.Context, executor Executor, statement string, arguments []any, ...) (err error)
- func FoundryObservers(writer any, seal sqlowner.ObserverSeal) (lifecycle.Observers, bool)
- func FoundryStatementUnknown(seal sqlowner.OutcomeSeal, operation string, cause error) error
- func Module(name foundation.ProviderID, key foundation.Key[*DB], ...) foundation.Module
- func NewError(operation string, code Code) error
- func RegisterObserver[M, H any](r *foundation.Registrar, pool foundation.Key[*DB], ...) error
- func Retry(ctx context.Context, transactor Transactor, policy RetryPolicy, ...) error
- func ScanOne(ctx context.Context, executor Executor, statement string, arguments []any, ...) (err error)
- func StickyReads(ctx context.Context) context.Context
- func StickyReadsHandler(next http.Handler) http.Handler
- type Adapter
- type Code
- type Connection
- type ConnectionName
- type Connections
- type DB
- func (db *DB) BindObservers(set lifecycle.Observers) error
- func (db *DB) Clock() clock.Clock
- func (db *DB) Close(ctx context.Context) error
- func (db *DB) Done() <-chan struct{}
- func (db *DB) Encryption() *encryption.Keyring
- func (db *DB) Exec(ctx context.Context, statement string, arguments ...any) (result Result, err error)
- func (db *DB) FoundryAutocommitQuery(seal sqlowner.AutocommitSeal, ctx context.Context, statement string, ...) (*Rows, error)
- func (db *DB) FoundryObservers(seal sqlowner.ObserverSeal) (set lifecycle.Observers, known bool)
- func (db *DB) HasReadPool() bool
- func (db *DB) Health(ctx context.Context) []PoolHealth
- func (db *DB) Observers() lifecycle.Observers
- func (db *DB) Ping(ctx context.Context) (err error)
- func (db *DB) PingPrimary(ctx context.Context) error
- func (db *DB) PingRead(ctx context.Context) error
- func (db *DB) Primary() PrimaryExecutor
- func (db *DB) Query(ctx context.Context, statement string, arguments ...any) (*Rows, error)
- func (db *DB) QueryRead(ctx context.Context, statement string, arguments ...any) (*Rows, error)
- func (db *DB) ReadinessProbes(primary, read health.ProbeID) []health.Probe
- func (db *DB) RoutingStats() RoutingStats
- func (db *DB) Session(ctx context.Context, fn func(*Session) error) (err error)
- func (db *DB) Start(ctx context.Context) error
- func (db *DB) Stats() Stats
- func (db *DB) Transaction(ctx context.Context, fn func(*Tx) error, options ...TxOptions) (err error)
- type Detail
- type EncryptedRow
- type Error
- func (e *Error) Code() Code
- func (e *Error) Constraint() string
- func (e *Error) Error() string
- func (e *Error) FoundryDiagnostic(seal errordiag.Seal) []fault.Attribute
- func (e *Error) GoString() string
- func (e *Error) Is(target error) bool
- func (e *Error) Outcome() Outcome
- func (e *Error) SQLState() string
- func (e *Error) Schema() string
- func (e *Error) Table() string
- func (e *Error) Unwrap() error
- type Executor
- type Isolation
- type JSONKind
- type Option
- func WithClock(source clock.Clock) Option
- func WithConnectionLimit(maxConnections int) Option
- func WithEncryption(keys *encryption.Keyring) Option
- func WithQueryObserver(observer QueryObserver) Option
- func WithReadPool(adapter func() (Adapter, error), config PoolConfig, maxConnections int) Option
- func WithSlowQueryLog(logger *slog.Logger, threshold time.Duration) Option
- func WithSlowQueryThreshold(threshold time.Duration) Option
- func WithStartupLog(logger *slog.Logger) Option
- func WithStatementDetector(d *StatementDetector) Option
- func WithStickyReads(window time.Duration) Option
- type Outcome
- type PoolConfig
- type PoolHealth
- type PoolRole
- type PoolStats
- type PrimaryExecutor
- func (p PrimaryExecutor) Clock() clock.Clock
- func (p PrimaryExecutor) Exec(ctx context.Context, statement string, arguments ...any) (Result, error)
- func (p PrimaryExecutor) FoundryAutocommitQuery(seal sqlowner.AutocommitSeal, ctx context.Context, statement string, ...) (*Rows, error)
- func (p PrimaryExecutor) FoundryObservers(seal sqlowner.ObserverSeal) (lifecycle.Observers, bool)
- func (p PrimaryExecutor) Query(ctx context.Context, statement string, arguments ...any) (*Rows, error)
- func (p PrimaryExecutor) Transaction(ctx context.Context, fn func(*Tx) error, options ...TxOptions) error
- type QueryEvent
- type QueryObserver
- type ReadRouter
- type Result
- type RetryPolicy
- type RoutingStats
- type Row
- type Rows
- func (r *Rows) Close() error
- func (r *Rows) Columns() ([]string, error)
- func (r *Rows) Err() error
- func (r *Rows) FieldEncryption() (context.Context, *encryption.Keyring)
- func (r *Rows) FoundryCollect(seal sqlowner.CollectionSeal, ctx context.Context, scan func(Row) error) (count int, err error)
- func (r *Rows) Next() bool
- func (r *Rows) Observers() lifecycle.Observers
- func (r *Rows) Scan(destinations ...any) error
- func (r *Rows) WithObserverScope(ctx context.Context, fn func(context.Context) error) (err error)
- type Session
- func (s *Session) Clock() clock.Clock
- func (s *Session) Discard()
- func (s *Session) Encryption() *encryption.Keyring
- func (s *Session) Exec(ctx context.Context, statement string, arguments ...any) (Result, error)
- func (s *Session) FoundryObservers(seal sqlowner.ObserverSeal) (lifecycle.Observers, bool)
- func (s *Session) Observers() lifecycle.Observers
- func (s *Session) Query(ctx context.Context, statement string, arguments ...any) (*Rows, error)
- func (s *Session) Transaction(ctx context.Context, fn func(*Tx) error, options ...TxOptions) error
- type StatementDetector
- type StatementDetectorConfig
- type StatementReport
- type StatementScope
- type StatementViolation
- type Stats
- type Transactor
- type Tx
- func (tx *Tx) AfterCommit(fn func(context.Context) error) error
- func (tx *Tx) BelongsTo(db *DB) bool
- func (tx *Tx) Clock() clock.Clock
- func (tx *Tx) Encryption() *encryption.Keyring
- func (tx *Tx) Exec(ctx context.Context, statement string, arguments ...any) (result Result, err error)
- func (tx *Tx) FoundryObservers(seal sqlowner.ObserverSeal) (lifecycle.Observers, bool)
- func (tx *Tx) Observers() lifecycle.Observers
- func (tx *Tx) Query(ctx context.Context, statement string, arguments ...any) (*Rows, error)
- func (tx *Tx) Savepoint(ctx context.Context, fn func(*Tx) error) error
- func (tx *Tx) SharesTransaction(other *Tx) bool
- func (tx *Tx) State() TxState
- func (tx *Tx) Transaction(ctx context.Context, fn func(*Tx) error, options ...TxOptions) error
- type TxOptions
- type TxState
Constants ¶
const MaxRetryAttempts = 10
MaxRetryAttempts bounds one Retry call.
Variables ¶
This section is empty.
Functions ¶
func FieldEncryption ¶
FieldEncryption returns the decryption scope of row. A row without one, or from a pool without a key ring, fails closed: the caller must not hydrate an encrypted field it cannot decrypt.
func ForEach ¶
func ForEach[T any](ctx context.Context, executor Executor, statement string, arguments []any, scan func(Row) (T, error), yield func(T) error) (err error)
ForEach hydrates and yields one value at a time, closing rows on early return, error or panic. It retains no collection; callbacks decide what to retain.
func FoundryObservers ¶
FoundryObservers returns the frozen observer snapshot of a concrete framework owner. Unknown wrappers cannot prove observer absence. The capability is validated here and is never passed to an application-implementable interface. Example (framework only): FoundryObservers(db, sqlowner.Observers()).
func FoundryStatementUnknown ¶
func FoundryStatementUnknown(seal sqlowner.OutcomeSeal, operation string, cause error) error
FoundryStatementUnknown labels a failure observed after a framework autocommit statement was sent, such as a result that could not be decoded: the statement's implicit transaction may already have committed.
func Module ¶
func Module(name foundation.ProviderID, key foundation.Key[*DB], adapter func() (Adapter, error), config PoolConfig, options ...Option) foundation.Module
Module registers a typed, prepared pool and starts it during application boot. The adapter factory is pure construction: it must not acquire resources or start goroutines. A fresh pool is constructed for each application using this declaration. Feature adapters may wrap this helper with their own configuration.
func NewError ¶
NewError constructs a classified framework failure without a driver cause. Typed query layers use it for results such as a required row that is absent, so every database outcome is inspected through the same *Error contract.
func RegisterObserver ¶
func RegisterObserver[M, H any](r *foundation.Registrar, pool foundation.Key[*DB], observer lifecycle.Observer[M, H], construct func(foundation.Resolver) (func() H, error)) error
RegisterObserver contributes a model-owned observer to a database Module. This shared registration boundary retains the model/hook pair. Dependencies are resolved once during application construction; the resulting factory is retained for per-operation hook construction. Neither stage acquires a pool connection. Names are unique within the selected database, across models.
func Retry ¶
func Retry(ctx context.Context, transactor Transactor, policy RetryPolicy, fn func(*Tx) error, options ...TxOptions) error
Retry runs fn in a transaction of transactor and runs the whole transaction again only when the previous attempt was a confirmed rollback caused by a serialization failure or deadlock. Every other failure is returned at once: an unknown commit outcome is never retried, because the attempt may have committed. The callback must therefore be safe to run more than once; process-local effects belong in Tx.AfterCommit, which runs only after the attempt that commits. A nested *Tx is rejected: its savepoint cannot recover a serialization failure of the enclosing transaction. The last failure is returned when attempts are exhausted or ctx ends while waiting.
func ScanOne ¶
func ScanOne(ctx context.Context, executor Executor, statement string, arguments []any, destinations ...any) (err error)
ScanOne requires exactly one row and always closes the stream. A zero-row result is NotFound, not a generic query failure. Multiple rows are TooManyRows. Arguments and destinations are explicit runtime-checked SQL boundaries.
func StickyReads ¶
StickyReads returns a context that tracks writes for read-your-writes routing. Use one per request (see StickyReadsHandler); a context that already carries a scope is returned unchanged, so nested calls share it.
Types ¶
type Adapter ¶
Adapter supplies an explicitly constructed standard Go connector and error classification. Applications normally use a feature adapter such as postgres. Connector methods must honor their contexts and database/sql's driver contract, including error methods invoked inside database/sql. Drivers must not panic or call runtime.Goexit. Classify must be safe to share; Foundry owns its invocation. Its input may be safely wrapped; errors.Is/As retain the original driver cause.
type Code ¶
type Code string
Code classifies a database failure without matching driver error messages. Use errors.Is(err, database.UniqueViolation), for example.
const ( QueryFailed Code = "query_failed" NotFound Code = "not_found" TooManyRows Code = "too_many_rows" Canceled Code = "canceled" DeadlineExceeded Code = "deadline_exceeded" Closed Code = "closed" NotReady Code = "not_ready" Busy Code = "busy" UniqueViolation Code = "unique_violation" ForeignKeyViolation Code = "foreign_key_violation" CheckViolation Code = "check_violation" NotNullViolation Code = "not_null_violation" SerializationFailure Code = "serialization_failure" Deadlock Code = "deadlock" CommitUnknown Code = "commit_unknown" AfterCommitFailed Code = "after_commit_failed" // QueryCanceled is a server-side cancellation, such as statement_timeout or // an administrator request. Caller context cancellation remains Canceled. QueryCanceled Code = "query_canceled" // LockNotAvailable reports NOWAIT or lock_timeout expiry. The statement did // not acquire its lock; retry policy belongs to the caller. LockNotAvailable Code = "lock_not_available" ExclusionViolation Code = "exclusion_violation" RestrictViolation Code = "restrict_violation" ReadOnlyTransaction Code = "read_only_sql_transaction" StringDataRightTruncation Code = "string_data_right_truncation" InvalidTextRepresentation Code = "invalid_text_representation" NumericValueOutOfRange Code = "numeric_value_out_of_range" InvalidDatetimeFormat Code = "invalid_datetime_format" DatetimeFieldOverflow Code = "datetime_field_overflow" DivisionByZero Code = "division_by_zero" // DataException covers other invalid values rejected by the server. DataException Code = "data_exception" ObjectInUse Code = "object_in_use" // InsufficientResources covers server disk, memory and configured limits. // Connection-slot exhaustion remains Unavailable. InsufficientResources Code = "insufficient_resources" IdleInTransactionTimeout Code = "idle_in_transaction_timeout" )
type Connection ¶
type Connection struct {
Name ConnectionName
Value *DB
}
Connection binds a typed name to an existing borrowed instance.
type ConnectionName ¶
type ConnectionName string
ConnectionName identifies one configured database instance, distinct from other service families.
func (ConnectionName) Validate ¶
func (n ConnectionName) Validate() error
Validate returns fault.Invalid unless the connection name is a semantic identifier.
type Connections ¶
type Connections struct {
// contains filtered or unexported fields
}
Connections is immutable. Default and named access alias the same owned instance. Resolve dependencies during construction; pass concrete services to domain code.
func NewConnections ¶
func NewConnections(selected ConnectionName, entries ...Connection) (*Connections, error)
NewConnections validates and snapshots named borrowed connections with an explicit default. It creates no additional database resources.
func (*Connections) Connection ¶
func (r *Connections) Connection(name ConnectionName) (*DB, error)
Connection returns the borrowed database registered under name. An unknown name returns fault.Missing rather than selecting the default.
func (*Connections) Default ¶
func (r *Connections) Default() (*DB, error)
Default returns the borrowed database selected at construction.
func (*Connections) DefaultName ¶
func (r *Connections) DefaultName() ConnectionName
DefaultName returns the selected name, or an empty name for a nil receiver.
func (*Connections) Names ¶
func (r *Connections) Names() []ConnectionName
Names returns an owned, sorted list of registered names, or nil for a nil receiver.
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB is a concurrency-safe, application-owned connection pool. Close rejects new work and drains active resource owners. Rows and transactions must be closed.
func Open ¶
Open constructs a pool and verifies connectivity before returning it. The adapter is an infrastructure boundary; credentials are supplied by its caller. Failure closes the newly owned pool. No schemas or migrations are applied.
func Prepare ¶
func Prepare(adapter Adapter, config PoolConfig, options ...Option) (*DB, error)
Prepare validates a pool without opening connections or starting goroutines. Start must succeed before operations can acquire connections. This supports pure provider registration and constructor injection before lifecycle boot.
func (*DB) BindObservers ¶
BindObservers attaches an immutable set to a directly prepared pool exactly once, before Start. Database Modules bind provider contributions automatically during Build instead. Binding never starts resources or invokes hook factories.
func (*DB) Clock ¶
Clock returns the pool's application time source. A prepared Module inherits its application source during boot; after Start it never replaces that source. Reading the clock does not acquire a connection or extend resource ownership.
func (*DB) Close ¶
Close rejects new work immediately, then waits for resources to drain. It is safe to repeat concurrently. A canceled caller stops waiting; cleanup remains active. Existing work keeps its own context and is not force-terminated.
func (*DB) Done ¶
func (db *DB) Done() <-chan struct{}
Done closes only when all resource owners have released and the pool has actually closed. A Close deadline does not imply this channel has closed.
func (*DB) Encryption ¶
func (db *DB) Encryption() *encryption.Keyring
Encryption returns the pool's encrypted-field key ring, or nil when none is configured. It never acquires a connection.
func (*DB) Exec ¶
func (db *DB) Exec(ctx context.Context, statement string, arguments ...any) (result Result, err error)
Exec executes a parameterized statement and releases its connection on return.
func (*DB) FoundryAutocommitQuery ¶
func (db *DB) FoundryAutocommitQuery(seal sqlowner.AutocommitSeal, ctx context.Context, statement string, arguments ...any) (*Rows, error)
FoundryAutocommitQuery runs one framework-compiled write statement outside an explicit transaction. Every returned failure carries the statement outcome: NoCommit before the statement was performed, RolledBack when the adapter confirms server rejection, and otherwise Unknown with CommitUnknown. Only a complete iteration whose Err and Close both succeed confirms the commit.
func (*DB) FoundryObservers ¶
FoundryObservers is the sealed owner capability used by typed queries to prove observer absence without I/O or pool locks. known is false while a prepared pool can still bind observers; callers must then use the Tx they receive.
func (*DB) HasReadPool ¶
HasReadPool reports configuration, not current endpoint health.
func (*DB) Health ¶
func (db *DB) Health(ctx context.Context) []PoolHealth
Health checks primary and each configured read endpoint, retaining their identities and errors.
func (*DB) Observers ¶
Observers returns this database's immutable observer set. A directly prepared pool may bind it before Start; running pools retain the same set for life.
func (*DB) Ping ¶
Ping checks every configured endpoint using the caller's context. Dependency failure affects readiness; it is not a process liveness failure.
func (*DB) PingPrimary ¶
PingPrimary checks the primary endpoint through its dedicated probe connection, so a saturated application pool cannot make readiness fail.
func (*DB) Primary ¶
func (db *DB) Primary() PrimaryExecutor
Primary returns an executor borrowing this database and pinning work to its primary endpoint.
func (*DB) Query ¶
Query returns a stream owning its connection until Close, complete iteration or the end of ctx. Always defer Close, and check Err after iteration. Do not share Rows between goroutines. Scan errors close the stream to release the connection promptly; cancellation closes a forgotten stream as a safety net.
A primary query may write (for example INSERT ... RETURNING), so with WithStickyReads it marks the request scope when it starts and when its stream closes.
func (*DB) QueryRead ¶
QueryRead uses the configured read pool, or primary when none is configured. SQL must be safe to execute on that endpoint. Replica lag means a recent primary commit is not necessarily visible; use Primary or the owning Tx.
func (*DB) ReadinessProbes ¶
ReadinessProbes contributes separate configured endpoint checks to the shared health registry. IDs belong to the application's declared health scope; the optional read ID is used only when that endpoint exists. These callbacks never execute migrations or inspect domain tables. Each endpoint is checked through one dedicated probe connection outside MaxOpen, so a saturated application pool cannot make every replica unready at once.
func (*DB) RoutingStats ¶
func (db *DB) RoutingStats() RoutingStats
RoutingStats returns a synchronized snapshot of primary and optional read pool utilization.
func (*DB) Session ¶
Session owns one connection until its callback and all cleanup have exited. Operations must be sequential; an escaped Session rejects later use. A scope with unfinished work is canceled and discarded instead of returned to the pool.
func (*DB) Start ¶
Start verifies a prepared pool once. The first caller's context controls that attempt; concurrent callers may stop waiting using their own contexts. A failed start is terminal for this pool; prepare another instance for a deliberate retry.
func (*DB) Stats ¶
Stats returns a synchronized snapshot of combined pool utilization and resource ownership.
func (*DB) Transaction ¶
func (db *DB) Transaction(ctx context.Context, fn func(*Tx) error, options ...TxOptions) (err error)
Transaction runs one callback exactly once. Options may contain at most one value. Callback failure, panic or Goexit rolls back; no user callback is retried. The begin context owns the callback phase. The callback runs in an owned goroutine so Goexit cannot bypass rollback. Cancellation is cooperative.
Once the callback succeeds, COMMIT runs detached from caller cancellation and is bounded by PoolConfig.CommitTimeout, so a client disconnect cannot turn a committing transaction into an unknown outcome. ROLLBACK is bounded likewise.
A callback error that contains no database failure is returned with its own identity and formatting after a confirmed rollback. Database failures are *Error values carrying the transaction Outcome.
Successful commit releases the connection before after-commit callbacks run. An Error with Outcome()==Committed means persistence succeeded despite a callback/release failure. Unknown commit outcomes require reconciliation; retrying this whole callback could duplicate external side effects.
type Detail ¶
type Detail struct {
Code Code
SQLState string
Constraint string
Schema string
Table string
CommitRejected bool
StatementRejected bool
}
Detail is the safe, structured classification produced by a driver adapter. Schema, Table, Constraint and SQLState are metadata, never query text, arguments or detail messages. CommitRejected is true only when the server confirms no commit. StatementRejected is true only when the adapter confirms a failed statement outside an explicit transaction did not commit: it was never sent, or the server rejected it before its implicit transaction could complete. Adapters must leave it false for connection loss, cancellation or unknown completion.
type EncryptedRow ¶
type EncryptedRow interface {
Row
// FieldEncryption returns the row's decryption context and owning pool's key ring.
FieldEncryption() (context.Context, *encryption.Keyring)
}
EncryptedRow is a Row that can decrypt encrypted model fields. Rows from a pool, transaction or session implement it; framework row adapters forward it.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error retains the driver cause while formatting only operation and code. Unwrapped causes may contain SQL, values or credentials; do not log them.
func (*Error) Constraint ¶
Constraint returns the adapter-reported constraint name, if available.
func (*Error) Error ¶
Error returns the operation and classification without formatting the driver cause.
func (*Error) FoundryDiagnostic ¶
FoundryDiagnostic contributes the safe classification to redacted failure diagnostics. Adapter metadata and public operation text remain private.
func (*Error) Outcome ¶
Outcome returns the recorded database outcome, independently of callback success.
func (*Error) Schema ¶
Schema returns the server-reported relation namespace. Example: failure.Schema().
type Executor ¶
type Executor interface {
// Exec executes a raw parameterized statement and returns its affected-row count.
Exec(context.Context, string, ...any) (Result, error)
// Query executes a raw parameterized statement and returns a stream that the caller must close.
Query(context.Context, string, ...any) (*Rows, error)
}
Executor is the raw SQL capability shared by pools and transactions. Values belong in arguments; never concatenate untrusted values into statement text. Model-specific type checking belongs to generated queries above this boundary.
type Isolation ¶
type Isolation uint8
Isolation selects portable PostgreSQL transaction isolation levels.
type JSONKind ¶
type JSONKind string
JSONKind identifies a JSON value's top-level shape. JSONNull is distinct from SQL NULL.
type Option ¶
type Option func(*poolSettings) error
Option configures application-owned database runtime dependencies separately from connection bounds and adapter credentials.
func WithClock ¶
WithClock injects model lifecycle time. Direct Open/Prepare calls default to clock.System; database Modules inherit the application's clock unless this option supplies an explicit override. Connection and cleanup deadlines always use real context deadlines. The source must be safe for concurrent use.
func WithConnectionLimit ¶
WithConnectionLimit caps all configured endpoints, including a read pool contributed by another option. It does not increase individual pool limits. Without this option a single pool's ceiling is its MaxOpen; WithReadPool must always supply a combined bound. Repeated limits are rejected.
func WithEncryption ¶
func WithEncryption(keys *encryption.Keyring) Option
WithEncryption gives the pool the application key ring used by encrypted model fields (database/encrypted). Transactions, sessions and result rows of the pool use the same key ring; without it, encrypted reads and writes fail instead of exposing or storing plaintext. Configured applications pass their Encryption key ring to every database connection.
func WithQueryObserver ¶
func WithQueryObserver(observer QueryObserver) Option
WithQueryObserver installs one statement observer for metrics or tracing. Observers are fixed for the pool's lifetime.
func WithReadPool ¶
func WithReadPool(adapter func() (Adapter, error), config PoolConfig, maxConnections int) Option
WithReadPool configures an optional read endpoint and an explicit combined connection ceiling. The primary and read MaxOpen sum must fit that ceiling. The adapter factory runs during Prepare, must be pure and must return a fresh or safely shared connector. A configured endpoint never silently falls back when unavailable. Without this option reads use the primary pool.
func WithSlowQueryLog ¶
WithSlowQueryLog logs statements taking at least threshold at Warn level with role, operation, duration, pool wait, row count, classification and a statement fingerprint (FNV-1a of the SQL text) that groups identical statements. Neither SQL text nor argument values are logged.
func WithSlowQueryThreshold ¶
WithSlowQueryThreshold enables slow-statement logging through the owning application's logger, which a database Module binds during boot. Direct Open/Prepare callers supply a logger with WithSlowQueryLog instead; Start rejects a threshold that has no logger.
func WithStartupLog ¶
WithStartupLog supplies diagnostics for direct Open/Prepare callers. Modules inherit their application's logger by default. Logs contain pool role, attempt, elapsed time, retry delay and classification, never connection strings or driver error text. This option does not enable query timing.
func WithStatementDetector ¶
func WithStatementDetector(d *StatementDetector) Option
WithStatementDetector composes detection with the existing query observer. Install the same instance used to Begin scopes; omitted means no instrumentation. Example: database.WithStatementDetector(detector).
func WithStickyReads ¶
WithStickyReads makes routed reads read-your-writes within a request scope: after a write through this DB in a context marked by StickyReads, reads that would use the read pool use the primary for window. Writes are Exec, transactions that are not read-only (including savepoints' outer transaction) and framework autocommit statements. Without a marked context or a read pool the option has no effect.
type Outcome ¶
type Outcome string
Outcome distinguishes a transaction's database outcome from callback success.
type PoolConfig ¶
type PoolConfig struct {
MaxOpen int
MaxIdle int
MaxLifetime time.Duration
MaxIdleTime time.Duration
ConnectTimeout time.Duration
AcquireTimeout time.Duration
CommitTimeout time.Duration
StartupTimeout time.Duration
}
PoolConfig bounds connection ownership. Use DefaultPoolConfig as a starting point, then change fields explicitly. Zero idle/lifetime settings disable idle retention/expiry respectively; maximum open connections and timeouts must be positive. Query execution uses its caller's context, not AcquireTimeout.
CommitTimeout bounds COMMIT and ROLLBACK after a transaction callback returns. Completion is detached from caller cancellation, so a client disconnect cannot turn an in-flight COMMIT into an unknown outcome. StartupTimeout is the total budget Start may spend retrying transient connection failures such as a database that is still starting; zero makes one attempt. Authentication and other non-transient failures are never retried.
func DefaultPoolConfig ¶
func DefaultPoolConfig() PoolConfig
DefaultPoolConfig returns a fresh, bounded configuration for one process. Idle retention equals MaxOpen so steady load does not churn connections; MaxIdleTime still closes connections left unused after a burst.
func (PoolConfig) Validate ¶
func (c PoolConfig) Validate() error
Validate rejects impossible or unbounded connection/acquisition settings.
type PoolHealth ¶
PoolHealth retains the endpoint identity and a safely formatted database error. Unwrapped driver causes remain explicit diagnostic access only.
type PoolRole ¶
type PoolRole string
PoolRole identifies an explicitly selected endpoint, never inferred SQL text.
type PoolStats ¶
type PoolStats struct {
Role PoolRole
MaxOpen, Open, InUse, Idle int
WaitCount int64
WaitDuration time.Duration
MaxIdleClosed int64
MaxIdleTimeClosed int64
MaxLifetimeClosed int64
}
PoolStats describes one endpoint. Resource owners belong to the shared DB and appear once in Stats; per-endpoint connection counts are independent. Counts and durations are cumulative since Start, suitable for metric counters. The dedicated readiness probe connection is not included.
type PrimaryExecutor ¶
type PrimaryExecutor struct {
// contains filtered or unexported fields
}
PrimaryExecutor pins all query and transaction work to the primary endpoint. It shares lifecycle, observers and shutdown ownership with its original DB. Its zero value rejects execution.
func (PrimaryExecutor) Clock ¶
func (p PrimaryExecutor) Clock() clock.Clock
Clock returns the original DB's application clock, or nil for the zero value.
func (PrimaryExecutor) Exec ¶
func (p PrimaryExecutor) Exec(ctx context.Context, statement string, arguments ...any) (Result, error)
Exec executes a parameterized statement on primary, or returns NotReady for a zero executor.
func (PrimaryExecutor) FoundryAutocommitQuery ¶
func (p PrimaryExecutor) FoundryAutocommitQuery(seal sqlowner.AutocommitSeal, ctx context.Context, statement string, arguments ...any) (*Rows, error)
FoundryAutocommitQuery keeps framework single-statement writes on primary.
func (PrimaryExecutor) FoundryObservers ¶
func (p PrimaryExecutor) FoundryObservers(seal sqlowner.ObserverSeal) (lifecycle.Observers, bool)
FoundryObservers reports the pinned pool's owner metadata.
func (PrimaryExecutor) Query ¶
func (p PrimaryExecutor) Query(ctx context.Context, statement string, arguments ...any) (*Rows, error)
Query opens a result stream on primary, or returns NotReady for a zero executor. The caller must close the returned stream.
func (PrimaryExecutor) Transaction ¶
func (p PrimaryExecutor) Transaction(ctx context.Context, fn func(*Tx) error, options ...TxOptions) error
Transaction runs the callback in a primary transaction using the owning database's outcome handling. A zero executor returns NotReady.
type QueryEvent ¶
type QueryEvent struct {
Role PoolRole
Operation string
Statement string
Duration time.Duration
PoolWait time.Duration
Rows int64
Code Code
SQLState string
}
QueryEvent describes one completed Exec or Query statement. Statement is the SQL text as sent: framework statements contain only identifiers, placeholders and declared constants, while raw statements contain whatever literals the application wrote. Argument values are never exposed.
Duration runs from sending until Exec returned or the Rows stream closed, so a streamed query includes the caller's iteration. PoolWait is connection acquisition for pool-level statements and zero inside transactions and sessions. Rows counts affected (Exec) or returned (Query) rows, -1 when the driver could not report it. Code and SQLState are empty on success.
type QueryObserver ¶
type QueryObserver func(context.Context, QueryEvent)
QueryObserver receives completed statements synchronously on the executing goroutine. It must be fast, must not use the database and must not retain the context. A panic is contained and never changes the statement result.
type ReadRouter ¶
type ReadRouter interface {
Executor
// QueryRead executes caller-classified read SQL according to the executor's routing policy.
QueryRead(context.Context, string, ...any) (*Rows, error)
}
ReadRouter is an optional executor capability for explicitly declared reads. Wrappers that intend to retain routing should forward QueryRead as well as Query; ordinary Executor wrappers deliberately retain their own Query policy. Transactions and connection-scoped sessions never implement this capability.
type Result ¶
type Result struct{ RowsAffected int64 }
Result reports affected rows. PostgreSQL generated IDs use RETURNING with Query rather than the non-portable database/sql LastInsertId contract.
type RetryPolicy ¶
RetryPolicy bounds automatic re-execution of a whole transaction. Attempts counts every execution, including the first. Waits between attempts use full jitter over an exponentially growing delay capped at MaxDelay.
func DefaultRetryPolicy ¶
func DefaultRetryPolicy() RetryPolicy
DefaultRetryPolicy allows three attempts with short jittered waits.
func (RetryPolicy) Validate ¶
func (p RetryPolicy) Validate() error
Validate checks attempt and delay bounds, returning fault.Invalid for invalid settings.
type RoutingStats ¶
RoutingStats combines per-endpoint pool snapshots with the configured connection ceiling.
type Row ¶
type Row interface {
// Scan decodes the current row into the supplied destinations.
Scan(...any) error
}
Row is the read capability passed to typed hydration callbacks. Standard Go sql.Scanner implementations work at this explicit raw decoding boundary.
type Rows ¶
type Rows struct {
// contains filtered or unexported fields
}
Rows owns a sequential result stream. It does not materialize the full result set. Scan destinations may be partially populated on errors and must then be discarded. Generated hydration builds a fresh value before publishing it.
func ReadQuery ¶
func ReadQuery(ctx context.Context, executor Executor, statement string, arguments ...any) (*Rows, error)
ReadQuery executes SQL already classified as a read by its caller. Generated SELECTs use this boundary; raw Query and writes keep their primary semantics. It never examines SQL text and never replaces an actual transaction executor.
func (*Rows) Err ¶
Err returns retained scan, iteration and cleanup failures, or the current iteration failure.
func (*Rows) FieldEncryption ¶
func (r *Rows) FieldEncryption() (context.Context, *encryption.Keyring)
FieldEncryption is the decryption scope of a result stream: its query context and its pool's key ring. Generated decoders use it through FieldEncryption(row) to open encrypted fields while hydrating.
func (*Rows) FoundryCollect ¶
func (r *Rows) FoundryCollect(seal sqlowner.CollectionSeal, ctx context.Context, scan func(Row) error) (count int, err error)
FoundryCollect lends the stream to a framework decoder until the entire loop exits. The capability is internal; scan must not retain or share its borrowed Row. The stream mutex excludes public Next/Scan/Close throughout that lifetime. Every exit closes rows and a failed collection publishes no count or models.
func (*Rows) Next ¶
Next advances to the next result row, closing the stream at exhaustion or failure. Check Err after iteration.
func (*Rows) Observers ¶
Observers retains the actual database owner's immutable registrations, even after the stream closes. Executor wrappers preserve this metadata by returning the original Rows. Inspecting it never constructs or dispatches model hooks.
func (*Rows) Scan ¶
Scan decodes the current row into destinations and closes the stream on a scan failure. It returns Closed if the stream is already closed.
func (*Rows) WithObserverScope ¶
WithObserverScope is the generated read adapter's lifetime boundary. Call it before iterating or closing this stream. Each stream accepts one scope. The callback must close rows before issuing SQL on their transaction or session; this method also closes rows on callback return, error, panic or Goexit.
Closing the stream releases its SQL operation, while this scope retains work ownership until fn exits. The callback context keeps ctx's values and observes ctx, the actual query caller and any owning transaction/session cancellation. It expires when fn returns. Declared model hooks are not dispatched here.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is an advanced, callback-scoped connection capability for operations such as migration locks spanning multiple transactions. It preserves one physical connection. Ordinary requests should use DB or Tx instead.
func (*Session) Discard ¶
func (s *Session) Discard()
Discard prevents this connection from returning to the pool after the callback. Use it whenever session state, such as an advisory lock, cannot be cleaned up.
func (*Session) Encryption ¶
func (s *Session) Encryption() *encryption.Keyring
Encryption retains the owning pool's key ring on a connection-scoped session.
func (*Session) Exec ¶
Exec and Query on a session may write, so with WithStickyReads they mark the request scope when they start and when they complete.
func (*Session) FoundryObservers ¶
FoundryObservers reports the session owner's frozen observer set.
func (*Session) Query ¶
Query opens a result stream on the session's retained connection and marks primary-write stickiness. Close the stream before starting another operation on the session.
func (*Session) Transaction ¶
Transaction runs on this session's existing connection. Unlike DB.Transaction, the session still retains the connection while after-commit callbacks run. Such callbacks must not reenter this session, and reacquiring the pool needs capacity for an additional connection. No physical commit is hidden inside a savepoint.
type StatementDetector ¶
type StatementDetector struct {
// contains filtered or unexported fields
}
StatementDetector is an immutable, injected observer; scopes own all counters. Raw SQL is identified only by a private per-instance keyed fingerprint.
func NewStatementDetector ¶
func NewStatementDetector(c StatementDetectorConfig) (*StatementDetector, error)
NewStatementDetector validates bounds and creates a private fingerprint key. Example: detector, err := database.NewStatementDetector(limits).
func (*StatementDetector) Begin ¶
func (d *StatementDetector) Begin(ctx context.Context) (context.Context, *StatementScope)
Begin starts an isolated scope. Nested scopes replace their parent for this detector. Example: ctx, scope := detector.Begin(t.Context()).
func (*StatementDetector) GoString ¶
func (*StatementDetector) GoString() string
GoString returns a fixed label without exposing the detector's private fingerprint key.
func (*StatementDetector) Observe ¶
func (d *StatementDetector) Observe(ctx context.Context, event QueryEvent)
Observe is the raw observer integration. Without compiler-owned internal metadata, statement text can only become an opaque keyed fingerprint.
func (*StatementDetector) String ¶
func (*StatementDetector) String() string
String returns a fixed label without exposing the detector's private fingerprint key.
type StatementDetectorConfig ¶
type StatementDetectorConfig struct{ Threshold, MaxShapes int }
StatementDetectorConfig bounds one test/request scope. Threshold is per shape. Example: c := database.DefaultStatementDetectorConfig().
func DefaultStatementDetectorConfig ¶
func DefaultStatementDetectorConfig() StatementDetectorConfig
DefaultStatementDetectorConfig permits ten executions per shape and 128 shapes per scope. Example: limits := database.DefaultStatementDetectorConfig().
type StatementReport ¶
type StatementReport struct {
Violations []StatementViolation
Overflow bool
CallSiteOverflow bool
}
StatementReport is an owned inspection snapshot. Either overflow flag means observation is incomplete, even when no retained shape exceeds its threshold.
type StatementScope ¶
type StatementScope struct {
// contains filtered or unexported fields
}
StatementScope retains trusted compiler shapes or keyed fingerprints, never raw SQL.
func (*StatementScope) Report ¶
func (s *StatementScope) Report() StatementReport
Report snapshots completed statements; close query rows before inspecting it. Example: report := scope.Report().
type StatementViolation ¶
type StatementViolation struct {
Shape string
Count, Threshold int
CallSites []string
CallSiteOverflow bool
}
StatementViolation contains only compiler-owned text or an opaque fingerprint, counts and up to four source locations. CallSiteOverflow makes truncation explicit.
type Stats ¶
type Stats struct {
Open int
InUse int
Idle int
WaitCount int64
WaitDuration time.Duration
Owners int
Closing bool
Ready bool
}
Stats is a snapshot of standard pool utilization and Foundry resource owners. Owners includes work waiting to acquire a connection, rows, transaction scopes and their connections. After-commit callbacks retain the scope owner only.
type Transactor ¶
type Transactor interface {
// Transaction runs and waits for a callback in an atomic transaction or nested savepoint scope.
// Returned errors must preserve the database outcome.
Transaction(context.Context, func(*Tx) error, ...TxOptions) error
}
Transactor owns a callback's atomic transaction scope. DB and Session open a transaction; Tx creates a savepoint within its existing transaction. Custom implementations must wait for callback completion and preserve outcome errors.
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Tx is a callback-scoped transaction or savepoint. Use it sequentially and close query rows before returning from its callback. Overlapping operations fail with Busy. An escaped Tx is closed after its callback; it cannot commit independently or be reused in a later request.
func (*Tx) AfterCommit ¶
AfterCommit registers process-local work. Registration order is retained; failures are collected without skipping later callbacks. Savepoint callbacks reach the outer transaction only after successful release. These callbacks have no crash durability; enqueue durable publication through the outbox layer.
func (*Tx) BelongsTo ¶
BelongsTo checks pool ownership without I/O. Infrastructure adapters use it before joining an application's transaction. It is not authorization and does not establish that the transaction is still active; normal operations enforce lifetime. Savepoints and connection-scoped transactions retain the same owner.
func (*Tx) Clock ¶
Clock retains the actual transaction owner's time source through savepoints and custom transactor wrappers. Its time is not frozen at transaction start.
func (*Tx) Encryption ¶
func (tx *Tx) Encryption() *encryption.Keyring
Encryption retains the owning pool's key ring through savepoints.
func (*Tx) Exec ¶
func (tx *Tx) Exec(ctx context.Context, statement string, arguments ...any) (result Result, err error)
Exec executes a parameterized statement within this transaction scope without committing it.
func (*Tx) FoundryObservers ¶
FoundryObservers reports the transaction owner's frozen observer set.
func (*Tx) Observers ¶
Observers retains the owning database's declarations on transactions and nested savepoints. Custom transactors must use this supplied Tx's ownership.
func (*Tx) Query ¶
Query opens a result stream within this transaction scope without committing it. Close the stream before starting another operation on the scope.
func (*Tx) Savepoint ¶
Savepoint creates an explicit nested scope. Its callback must use the supplied child Tx. The parent rejects other operations until this scope finishes. Success releases the savepoint, merging callbacks into the parent; it does not commit. Failure rolls back this scope and discards its after-commit callbacks. If rollback/release fails, the outer transaction is poisoned and cannot commit even when application code ignores the savepoint error.
func (*Tx) SharesTransaction ¶
SharesTransaction reports whether two scopes belong to the same outer SQL transaction, including nested savepoints. It performs no I/O and does not prove either scope is active. Independent transactions from one pool differ.
func (*Tx) State ¶
State returns a synchronized snapshot of the transaction scope's lifecycle state.
func (*Tx) Transaction ¶
Transaction runs a nested callback in a savepoint. Isolation and read-only settings belong to the outer transaction, so nested options are rejected. Successful return releases the savepoint; only the outer scope can commit.
Source Files
¶
- clock.go
- diagnostics.go
- encryption.go
- errors.go
- execution.go
- instrumentation.go
- json_kind.go
- module.go
- named.go
- observer_owner.go
- observer_scope.go
- observers.go
- pool.go
- readiness.go
- retry.go
- routing.go
- row_collection.go
- savepoint.go
- scope.go
- session.go
- startup_logging.go
- statement_detector.go
- sticky_reads.go
- transaction.go
- transactor.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package codec preserves concrete Go types through the SQL value boundary.
|
Package codec preserves concrete Go types through the SQL value boundary. |
|
Package command provides migration and seeder commands for a consumer binary.
|
Package command provides migration and seeder commands for a consumer binary. |
|
Package encrypted provides model field types that are stored as authenticated encryption envelopes, like Laravel's encrypted casts.
|
Package encrypted provides model field types that are stored as authenticated encryption envelopes, like Laravel's encrypted casts. |
|
Package lifecycle defines typed model lifecycle data shared by generated hooks, observers and audit integrations.
|
Package lifecycle defines typed model lifecycle data shared by generated hooks, observers and audit integrations. |
|
Package migrate declares immutable, versioned schema changes and validates migration history.
|
Package migrate declares immutable, versioned schema changes and validates migration history. |
|
Package orm declares typed tables without generated model adapters.
|
Package orm declares typed tables without generated model adapters. |
|
expr
Package expr provides thin, typed SQL expressions in explicit source scopes.
|
Package expr provides thin, typed SQL expressions in explicit source scopes. |
|
internal/enuminit
Package enuminit deliberately declares models before generated enum variables.
|
Package enuminit deliberately declares models before generated enum variables. |
|
rows
Package rows provides typed aliases, joins and complete row projections.
|
Package rows provides typed aliases, joins and complete row projections. |
|
Package postgres adapts pgx to Foundry's database contracts.
|
Package postgres adapts pgx to Foundry's database contracts. |
|
Package prune removes obsolete models in bounded batches, like Laravel's Prunable and MassPrunable models.
|
Package prune removes obsolete models in bounded batches, like Laravel's Prunable and MassPrunable models. |
|
Package relation provides explicit loaded states for typed model relations.
|
Package relation provides explicit loaded states for typed model relations. |
|
Package seed runs explicitly registered data seeders through normal Foundry transactions.
|
Package seed runs explicitly registered data seeders through normal Foundry transactions. |