Help us shape the future of Go! Take the 2026 Go Developer Survey

database

package
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 37 Imported by: 0

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

View Source
const MaxRetryAttempts = 10

MaxRetryAttempts bounds one Retry call.

Variables

This section is empty.

Functions

func FieldEncryption

func FieldEncryption(row Row) (context.Context, *encryption.Keyring, error)

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

func FoundryObservers(writer any, seal sqlowner.ObserverSeal) (lifecycle.Observers, bool)

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

func NewError(operation string, code Code) error

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

func StickyReads(ctx context.Context) context.Context

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.

func StickyReadsHandler

func StickyReadsHandler(next http.Handler) http.Handler

StickyReadsHandler gives every request its own StickyReads scope. Add it to the HTTP middleware stack of applications whose database uses WithStickyReads; background work may call StickyReads explicitly.

Types

type Adapter

type Adapter struct {
	Connector driver.Connector
	Classify  func(error) Detail
}

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"
	Unavailable          Code = "unavailable"
	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"
)

func (Code) Error

func (c Code) Error() string

Error returns the classification code as text.

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

func Open(ctx context.Context, adapter Adapter, config PoolConfig, options ...Option) (*DB, error)

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

func (db *DB) BindObservers(set lifecycle.Observers) error

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

func (db *DB) Clock() clock.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

func (db *DB) Close(ctx context.Context) error

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

func (db *DB) FoundryObservers(seal sqlowner.ObserverSeal) (set lifecycle.Observers, known bool)

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

func (db *DB) HasReadPool() bool

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

func (db *DB) Observers() lifecycle.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

func (db *DB) Ping(ctx context.Context) (err error)

Ping checks every configured endpoint using the caller's context. Dependency failure affects readiness; it is not a process liveness failure.

func (*DB) PingPrimary

func (db *DB) PingPrimary(ctx context.Context) error

PingPrimary checks the primary endpoint through its dedicated probe connection, so a saturated application pool cannot make readiness fail.

func (*DB) PingRead

func (db *DB) PingRead(ctx context.Context) error

PingRead checks the selected read endpoint, falling back only when absent.

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

func (db *DB) Query(ctx context.Context, statement string, arguments ...any) (*Rows, error)

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

func (db *DB) QueryRead(ctx context.Context, statement string, arguments ...any) (*Rows, error)

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

func (db *DB) ReadinessProbes(primary, read health.ProbeID) []health.Probe

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

func (db *DB) Session(ctx context.Context, fn func(*Session) error) (err error)

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

func (db *DB) Start(ctx context.Context) error

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

func (db *DB) Stats() 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) Code

func (e *Error) Code() Code

Code returns the database failure classification.

func (*Error) Constraint

func (e *Error) Constraint() string

Constraint returns the adapter-reported constraint name, if available.

func (*Error) Error

func (e *Error) Error() string

Error returns the operation and classification without formatting the driver cause.

func (*Error) FoundryDiagnostic

func (e *Error) FoundryDiagnostic(seal errordiag.Seal) []fault.Attribute

FoundryDiagnostic contributes the safe classification to redacted failure diagnostics. Adapter metadata and public operation text remain private.

func (*Error) GoString

func (e *Error) GoString() string

GoString returns the same safe text as Error.

func (*Error) Is

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

Is reports whether target is the same database classification code.

func (*Error) Outcome

func (e *Error) Outcome() Outcome

Outcome returns the recorded database outcome, independently of callback success.

func (*Error) SQLState

func (e *Error) SQLState() string

SQLState returns the adapter-reported SQLSTATE, if available.

func (*Error) Schema

func (e *Error) Schema() string

Schema returns the server-reported relation namespace. Example: failure.Schema().

func (*Error) Table

func (e *Error) Table() string

Table returns the server-reported relation name. Example: failure.Table().

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the retained cause, which may contain private driver details.

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.

const (
	DefaultIsolation Isolation = iota
	ReadCommitted
	RepeatableRead
	Serializable
)

type JSONKind

type JSONKind string

JSONKind identifies a JSON value's top-level shape. JSONNull is distinct from SQL NULL.

const (
	JSONObject  JSONKind = "object"
	JSONArray   JSONKind = "array"
	JSONString  JSONKind = "string"
	JSONNumber  JSONKind = "number"
	JSONBoolean JSONKind = "boolean"
	JSONNull    JSONKind = "null"
)

func (JSONKind) Validate

func (k JSONKind) Validate() error

Validate returns fault.Invalid unless the kind is a recognized JSON shape.

type Option

type Option func(*poolSettings) error

Option configures application-owned database runtime dependencies separately from connection bounds and adapter credentials.

func WithClock

func WithClock(source clock.Clock) Option

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

func WithConnectionLimit(maxConnections int) Option

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

func WithSlowQueryLog(logger *slog.Logger, threshold time.Duration) Option

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

func WithSlowQueryThreshold(threshold time.Duration) Option

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

func WithStartupLog(logger *slog.Logger) Option

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

func WithStickyReads(window time.Duration) Option

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.

const (
	Unspecified Outcome = "unspecified"
	NoCommit    Outcome = "no_commit"
	Committed   Outcome = "committed"
	RolledBack  Outcome = "rolled_back"
	Unknown     Outcome = "unknown"
)

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

type PoolHealth struct {
	Role  PoolRole
	Error error
}

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.

const (
	PrimaryPool PoolRole = "primary"
	ReadPool    PoolRole = "read"
)

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

type RetryPolicy struct {
	Attempts     int
	InitialDelay time.Duration
	MaxDelay     time.Duration
}

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

type RoutingStats struct {
	Primary        PoolStats
	Read           value.Optional[PoolStats]
	MaxConnections int
}

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) Close

func (r *Rows) Close() error

Close is idempotent and preserves scan, iteration, and release errors.

func (*Rows) Columns

func (r *Rows) Columns() ([]string, error)

Columns returns a caller-owned snapshot of result column names.

func (*Rows) Err

func (r *Rows) Err() error

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

func (r *Rows) Next() bool

Next advances to the next result row, closing the stream at exhaustion or failure. Check Err after iteration.

func (*Rows) Observers

func (r *Rows) Observers() lifecycle.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

func (r *Rows) Scan(destinations ...any) error

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

func (r *Rows) WithObserverScope(ctx context.Context, fn func(context.Context) error) (err error)

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) Clock

func (s *Session) Clock() clock.Clock

Clock retains the owning pool's time source on a connection-scoped session.

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

func (s *Session) Exec(ctx context.Context, statement string, arguments ...any) (Result, error)

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

func (s *Session) FoundryObservers(seal sqlowner.ObserverSeal) (lifecycle.Observers, bool)

FoundryObservers reports the session owner's frozen observer set.

func (*Session) Observers

func (s *Session) Observers() lifecycle.Observers

Observers retains the owning database's declarations on this session.

func (*Session) Query

func (s *Session) Query(ctx context.Context, statement string, arguments ...any) (*Rows, error)

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

func (s *Session) Transaction(ctx context.Context, fn func(*Tx) error, options ...TxOptions) error

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

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

func (tx *Tx) AfterCommit(fn func(context.Context) error) error

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

func (tx *Tx) BelongsTo(db *DB) bool

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

func (tx *Tx) Clock() clock.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

func (tx *Tx) FoundryObservers(seal sqlowner.ObserverSeal) (lifecycle.Observers, bool)

FoundryObservers reports the transaction owner's frozen observer set.

func (*Tx) Observers

func (tx *Tx) Observers() lifecycle.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

func (tx *Tx) Query(ctx context.Context, statement string, arguments ...any) (*Rows, error)

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

func (tx *Tx) Savepoint(ctx context.Context, fn func(*Tx) error) error

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

func (tx *Tx) SharesTransaction(other *Tx) bool

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

func (tx *Tx) State() TxState

State returns a synchronized snapshot of the transaction scope's lifecycle state.

func (*Tx) Transaction

func (tx *Tx) Transaction(ctx context.Context, fn func(*Tx) error, options ...TxOptions) error

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.

type TxOptions

type TxOptions struct {
	Isolation Isolation
	ReadOnly  bool
}

TxOptions controls one transaction. The zero value uses server defaults.

type TxState

type TxState string

TxState describes scope lifetime. A released savepoint has not committed; only the outer transaction can produce a Committed database outcome.

const (
	TxActive     TxState = "active"
	TxFinishing  TxState = "finishing"
	TxCommitted  TxState = "committed"
	TxRolledBack TxState = "rolled_back"
	TxUnknown    TxState = "unknown"
	TxReleased   TxState = "savepoint_released"
)

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.
orm
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.

Jump to

Keyboard shortcuts

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