Documentation
¶
Index ¶
- Variables
- func ActorFromContext(ctx context.Context) string
- func Aggregate[R any, T any](ctx context.Context, q projectable[T], agg AggExpr) (R, error)
- func ContextWithTx(ctx context.Context, tx *Tx) context.Context
- func EventTypeName(v any) (string, error)
- func GroupBy[R any, T any](ctx context.Context, q projectable[T], groups []GroupSpec, aggs []AliasedAgg, ...) ([]*R, error)
- func InboxSchema(table, dialect string) string
- func JSONEqual[T any](a, b T) bool
- func NormalizeIntKey(v any) any
- func NormalizeUUIDKey(v any) any
- func OutboxSchema(table, dialect string) string
- func RawQuery[T any](ctx context.Context, e *Engine, sql string, args ...any) ([]*T, error)
- func RawQueryRow[T any](ctx context.Context, e *Engine, sql string, args ...any) (*T, error)
- func Select[R any, T any](ctx context.Context, q projectable[T], cols ...ColumnRef) ([]*R, error)
- func SetKeyGenerator[T any](meta ModelMeta[T], gen func() any)
- func SetKeyStrategy[T any](meta ModelMeta[T], s KeyStrategy)
- func UUIDv7Key() any
- func WithActor(ctx context.Context, actor string) context.Context
- type AfterCommitHook
- type AggExpr
- type AliasedAgg
- type Audit
- type Batch
- type BatchResult
- type BeforeCommitHook
- type BoolColumn
- func (c BoolColumn) Asc() OrderExpr
- func (c BoolColumn) ColRef() ColumnRef
- func (c BoolColumn) Desc() OrderExpr
- func (c BoolColumn) Eq(v bool) Predicate
- func (c BoolColumn) IsFalse() Predicate
- func (c BoolColumn) IsNotNull() Predicate
- func (c BoolColumn) IsNull() Predicate
- func (c BoolColumn) IsTrue() Predicate
- func (c BoolColumn) NEQ(v bool) Predicate
- func (c BoolColumn) Name() string
- type ClaimedMessage
- type Column
- func (c Column[T]) Asc() OrderExpr
- func (c Column[T]) ColRef() ColumnRef
- func (c Column[T]) Desc() OrderExpr
- func (c Column[T]) Eq(v T) Predicate
- func (c Column[T]) In(vs ...T) Predicate
- func (c Column[T]) IsNotNull() Predicate
- func (c Column[T]) IsNull() Predicate
- func (c Column[T]) NEQ(v T) Predicate
- func (c Column[T]) Name() string
- func (c Column[T]) NotIn(vs ...T) Predicate
- type ColumnRef
- type ComparableColumn
- func (c ComparableColumn[T]) Asc() OrderExpr
- func (c ComparableColumn[T]) Between(low, high T) Predicate
- func (c ComparableColumn[T]) ColRef() ColumnRef
- func (c ComparableColumn[T]) Desc() OrderExpr
- func (c ComparableColumn[T]) Eq(v T) Predicate
- func (c ComparableColumn[T]) GT(v T) Predicate
- func (c ComparableColumn[T]) GTE(v T) Predicate
- func (c ComparableColumn[T]) In(vs ...T) Predicate
- func (c ComparableColumn[T]) IsNotNull() Predicate
- func (c ComparableColumn[T]) IsNull() Predicate
- func (c ComparableColumn[T]) LT(v T) Predicate
- func (c ComparableColumn[T]) LTE(v T) Predicate
- func (c ComparableColumn[T]) NEQ(v T) Predicate
- func (c ComparableColumn[T]) Name() string
- func (c ComparableColumn[T]) NotIn(vs ...T) Predicate
- type CursorPage
- type Engine
- func (e *Engine) ApplyMigrations(ctx context.Context, dir string) (int, error)
- func (e *Engine) ApplyMigrationsFS(ctx context.Context, fsys ...fs.FS) (int, error)
- func (e *Engine) Close()
- func (e *Engine) DialectName() string
- func (e *Engine) Exec(ctx context.Context, sql string, args ...any) (int64, error)
- func (e *Engine) HealthCheck(ctx context.Context) error
- func (e *Engine) NewBatch() *Batch
- func (e *Engine) OnAfterCommit(hook AfterCommitHook)
- func (e *Engine) OnBeforeCommit(hook BeforeCommitHook)
- func (e *Engine) OnQuery(hook QueryHook)
- func (e *Engine) Ping(ctx context.Context) error
- func (e *Engine) Query(ctx context.Context, sql string, args ...any) (Rows, error)
- func (e *Engine) QueryRow(ctx context.Context, sql string, args ...any) Row
- func (e *Engine) Stats() PoolStats
- func (e *Engine) Transaction(ctx context.Context, fn func(tx *Tx) error, opts ...TxOption) (retErr error)
- func (e *Engine) TransactionWithRetry(ctx context.Context, fn func(tx *Tx) error, opts ...TxOption) error
- func (e *Engine) UseOutbox(table string, opts ...OutboxOption)
- func (e *Engine) WithTx(ctx context.Context, fn func(ctx context.Context) error, opts ...TxOption) error
- type EntityState
- type EventRecorder
- type FieldChange
- type GroupByOpt
- type GroupSpec
- type Inbox
- type IncludableQuery
- func (q *IncludableQuery[T]) All(ctx context.Context) ([]*T, error)
- func (q *IncludableQuery[T]) Find(ctx context.Context, id any) (*T, error)
- func (q *IncludableQuery[T]) First(ctx context.Context) (*T, error)
- func (q *IncludableQuery[T]) Include(rels ...IncludeSpec) *IncludableQuery[T]
- func (q *IncludableQuery[T]) Limit(n int) *IncludableQuery[T]
- func (q *IncludableQuery[T]) OrderBy(exprs ...OrderExpr) *IncludableQuery[T]
- func (q *IncludableQuery[T]) Primary() *IncludableQuery[T]
- func (q *IncludableQuery[T]) Skip(n int) *IncludableQuery[T]
- func (q *IncludableQuery[T]) Take(n int) *IncludableQuery[T]
- func (q *IncludableQuery[T]) Unscoped() *IncludableQuery[T]
- func (q *IncludableQuery[T]) Where(pred Predicate) *IncludableQuery[T]
- func (q *IncludableQuery[T]) WithoutFilter(name string) *IncludableQuery[T]
- type IncludeSpec
- func (s IncludeSpec) Limit(n int) IncludeSpec
- func (s IncludeSpec) OrderBy(exprs ...OrderExpr) IncludeSpec
- func (s IncludeSpec) Then(children ...IncludeSpec) IncludeSpec
- func (s IncludeSpec) Unscoped() IncludeSpec
- func (s IncludeSpec) Where(pred Predicate) IncludeSpec
- func (s IncludeSpec) WithoutFilter(name string) IncludeSpec
- type IsolationLevel
- type JSON
- type JoinOn
- type KeyStrategy
- type Model
- func (m *Model[K]) ClearEvents()
- func (m Model[K]) CreatedAt() time.Time
- func (m Model[K]) ID() K
- func (m *Model[K]) PendingEvents() []any
- func (m *Model[K]) RecordEvent(event any)
- func (m *Model[K]) ScanPtrs() (*K, *time.Time, *time.Time)
- func (m *Model[K]) SetID(id K)
- func (m Model[K]) UpdatedAt() time.Time
- type ModelMeta
- type ModelMetaBase
- type MultiColumnMapper
- type NamedFilter
- type OffsetPage
- type Option
- func WithAfterCommitErrorSink(fn func(ctx context.Context, err error)) Option
- func WithAuthToken(token string) Option
- func WithConnMaxIdleTime(d time.Duration) Option
- func WithConnMaxLifetime(d time.Duration) Option
- func WithContext(ctx context.Context) Option
- func WithDevMode() Option
- func WithDialect(dia dialect.Dialect) Option
- func WithDriver(drv driver.Driver) Option
- func WithLogger(logger *slog.Logger) Option
- func WithMaxConns(n int) Option
- func WithQueryLog(enabled bool) Option
- func WithQueryTimeout(d time.Duration) Option
- func WithReadReplica(dsn string) Option
- func WithSimpleProtocol() Option
- func WithSlowQueryThreshold(d time.Duration) Option
- func WithTracer(tracer Tracer) Option
- type OrderExpr
- type OrderedColumn
- func (c OrderedColumn[T]) Asc() OrderExpr
- func (c OrderedColumn[T]) Between(low, high T) Predicate
- func (c OrderedColumn[T]) ColRef() ColumnRef
- func (c OrderedColumn[T]) Desc() OrderExpr
- func (c OrderedColumn[T]) Eq(v T) Predicate
- func (c OrderedColumn[T]) GT(v T) Predicate
- func (c OrderedColumn[T]) GTE(v T) Predicate
- func (c OrderedColumn[T]) In(vs ...T) Predicate
- func (c OrderedColumn[T]) IsNotNull() Predicate
- func (c OrderedColumn[T]) IsNull() Predicate
- func (c OrderedColumn[T]) LT(v T) Predicate
- func (c OrderedColumn[T]) LTE(v T) Predicate
- func (c OrderedColumn[T]) NEQ(v T) Predicate
- func (c OrderedColumn[T]) Name() string
- func (c OrderedColumn[T]) NotIn(vs ...T) Predicate
- type OutboxMessage
- type OutboxOption
- type PoolStats
- type Predicate
- type Publisher
- type PublisherFunc
- type QualifiedCol
- type QueryBuilder
- func (q *QueryBuilder[T]) After(cursor string) *QueryBuilder[T]
- func (q *QueryBuilder[T]) All(ctx context.Context) ([]*T, error)
- func (q *QueryBuilder[T]) AllRows() *QueryBuilder[T]
- func (q *QueryBuilder[T]) Before(cursor string) *QueryBuilder[T]
- func (q *QueryBuilder[T]) BulkDelete(ctx context.Context) (int, error)
- func (q *QueryBuilder[T]) BulkUpdate(ctx context.Context, sets ...SetClause) (int, error)
- func (q *QueryBuilder[T]) Count(ctx context.Context) (int, error)
- func (q *QueryBuilder[T]) Distinct() *QueryBuilder[T]
- func (q *QueryBuilder[T]) Exists(ctx context.Context) (bool, error)
- func (q *QueryBuilder[T]) First(ctx context.Context) (*T, error)
- func (q *QueryBuilder[T]) FirstOrNil(ctx context.Context) (*T, error)
- func (q *QueryBuilder[T]) InnerJoin(table string, on JoinOn) *QueryBuilder[T]
- func (q *QueryBuilder[T]) LeftJoin(table string, on JoinOn) *QueryBuilder[T]
- func (q *QueryBuilder[T]) Limit(n int) *QueryBuilder[T]
- func (q *QueryBuilder[T]) OrderBy(exprs ...OrderExpr) *QueryBuilder[T]
- func (q *QueryBuilder[T]) Page(ctx context.Context) (*CursorPage[T], error)
- func (q *QueryBuilder[T]) PageOffset(ctx context.Context) (*OffsetPage[T], error)
- func (q *QueryBuilder[T]) Primary() *QueryBuilder[T]
- func (q *QueryBuilder[T]) Skip(n int) *QueryBuilder[T]
- func (q *QueryBuilder[T]) Take(n int) *QueryBuilder[T]
- func (q *QueryBuilder[T]) Timeout(d time.Duration) *QueryBuilder[T]
- func (q *QueryBuilder[T]) Unscoped() *QueryBuilder[T]
- func (q *QueryBuilder[T]) Where(pred Predicate) *QueryBuilder[T]
- func (q *QueryBuilder[T]) WithoutFilter(name string) *QueryBuilder[T]
- type QueryEvent
- type QueryHook
- type RawExpr
- type Relation
- type RelationInfo
- type RelationType
- type Relay
- type RelayOption
- func WithRelayBatchSize(n int) RelayOption
- func WithRelayConcurrency(n int) RelayOption
- func WithRelayLease(d time.Duration) RelayOption
- func WithRelayMaxAttempts(n int) RelayOption
- func WithRelayOnDead(fn func(ctx context.Context, msg ClaimedMessage, err error)) RelayOption
- func WithRelayOnError(fn func(ctx context.Context, err error)) RelayOption
- func WithRelayPollInterval(d time.Duration) RelayOption
- func WithRelayWorkerID(id string) RelayOption
- type Repository
- func (r *Repository[T]) After(cursor string) *QueryBuilder[T]
- func (r *Repository[T]) All(ctx context.Context) ([]*T, error)
- func (r *Repository[T]) AllRows() *QueryBuilder[T]
- func (r *Repository[T]) Before(cursor string) *QueryBuilder[T]
- func (r *Repository[T]) BulkInsert(ctx context.Context, entities []*T) (int, error)
- func (r *Repository[T]) BulkInsertWithEvents(ctx context.Context, entities []*T) (int, error)
- func (r *Repository[T]) BulkUpsert(ctx context.Context, entities []*T, opts ...UpsertOption) (int, error)
- func (r *Repository[T]) Count(ctx context.Context) (int, error)
- func (r *Repository[T]) Distinct() *QueryBuilder[T]
- func (r *Repository[T]) Exists(ctx context.Context) (bool, error)
- func (r *Repository[T]) Find(ctx context.Context, id any) (*T, error)
- func (r *Repository[T]) First(ctx context.Context) (*T, error)
- func (r *Repository[T]) FirstOrNil(ctx context.Context) (*T, error)
- func (r *Repository[T]) Include(rels ...IncludeSpec) *IncludableQuery[T]
- func (r *Repository[T]) InnerJoin(table string, on JoinOn) *QueryBuilder[T]
- func (r *Repository[T]) LeftJoin(table string, on JoinOn) *QueryBuilder[T]
- func (r *Repository[T]) Limit(n int) *QueryBuilder[T]
- func (r *Repository[T]) OrderBy(exprs ...OrderExpr) *QueryBuilder[T]
- func (r *Repository[T]) Primary() *QueryBuilder[T]
- func (r *Repository[T]) Skip(n int) *QueryBuilder[T]
- func (r *Repository[T]) Take(n int) *QueryBuilder[T]
- func (r *Repository[T]) Unscoped() *QueryBuilder[T]
- func (r *Repository[T]) Where(pred Predicate) *QueryBuilder[T]
- func (r *Repository[T]) WithoutFilter(name string) *QueryBuilder[T]
- type RetryConfig
- type Row
- type Rows
- type SetClause
- type SoftDelete
- type Span
- type StringColumn
- func (c StringColumn) Asc() OrderExpr
- func (c StringColumn) ColRef() ColumnRef
- func (c StringColumn) Contains(substr string) Predicate
- func (c StringColumn) Desc() OrderExpr
- func (c StringColumn) Eq(v string) Predicate
- func (c StringColumn) GT(v string) Predicate
- func (c StringColumn) GTE(v string) Predicate
- func (c StringColumn) HasPrefix(prefix string) Predicate
- func (c StringColumn) HasSuffix(suffix string) Predicate
- func (c StringColumn) ILike(pattern string) Predicate
- func (c StringColumn) In(vs ...string) Predicate
- func (c StringColumn) IsNotNull() Predicate
- func (c StringColumn) IsNull() Predicate
- func (c StringColumn) LT(v string) Predicate
- func (c StringColumn) LTE(v string) Predicate
- func (c StringColumn) Like(pattern string) Predicate
- func (c StringColumn) NEQ(v string) Predicate
- func (c StringColumn) Name() string
- func (c StringColumn) NotIn(vs ...string) Predicate
- type TimeColumn
- func (c TimeColumn) After(t time.Time) Predicate
- func (c TimeColumn) Asc() OrderExpr
- func (c TimeColumn) Before(t time.Time) Predicate
- func (c TimeColumn) Between(low, high time.Time) Predicate
- func (c TimeColumn) ColRef() ColumnRef
- func (c TimeColumn) Desc() OrderExpr
- func (c TimeColumn) Eq(v time.Time) Predicate
- func (c TimeColumn) GT(v time.Time) Predicate
- func (c TimeColumn) GTE(v time.Time) Predicate
- func (c TimeColumn) In(vs ...time.Time) Predicate
- func (c TimeColumn) IsNotNull() Predicate
- func (c TimeColumn) IsNull() Predicate
- func (c TimeColumn) LT(v time.Time) Predicate
- func (c TimeColumn) LTE(v time.Time) Predicate
- func (c TimeColumn) NEQ(v time.Time) Predicate
- func (c TimeColumn) Name() string
- func (c TimeColumn) NotIn(vs ...time.Time) Predicate
- type Tracer
- type Tx
- func (tx *Tx) AdvisoryLock(ctx context.Context, key int64) error
- func (tx *Tx) Exec(ctx context.Context, sql string, args ...any) (int64, error)
- func (tx *Tx) HardRemove(entity any) error
- func (tx *Tx) NewBatch() *Batch
- func (tx *Tx) Query(ctx context.Context, sql string, args ...any) (Rows, error)
- func (tx *Tx) QueryRow(ctx context.Context, sql string, args ...any) Row
- func (tx *Tx) SaveChanges(ctx context.Context) error
- func (tx *Tx) Savepoint(ctx context.Context, name string, fn func(sp *Tx) error) error
- func (tx *Tx) TryAdvisoryLock(ctx context.Context, key int64) (bool, error)
- type TxIncludableQuery
- func (q *TxIncludableQuery[T]) All(ctx context.Context) ([]*T, error)
- func (q *TxIncludableQuery[T]) Find(ctx context.Context, id any) (*T, error)
- func (q *TxIncludableQuery[T]) First(ctx context.Context) (*T, error)
- func (q *TxIncludableQuery[T]) Include(rels ...IncludeSpec) *TxIncludableQuery[T]
- func (q *TxIncludableQuery[T]) Limit(n int) *TxIncludableQuery[T]
- func (q *TxIncludableQuery[T]) OrderBy(exprs ...OrderExpr) *TxIncludableQuery[T]
- func (q *TxIncludableQuery[T]) Where(pred Predicate) *TxIncludableQuery[T]
- type TxOption
- type TxQueryBuilder
- func (q *TxQueryBuilder[T]) After(cursor string) *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) All(ctx context.Context) ([]*T, error)
- func (q *TxQueryBuilder[T]) AsNoTracking() *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) Before(cursor string) *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) BulkDelete(ctx context.Context) (int, error)
- func (q *TxQueryBuilder[T]) BulkUpdate(ctx context.Context, sets ...SetClause) (int, error)
- func (q *TxQueryBuilder[T]) Count(ctx context.Context) (int, error)
- func (q *TxQueryBuilder[T]) Exists(ctx context.Context) (bool, error)
- func (q *TxQueryBuilder[T]) First(ctx context.Context) (*T, error)
- func (q *TxQueryBuilder[T]) FirstOrNil(ctx context.Context) (*T, error)
- func (q *TxQueryBuilder[T]) Limit(n int) *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) OrderBy(exprs ...OrderExpr) *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) Page(ctx context.Context) (*CursorPage[T], error)
- func (q *TxQueryBuilder[T]) PageOffset(ctx context.Context) (*OffsetPage[T], error)
- func (q *TxQueryBuilder[T]) Skip(n int) *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) Take(n int) *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) Unscoped() *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) Where(pred Predicate) *TxQueryBuilder[T]
- func (q *TxQueryBuilder[T]) WithoutFilter(name string) *TxQueryBuilder[T]
- type TxRepository
- func (r *TxRepository[T]) Add(entity *T)
- func (r *TxRepository[T]) All(ctx context.Context) ([]*T, error)
- func (r *TxRepository[T]) AsNoTracking() *TxQueryBuilder[T]
- func (r *TxRepository[T]) Attach(entity *T, state EntityState)
- func (r *TxRepository[T]) BulkInsert(ctx context.Context, entities []*T) (int, error)
- func (r *TxRepository[T]) BulkUpsert(ctx context.Context, entities []*T, opts ...UpsertOption) (int, error)
- func (r *TxRepository[T]) Detach(entity *T)
- func (r *TxRepository[T]) Find(ctx context.Context, id any) (*T, error)
- func (r *TxRepository[T]) Include(rels ...IncludeSpec) *TxIncludableQuery[T]
- func (r *TxRepository[T]) OrderBy(exprs ...OrderExpr) *TxQueryBuilder[T]
- func (r *TxRepository[T]) Remove(entity *T) error
- func (r *TxRepository[T]) Unscoped() *TxQueryBuilder[T]
- func (r *TxRepository[T]) Where(pred Predicate) *TxQueryBuilder[T]
- func (r *TxRepository[T]) WithoutFilter(name string) *TxQueryBuilder[T]
- type UpsertOption
- type Versioned
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUniqueViolation is returned when an INSERT/UPDATE violates a unique or // primary-key constraint. ErrUniqueViolation = dberr.ErrUniqueViolation // ErrForeignKeyViolation is returned when a foreign-key constraint fails. ErrForeignKeyViolation = dberr.ErrForeignKeyViolation // ErrNotNullViolation is returned when a NOT NULL column receives NULL. ErrNotNullViolation = dberr.ErrNotNullViolation // ErrCheckViolation is returned when a CHECK constraint fails. ErrCheckViolation = dberr.ErrCheckViolation // ErrSerializationFailure is returned for serialization failures / deadlocks // under high isolation; the transaction should be retried. ErrSerializationFailure = dberr.ErrSerializationFailure )
Dialect-neutral database error sentinels. Match them with errors.Is on errors returned by SaveChanges, bulk operations, raw Exec/Query, etc. The original driver error (e.g. *pgconn.PgError) is still reachable via errors.As.
if err := uow.SaveChanges(ctx); errors.Is(err, drel.ErrUniqueViolation) {
return conflict()
}
var ErrBatchNotExecuted = errors.New("drel: batch result read before Execute ran this query")
ErrBatchNotExecuted is the initial error on every queued BatchResult. It is cleared as Execute runs each item, so reading a result before Execute ran (or for an item that never ran because Execute aborted early) returns this rather than a silent zero value.
var ErrBatchPartial = errors.New("drel: one or more batched queries failed")
ErrBatchPartial is returned by Execute when the batch completed but at least one queued query failed. Each failing query's own error is available via its BatchResult.Result(); ErrBatchPartial wraps the first failure.
var ErrBulkDeleteRequiresFilter = fmt.Errorf("drel: BulkDelete requires at least one Where predicate to prevent accidental full-table deletes")
ErrBulkDeleteRequiresFilter is returned when BulkDelete is called without any WHERE predicates or filters.
var ErrBulkUpdateRequiresFilter = fmt.Errorf("drel: BulkUpdate requires at least one Where predicate to prevent accidental full-table updates")
ErrBulkUpdateRequiresFilter is returned when BulkUpdate is called without any user Where predicate and without AllRows(), to prevent accidental full-table updates. Auto-applied filters (e.g. soft-delete) do not satisfy the guard.
var ErrConcurrencyConflict = errors.New("drel: concurrency conflict — entity was modified by another transaction")
ErrConcurrencyConflict is returned when an entity was modified by another transaction.
var ErrCursorColumnNullable = errors.New(
"drel: cursor pagination over a NULL-valued ordering key requires NullsFirst()/NullsLast() on that column")
ErrCursorColumnNullable is returned when a keyset cursor must page across a NULL-valued ordering key whose NULL placement is not pinned. Pin it with NullsFirst()/NullsLast() on that OrderBy column so paging is deterministic.
var ErrCursorPaginationNeedsOrderBy = errors.New("drel: cursor pagination requires OrderBy")
ErrCursorPaginationNeedsOrderBy is returned when Page is called without an OrderBy. Keyset pagination requires a deterministic ordering.
var ErrDuplicateMessage = errors.New("drel: the handler already processed this message")
ErrDuplicateMessage reports that the handler already processed the message. The caller must acknowledge the message to the broker and do no further work.
var ErrEntityNotTracked = errors.New("drel: entity is not tracked")
ErrEntityNotTracked is returned when an operation requires a tracked entity but none is found.
var ErrInvalidCursor = errors.New("drel: invalid cursor")
ErrInvalidCursor is returned when a cursor string cannot be decoded.
var ErrInvalidPageSize = errors.New("drel: page size (Take/Limit) must be > 0")
ErrInvalidPageSize is returned when a pagination page size (Take/Limit) is <= 0.
var ErrNestedTxOptions = errors.New("drel: transaction options are not allowed on a nested WithTx call")
ErrNestedTxOptions reports that a nested WithTx call carried transaction options. Isolation and read-only belong to the outermost call, because a savepoint cannot change them.
var ErrNotFound = errors.New("drel: not found")
ErrNotFound is returned when a query expects a result but finds none.
var ErrOutboxAnonymousEvent = errors.New("drel: outbox event has no qualified type name (nil or anonymous type)")
ErrOutboxAnonymousEvent is returned by the default outbox mapping path when an event value has no resolvable type name (nil, or an anonymous type). Such events would otherwise be written with an empty type, which a relay cannot route. Provide a WithOutboxMapper to map anonymous events explicitly.
var ErrPaginationNeedsLimit = errors.New("drel: pagination requires Take/Limit to set the page size")
ErrPaginationNeedsLimit is returned when a pagination method is called without Take/Limit.
var ErrRawArgMismatch = errors.New("drel: raw predicate placeholder/argument count mismatch")
ErrRawArgMismatch is returned by RawErr when the number of ? placeholders in the raw SQL does not match the number of supplied arguments.
var ErrUnknownProjectionColumn = errors.New("drel: projected column has no matching DTO field (db tag)")
ErrUnknownProjectionColumn is returned by Select/GroupBy when a projected SQL column has no DTO field whose `db` tag matches it. Binding such a column would either error confusingly or, when types align, silently corrupt data, so drel fails loudly instead. Match it with errors.Is.
var SoftDeleteFilter = NamedFilter{ Name: "soft_delete", Clause: ast.WhereClause{ Comparison: &ast.ComparisonNode{Column: "deleted_at", Op: ast.OpIsNull}, }, }
Functions ¶
func ActorFromContext ¶
ActorFromContext extracts the actor identifier from the context, returning an empty string if none is set.
func Aggregate ¶ added in v0.3.0
Aggregate executes a single aggregate function and returns the scalar result. Accepts an engine-level *QueryBuilder[T] or a transaction-bound *TxQueryBuilder[T].
func ContextWithTx ¶ added in v0.6.0
ContextWithTx returns a copy of ctx that carries tx. WithTx calls it for you. Call it directly when you open the transaction yourself, for example in a test harness or in middleware that owns the transaction. Code below then finds the transaction with FromContext or MustFromContext, and a nested WithTx call joins it through a savepoint.
func EventTypeName ¶ added in v0.7.0
EventTypeName returns the package-qualified Go type name of an event value (PkgPath + "." + Name), unwrapping a pointer. The outbox and the event store name an event the same way, so one event carries one name everywhere.
It returns ErrOutboxAnonymousEvent for a nil value or an anonymous type, which have no name a consumer can route on.
func GroupBy ¶ added in v0.3.0
func GroupBy[R any, T any](ctx context.Context, q projectable[T], groups []GroupSpec, aggs []AliasedAgg, opts ...GroupByOpt) ([]*R, error)
GroupBy executes a GROUP BY query with aggregates, returning results as []*R. Accepts an engine-level *QueryBuilder[T] or a transaction-bound *TxQueryBuilder[T].
func InboxSchema ¶ added in v0.6.0
InboxSchema returns the CREATE TABLE DDL for an inbox table for the given dialect ("postgres" or "sqlite").
The primary key is the pair of message ID and handler name. A row with processed_at set is a committed success, and it blocks a new claim. A row with processed_at null only counts a failed attempt, and it does not block.
func JSONEqual ¶ added in v0.5.0
JSONEqual reports whether a and b marshal to identical JSON. It is used by generated diff code for JSON struct/non-comparable columns that have no cheap slices.Equal/maps.Equal form. On a marshal error it conservatively reports false so the change is recorded (a write is safer than silently skipping it).
func NormalizeIntKey ¶ added in v0.5.0
NormalizeIntKey collapses int64/int32 to int so pivot keys match an int PK.
func NormalizeUUIDKey ¶ added in v0.5.0
NormalizeUUIDKey converts a UUID primary-key value scanned as a raw driver type into a uuid.UUID so it compares equal to PKValue. It accepts uuid.UUID, [16]byte, []byte (16 bytes), and the canonical string form.
func OutboxSchema ¶ added in v0.3.0
OutboxSchema returns CREATE TABLE (and a partial index) DDL for an outbox table for the given dialect ("postgres" or "sqlite"). The payload column is TEXT for portability (JSON is stored as a string); processed_at is left for a relay to stamp.
The lease columns (claimed_by, claimed_until, attempts, last_error, dead_at) let more than one Relay replica poll one table without publishing a message two times. partition_key orders the publish inside one aggregate.
A partial index on open rows is emitted so the relay claim
SELECT id FROM <table> WHERE processed_at IS NULL AND dead_at IS NULL ORDER BY id;
uses an index seek rather than a sequential scan that grows with total outbox size (processed rows are typically retained for audit).
func RawQuery ¶ added in v0.3.0
RawQuery executes arbitrary SQL and scans results into []*T. Uses $1, $2 placeholder format — rewritten to ? for SQLite automatically.
IMPORTANT: results are bound to T's fields in struct-declaration order (the `db`-tagged fields, top to bottom), NOT by matching result-set column names. You MUST write the SELECT column list in the same order as T declares its tagged fields, or values land in the wrong fields. Unlike Select/GroupBy, which bind by name, RawQuery cannot inspect the result-set column names today.
func RawQueryRow ¶ added in v0.3.0
RawQueryRow executes arbitrary SQL expecting exactly one row, scanned into *T. Uses $1, $2 placeholder format — rewritten to ? for SQLite automatically.
IMPORTANT: like RawQuery, the single row is bound to T's fields in struct-declaration order, NOT by result-set column name. Order the SELECT columns to match T's tagged-field order.
func Select ¶ added in v0.3.0
Select executes a projection query, returning only specified columns into DTO type R. It accepts either an engine-level *QueryBuilder[T] or a transaction-bound *TxQueryBuilder[T]; in the latter case the projection runs inside the transaction.
func SetKeyGenerator ¶ added in v0.4.0
SetKeyGenerator overrides the key generator for a model at runtime. Setting a generator implies KeyAppAssigned. Pass nil to require app-supplied keys.
func SetKeyStrategy ¶ added in v0.4.0
func SetKeyStrategy[T any](meta ModelMeta[T], s KeyStrategy)
SetKeyStrategy overrides the key strategy for a model at runtime. It must be called before the model's repositories are used (typically at startup).
Types ¶
type AfterCommitHook ¶
type AggExpr ¶ added in v0.3.0
type AggExpr struct {
// contains filtered or unexported fields
}
AggExpr represents an aggregate function call.
func Count ¶ added in v0.5.0
func Count() AggExpr
Count is an alias for CountStar reading naturally as Count().
func CountCol ¶ added in v0.3.0
CountCol creates a COUNT aggregate expression for a specific column.
func CountDistinct ¶ added in v0.5.0
CountDistinct creates a COUNT(DISTINCT col) aggregate expression that counts the number of distinct non-NULL values in col.
type AliasedAgg ¶ added in v0.3.0
type AliasedAgg struct {
// contains filtered or unexported fields
}
AliasedAgg pairs an aggregate with a result alias.
func As ¶ added in v0.3.0
func As(alias string, agg AggExpr) AliasedAgg
As pairs an aggregate expression with a column alias for the result.
type Batch ¶ added in v0.3.0
type Batch struct {
// contains filtered or unexported fields
}
Batch groups multiple read queries so they execute in a single network round-trip when the driver supports pipelining (pgx), falling back to sequential execution otherwise. Queue queries with BatchAll/BatchFirst/ BatchCount, call Execute, then read each typed result via Result.
batch := db.NewBatch()
users := drel.BatchAll(batch, db.Users.Where(Users.Active.IsTrue()))
count := drel.BatchCount(batch, db.Users)
if err := batch.Execute(ctx); err != nil { ... }
us, _ := users.Result()
n, _ := count.Result()
A batch created with Engine.NewBatch pipelines on pgx (and runs sequentially on SQLite/libSQL). A batch created with Tx.NewBatch always runs sequentially on the transaction connection so it observes the transaction's uncommitted writes; a UnitOfWork batches the same way via the Tx it opens during a flush. Batch results are read-only and are NOT snapshotted into a change tracker: to mutate-and-save loaded entities, load them via Find/All/Include instead.
func (*Batch) Execute ¶ added in v0.3.0
Execute runs all queued queries. On a pipelining driver they are sent in one round-trip and their results read in order; otherwise they run sequentially. Execute drains every queued query even if an earlier one fails: each query's own error (and value) is stored on its BatchResult, so Result() faithfully reports per-query success or failure. If any query failed, Execute returns ErrBatchPartial wrapping the first failure; otherwise it returns nil.
type BatchResult ¶ added in v0.3.0
type BatchResult[T any] struct { // contains filtered or unexported fields }
BatchResult holds the typed outcome of a batched query, available after the batch has been executed.
func BatchAll ¶ added in v0.3.0
func BatchAll[T any](b *Batch, q *QueryBuilder[T]) *BatchResult[[]*T]
BatchAll queues a query returning all matching rows.
func BatchCount ¶ added in v0.3.0
func BatchCount[T any](b *Batch, q *QueryBuilder[T]) *BatchResult[int]
BatchCount queues a COUNT query.
func BatchFirst ¶ added in v0.3.0
func BatchFirst[T any](b *Batch, q *QueryBuilder[T]) *BatchResult[*T]
BatchFirst queues a query returning the first matching row; Result returns ErrNotFound if there is none.
func (*BatchResult[T]) Result ¶ added in v0.3.0
func (r *BatchResult[T]) Result() (T, error)
Result returns the query's result and any error encountered while scanning it.
type BoolColumn ¶
type BoolColumn struct {
// contains filtered or unexported fields
}
func NewBoolCol ¶
func NewBoolCol(name string) BoolColumn
func (BoolColumn) Asc ¶
func (c BoolColumn) Asc() OrderExpr
func (BoolColumn) ColRef ¶ added in v0.3.0
func (c BoolColumn) ColRef() ColumnRef
ColRef returns a ColumnRef for use with Select projections and aggregates.
func (BoolColumn) Desc ¶
func (c BoolColumn) Desc() OrderExpr
func (BoolColumn) Eq ¶
func (c BoolColumn) Eq(v bool) Predicate
func (BoolColumn) IsFalse ¶
func (c BoolColumn) IsFalse() Predicate
func (BoolColumn) IsNotNull ¶
func (c BoolColumn) IsNotNull() Predicate
func (BoolColumn) IsNull ¶
func (c BoolColumn) IsNull() Predicate
func (BoolColumn) IsTrue ¶
func (c BoolColumn) IsTrue() Predicate
func (BoolColumn) NEQ ¶
func (c BoolColumn) NEQ(v bool) Predicate
func (BoolColumn) Name ¶
func (c BoolColumn) Name() string
type ClaimedMessage ¶ added in v0.6.0
type ClaimedMessage struct {
ID int64
Type string
Payload []byte
PartitionKey string
// Attempts counts the claims of this message, this one included. The first
// delivery carries 1.
Attempts int
}
ClaimedMessage is one outbox row that a Relay holds a lease on.
type Column ¶
type Column[T any] struct { // contains filtered or unexported fields }
type ColumnRef ¶ added in v0.3.0
type ColumnRef struct {
// contains filtered or unexported fields
}
ColumnRef identifies a database column for use in Select projections.
type ComparableColumn ¶ added in v0.5.0
type ComparableColumn[T any] struct { // contains filtered or unexported fields }
ComparableColumn is a column type for values that support ordering but are not covered by the built-in numeric/string/time-specific column types — for example uuid.UUID, *time.Time, or custom value objects that implement a total order. It provides the full range-operator set (GT/GTE/LT/LTE/Between).
func NewComparableCol ¶ added in v0.5.0
func NewComparableCol[T any](name string) ComparableColumn[T]
func (ComparableColumn[T]) Asc ¶ added in v0.5.0
func (c ComparableColumn[T]) Asc() OrderExpr
func (ComparableColumn[T]) Between ¶ added in v0.5.0
func (c ComparableColumn[T]) Between(low, high T) Predicate
Between returns a predicate matching rows where the column value is between low and high inclusive (SQL BETWEEN low AND high).
func (ComparableColumn[T]) ColRef ¶ added in v0.5.0
func (c ComparableColumn[T]) ColRef() ColumnRef
func (ComparableColumn[T]) Desc ¶ added in v0.5.0
func (c ComparableColumn[T]) Desc() OrderExpr
func (ComparableColumn[T]) Eq ¶ added in v0.5.0
func (c ComparableColumn[T]) Eq(v T) Predicate
func (ComparableColumn[T]) GT ¶ added in v0.5.0
func (c ComparableColumn[T]) GT(v T) Predicate
func (ComparableColumn[T]) GTE ¶ added in v0.5.0
func (c ComparableColumn[T]) GTE(v T) Predicate
func (ComparableColumn[T]) In ¶ added in v0.5.0
func (c ComparableColumn[T]) In(vs ...T) Predicate
func (ComparableColumn[T]) IsNotNull ¶ added in v0.5.0
func (c ComparableColumn[T]) IsNotNull() Predicate
func (ComparableColumn[T]) IsNull ¶ added in v0.5.0
func (c ComparableColumn[T]) IsNull() Predicate
func (ComparableColumn[T]) LT ¶ added in v0.5.0
func (c ComparableColumn[T]) LT(v T) Predicate
func (ComparableColumn[T]) LTE ¶ added in v0.5.0
func (c ComparableColumn[T]) LTE(v T) Predicate
func (ComparableColumn[T]) NEQ ¶ added in v0.5.0
func (c ComparableColumn[T]) NEQ(v T) Predicate
func (ComparableColumn[T]) Name ¶ added in v0.5.0
func (c ComparableColumn[T]) Name() string
func (ComparableColumn[T]) NotIn ¶ added in v0.5.0
func (c ComparableColumn[T]) NotIn(vs ...T) Predicate
type CursorPage ¶ added in v0.3.0
type CursorPage[T any] struct { Items []*T NextCursor string // empty when there are no more results PreviousCursor string // empty when there is no previous page HasMore bool HasPrev bool }
CursorPage holds a page of results from keyset (cursor) pagination.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine holds a database driver and dialect for executing queries.
func NewEngine ¶
NewEngine creates a new Engine connected to the given DSN. The dialect and driver are auto-detected from the DSN unless overridden with WithDriver or WithDialect.
libSQL/Turso caveat: the websocket transport (ws:// or wss://) returns DATETIME columns as strings and corrupts time.Time scans (including created_at/updated_at). Prefer a libsql:// or https:// DSN for models with time.Time fields; NewEngine logs a warning when a ws://-scheme DSN is opened.
func (*Engine) ApplyMigrations ¶ added in v0.5.0
ApplyMigrations runs all pending up-migrations from dir against the engine's own connection pool, returning the number applied. It reuses the standard migration runner (tracking table + checksums), so it is safe to call against an in-memory SQLite engine — the migrations land in the same database the engine queries. The migration files must be written for the engine's dialect (see Engine.DialectName); this is the caller's responsibility.
func (*Engine) ApplyMigrationsFS ¶ added in v0.7.0
ApplyMigrationsFS applies the pending migrations of one or more embedded migration sets and returns how many it applied. Each feature slice embeds its own migrations with //go:embed, and drel merges the sets in version order, so the migrations run in the order they were written and not in the order the arguments appear.
//go:embed *.sql var FS embed.FS // generated in each module n, err := db.ApplyMigrationsFS(ctx, posts.FS, users.FS, billing.FS)
A version that appears in two modules is an error that names both files. Two slices generated in the same second, or on two branches, produce the same version, and there is no correct order between them.
The migration files must be written for the engine's dialect.
func (*Engine) Close ¶
func (e *Engine) Close()
Close shuts down the underlying database connection and any read replicas.
func (*Engine) DialectName ¶ added in v0.5.0
DialectName reports the engine's dialect: "postgres" or "sqlite". libSQL/Turso reuse the SQLite dialect, so they also report "sqlite".
func (*Engine) Exec ¶
Exec executes a raw SQL statement and returns the number of rows affected. $N placeholders are rewritten to ? on dialects that use ? (SQLite/libSQL).
func (*Engine) HealthCheck ¶ added in v0.5.0
HealthCheck pings the primary and every registered read replica, returning a joined error naming any unreachable endpoint. Wire it into a readiness probe (e.g. /readyz). A replica failure does not mask a primary failure: both are reported.
func (*Engine) NewBatch ¶ added in v0.3.0
NewBatch creates an empty query batch bound to this engine.
func (*Engine) OnAfterCommit ¶
func (e *Engine) OnAfterCommit(hook AfterCommitHook)
func (*Engine) OnBeforeCommit ¶
func (e *Engine) OnBeforeCommit(hook BeforeCommitHook)
func (*Engine) Ping ¶ added in v0.5.0
Ping verifies a working connection to the primary database. Wire it into a liveness probe (e.g. /healthz). It respects ctx cancellation/deadline.
func (*Engine) Query ¶
Query executes a raw SQL query and returns the result rows. The caller must close the returned Rows when done. $N placeholders are rewritten to ? on dialects that use ? (SQLite/libSQL).
func (*Engine) QueryRow ¶
QueryRow executes a raw SQL query that is expected to return at most one row. $N placeholders are rewritten to ? on dialects that use ? (SQLite/libSQL).
func (*Engine) Stats ¶ added in v0.5.0
Stats returns a snapshot of the primary connection pool's utilisation.
func (*Engine) Transaction ¶
func (e *Engine) Transaction(ctx context.Context, fn func(tx *Tx) error, opts ...TxOption) (retErr error)
Transaction runs fn inside a database transaction. If fn returns nil the transaction is committed; otherwise it is rolled back. Pending changes in the Tx change tracker are flushed automatically before commit.
func (*Engine) TransactionWithRetry ¶ added in v0.5.0
func (e *Engine) TransactionWithRetry(ctx context.Context, fn func(tx *Tx) error, opts ...TxOption) error
TransactionWithRetry runs fn in a transaction, re-running it on ErrSerializationFailure (deadlock / SQLSTATE 40001 / SQLITE_BUSY) up to MaxAttempts, with exponential backoff + jitter, honouring ctx cancellation between attempts. Configure the bounds with WithRetry; without it, defaults apply (3 attempts). Each attempt gets a fresh Tx and change tracker, so fn MUST rebuild any entities it adds/edits on every call — do not reuse entity pointers across attempts (see the savepoint in-memory caveat on Tx.Savepoint).
Any non-serialization error (or success) returns immediately.
func (*Engine) UseOutbox ¶ added in v0.3.0
func (e *Engine) UseOutbox(table string, opts ...OutboxOption)
UseOutbox writes domain events to a transactional outbox table on every SaveChanges, within the same transaction as the changes. The table must exist (see OutboxSchema) with at least (type, payload) columns; payload is stored as JSON text. Events are dispatched to after-commit handlers as usual in addition to being persisted.
func (*Engine) WithTx ¶ added in v0.6.0
func (e *Engine) WithTx(ctx context.Context, fn func(ctx context.Context) error, opts ...TxOption) error
WithTx runs fn inside a database transaction and puts that transaction in the context it passes to fn. Retrieve it with FromContext or MustFromContext.
The transaction commits when fn returns nil. It rolls back when fn returns an error or panics.
A nested WithTx call on the same engine reuses the transaction from the context and opens a savepoint. It does not begin a second transaction, and it does not commit. An error from the nested call rolls back to the savepoint only, and the outer call still decides the commit. A nested call returns ErrNestedTxOptions if it carries transaction options.
The behaviour is the same for Postgres, SQLite and LibSQL.
type EntityState ¶ added in v0.3.0
type EntityState int
EntityState describes a tracked entity's lifecycle state within a Tx.
const ( // StateUnchanged marks an entity with no pending changes. StateUnchanged EntityState = iota // StateAdded marks an entity to be INSERTed on the next flush. StateAdded // StateModified marks an entity to be UPDATEd on the next flush. StateModified // StateDeleted marks an entity to be deleted on the next flush. StateDeleted )
type EventRecorder ¶
type EventRecorder interface {
PendingEvents() []any
ClearEvents()
}
type FieldChange ¶
FieldChange represents a single column value that has changed on an entity.
type GroupByOpt ¶ added in v0.3.0
type GroupByOpt func(*groupByConfig)
GroupByOpt is an option for GroupBy queries.
func Having ¶ added in v0.3.0
func Having(pred Predicate) GroupByOpt
Having adds a HAVING clause to a GroupBy query.
type GroupSpec ¶ added in v0.3.0
type GroupSpec struct {
// contains filtered or unexported fields
}
GroupSpec specifies a GROUP BY column.
type Inbox ¶ added in v0.6.0
type Inbox struct {
// contains filtered or unexported fields
}
Inbox suppresses a duplicate delivery. A message broker delivers at least once, so one message can reach a handler more than one time. Claim writes a dedupe row inside the caller's transaction, next to the application write. The two therefore commit together, or neither commits.
The key is the pair of message ID and handler name. Two handlers can process one message. One handler cannot process one message two times.
func NewInbox ¶ added in v0.6.0
NewInbox creates an inbox on one table. The table must exist. InboxSchema emits it.
func (*Inbox) Claim ¶ added in v0.6.0
Claim writes the dedupe row for one message and one handler inside the transaction that WithTx put in ctx. Call it first in the handler, before the application write.
It returns ErrDuplicateMessage when the handler already processed the message. Acknowledge the message and stop.
It panics when ctx carries no transaction. A dedupe row outside the application transaction gives no protection at all, so this is a wiring fault and it must fail at once.
A handler that fails must roll the transaction back. The dedupe row then disappears with it, and the broker can deliver the message again. Record the failure with Fail after the rollback.
func (*Inbox) Fail ¶ added in v0.6.0
Fail records a failed attempt. Call it after the handler's transaction rolled back, so it runs on the engine and not on that transaction. The row it writes counts the attempt and holds the error. It does not block a later claim.
A message that the handler already processed is left alone, so a late error cannot reopen it.
func (*Inbox) Purge ¶ added in v0.6.0
Purge deletes the rows received before a time and returns the count. Run it on a schedule to hold the table small.
Purge only beyond the retention of the message broker. A purged row no longer suppresses its message, so an older delivery would run a second time.
type IncludableQuery ¶
type IncludableQuery[T any] struct { // contains filtered or unexported fields }
IncludableQuery constructs queries that eagerly load related entities. The root query may be refined with Where/OrderBy/Limit/Skip/Take exactly like a plain QueryBuilder; the configured relationships are loaded via split queries after the root result set is materialized.
func (*IncludableQuery[T]) All ¶
func (q *IncludableQuery[T]) All(ctx context.Context) ([]*T, error)
All returns all matching records (honoring Where/OrderBy/Limit) and loads included relationships.
func (*IncludableQuery[T]) Find ¶
func (q *IncludableQuery[T]) Find(ctx context.Context, id any) (*T, error)
Find looks up a single record by primary key and loads included relationships.
func (*IncludableQuery[T]) First ¶ added in v0.3.0
func (q *IncludableQuery[T]) First(ctx context.Context) (*T, error)
First returns the first matching record (honoring Where/OrderBy) and loads included relationships, or ErrNotFound if none match.
func (*IncludableQuery[T]) Include ¶ added in v0.3.0
func (q *IncludableQuery[T]) Include(rels ...IncludeSpec) *IncludableQuery[T]
Include adds more relationships to eagerly load.
func (*IncludableQuery[T]) Limit ¶ added in v0.3.0
func (q *IncludableQuery[T]) Limit(n int) *IncludableQuery[T]
Limit restricts the number of root records returned.
func (*IncludableQuery[T]) OrderBy ¶ added in v0.3.0
func (q *IncludableQuery[T]) OrderBy(exprs ...OrderExpr) *IncludableQuery[T]
OrderBy sets the ordering for the root query.
func (*IncludableQuery[T]) Primary ¶ added in v0.5.0
func (q *IncludableQuery[T]) Primary() *IncludableQuery[T]
Primary forces both the root query and all included sub-queries to read from the primary connection instead of a read replica. Use it for read-your-writes consistency immediately after a write. No effect when no replicas configured.
func (*IncludableQuery[T]) Skip ¶ added in v0.3.0
func (q *IncludableQuery[T]) Skip(n int) *IncludableQuery[T]
Skip sets the offset for the root query.
func (*IncludableQuery[T]) Take ¶ added in v0.3.0
func (q *IncludableQuery[T]) Take(n int) *IncludableQuery[T]
Take restricts the number of root records returned (alias for Limit).
func (*IncludableQuery[T]) Unscoped ¶ added in v0.3.0
func (q *IncludableQuery[T]) Unscoped() *IncludableQuery[T]
Unscoped removes all global filters from the root query.
func (*IncludableQuery[T]) Where ¶ added in v0.3.0
func (q *IncludableQuery[T]) Where(pred Predicate) *IncludableQuery[T]
Where adds a filter predicate to the root query.
func (*IncludableQuery[T]) WithoutFilter ¶ added in v0.3.0
func (q *IncludableQuery[T]) WithoutFilter(name string) *IncludableQuery[T]
WithoutFilter removes the named global filter from the root query.
type IncludeSpec ¶
type IncludeSpec struct {
// contains filtered or unexported fields
}
IncludeSpec wraps a RelationInfo for use with Include queries.
func NewIncludeSpec ¶
func NewIncludeSpec(rel *RelationInfo) IncludeSpec
NewIncludeSpec creates an IncludeSpec from a RelationInfo.
func (IncludeSpec) Limit ¶ added in v0.3.0
func (s IncludeSpec) Limit(n int) IncludeSpec
Limit returns a copy of the IncludeSpec that limits the number of related entities loaded per parent. For multi-parent loads this is enforced with a window function (ROW_NUMBER() partitioned by the foreign key); for a single parent it is a plain LIMIT.
func (IncludeSpec) OrderBy ¶ added in v0.3.0
func (s IncludeSpec) OrderBy(exprs ...OrderExpr) IncludeSpec
OrderBy returns a copy of the IncludeSpec with the given ordering applied to the related entities query.
func (IncludeSpec) Then ¶ added in v0.3.0
func (s IncludeSpec) Then(children ...IncludeSpec) IncludeSpec
Then returns a copy of the IncludeSpec that also eagerly loads the given relationships on the related entities, enabling nested includes such as Users.Posts.Then(Posts.Tags). The child specs describe relationships on the related model (here Post), and may themselves be nested with Then. Nested loading uses split queries on each level, so it never produces a cartesian product regardless of depth.
func (IncludeSpec) Unscoped ¶
func (s IncludeSpec) Unscoped() IncludeSpec
Unscoped returns a copy of the IncludeSpec that bypasses global filters (e.g. soft delete) when loading the related entities.
func (IncludeSpec) Where ¶ added in v0.3.0
func (s IncludeSpec) Where(pred Predicate) IncludeSpec
Where returns a copy of the IncludeSpec with an additional filter predicate applied to the related entities query.
func (IncludeSpec) WithoutFilter ¶ added in v0.3.0
func (s IncludeSpec) WithoutFilter(name string) IncludeSpec
WithoutFilter returns a copy of the IncludeSpec that drops the named global filter when loading the related entities (the others still apply).
type IsolationLevel ¶
type IsolationLevel int
IsolationLevel represents the transaction isolation level.
const ( // ReadCommitted is the default isolation level. ReadCommitted IsolationLevel = iota // RepeatableRead prevents non-repeatable reads. RepeatableRead // Serializable provides full serializability. Serializable )
type JSON ¶ added in v0.5.0
type JSON[T any] struct { V *T }
JSON is a generic adapter that maps a Go value of type T to a JSON-encoded database column (Postgres jsonb / SQLite TEXT). It implements driver.Valuer (marshals *V on write) and sql.Scanner (unmarshals into *V on read), so it round-trips on both pgx and database/sql without any reflection in the ORM.
Generated code wraps slice/map/struct columns as JSON{V: &p.Field}. V is a pointer so the value-receiver Scan can populate the underlying field.
type JoinOn ¶ added in v0.5.0
type JoinOn struct {
// contains filtered or unexported fields
}
JoinOn is a fully-qualified ON expression for a JOIN clause. It is produced by QualifiedCol.EqCol and consumed by QueryBuilder.LeftJoin/InnerJoin.
type KeyStrategy ¶ added in v0.4.0
type KeyStrategy uint8
KeyStrategy selects how a model's primary key is produced.
const ( // KeyAutoIncrement uses a database-generated key (SERIAL / AUTOINCREMENT) // read back after INSERT. This is the default for integer primary keys and // is the historical behavior. KeyAutoIncrement KeyStrategy = iota // KeyAppAssigned uses a key known before INSERT — generated by a registered // generator (e.g. UUIDv7) or set by application code. The key is written as // part of the INSERT and is never read back. KeyAppAssigned )
type Model ¶
type Model[K comparable] struct { // contains filtered or unexported fields }
func (*Model[K]) ClearEvents ¶
func (m *Model[K]) ClearEvents()
func (*Model[K]) PendingEvents ¶
func (*Model[K]) RecordEvent ¶
RecordEvent stages a domain event on the entity. Recorded events are dispatched (to after-commit handlers and any outbox) when the entity is persisted by SaveChanges — i.e. when it is inserted, updated, or deleted in that unit of work. Recording an event on an entity that is otherwise unchanged (no field mutation, not added or removed) does not, on its own, cause a flush, so its events are not dispatched until the entity is also mutated. Record events alongside the mutation that produced them.
func (*Model[K]) ScanPtrs ¶
ScanPtrs returns pointers to the base model fields for use in row scanning. Generated code calls this to obtain scan destinations for id, createdAt, and updatedAt without directly accessing unexported fields.
type ModelMeta ¶
type ModelMeta[T any] struct { Table string Columns []string PKColumn string Scan func(Row) (*T, error) Snapshot func(*T) any Diff func(*T, any) []FieldChange PKValue func(*T) any InsertColumns func(*T) ([]string, []any) ScanReturning func(*T, Row) error ScanGenerated func(*T, Row) error // scans created_at, updated_at only (app-assigned) KeyStrategy KeyStrategy GenerateKey func() any SetKey func(*T, any) KeyIsZero func(*T) bool ColumnValue func(*T, int) any // NormalizeKey converts a primary-key value scanned as a raw driver type // (e.g. [16]byte/string for a UUID, int64 for an integer) into the canonical // Go key type returned by PKValue, so pivot-table keys compare equal to it. // Optional; when nil the loader falls back to int normalization. NormalizeKey func(any) any Filters []NamedFilter HasSoftDelete bool HasVersioned bool HasAudit bool VersionValue func(*T) int SetVersion func(*T, int) AuditSetCreate func(*T, string) AuditSetUpdate func(*T, string) }
ModelMeta describes the database mapping for a model type T.
type ModelMetaBase ¶
type ModelMetaBase struct {
Table string
Columns []string
PKColumn string
Snapshot func(entity any) any
Diff func(entity any, snapshot any) []FieldChange
PKValue func(entity any) any
InsertColumns func(entity any) ([]string, []any)
ScanRow func(Row) (any, error)
ScanReturning func(entity any, row Row) error
ScanGenerated func(entity any, row Row) error
KeyStrategy KeyStrategy
GenerateKey func() any
SetKey func(entity any, key any)
KeyIsZero func(entity any) bool
ColumnValue func(entity any, colIdx int) any
HasSoftDelete bool
HasVersioned bool
HasAudit bool
VersionValue func(entity any) int
SetVersion func(entity any, v int)
AuditSetCreate func(entity any, actor string)
AuditSetUpdate func(entity any, actor string)
Filters []NamedFilter
NormalizeKey func(any) any
}
ModelMetaBase is the type-erased version of ModelMeta[T], used internally by the change tracker and relationship loading infrastructure.
func ToMetaBase ¶
func ToMetaBase[T any](meta *ModelMeta[T]) *ModelMetaBase
ToMetaBase converts a typed ModelMeta[T] to a type-erased ModelMetaBase.
type MultiColumnMapper ¶
type MultiColumnMapper interface {
DrelColumns() []string
DrelValues() ([]any, error)
DrelScanMulti(vals []any) error
}
MultiColumnMapper is implemented by value objects that map to multiple database columns (e.g., Money → amount + currency).
type NamedFilter ¶
type NamedFilter struct {
Name string
Clause ast.WhereClause
}
type OffsetPage ¶ added in v0.3.0
type OffsetPage[T any] struct { Items []*T Total int Page int // 1-based page number PageSize int TotalPages int HasMore bool }
OffsetPage holds a page of results from offset-based pagination.
type Option ¶
type Option func(*engineConfig)
Option configures Engine creation.
func WithAfterCommitErrorSink ¶ added in v0.5.0
WithAfterCommitErrorSink registers a callback that receives errors and recovered panics from after-commit hooks. After-commit hooks run after the commit has already succeeded, so their failures cannot roll back the transaction — durable side-effects belong in the outbox. The sink is the only signal for such failures; if unset they are dropped. The sink itself is recovered, so a panicking sink cannot crash the caller.
func WithAuthToken ¶ added in v0.3.0
WithAuthToken sets the authentication token for a libSQL/Turso connection. It is appended to the DSN as the authToken query parameter.
Prefer a libsql:// or https:// DSN over ws://wss:// — the websocket transport corrupts time.Time columns (see NewEngine).
func WithConnMaxIdleTime ¶ added in v0.3.2
WithConnMaxIdleTime sets how long a connection may sit idle before being closed.
func WithConnMaxLifetime ¶ added in v0.3.2
WithConnMaxLifetime sets the maximum lifetime of a pooled connection before it is recycled (useful behind connection poolers / for failover).
func WithContext ¶
WithContext sets the context used during engine creation.
func WithDevMode ¶ added in v0.3.0
func WithDevMode() Option
WithDevMode enables development-time diagnostics: warnings for unbounded queries (SELECT without LIMIT), likely N+1 access patterns (the same query shape executed repeatedly in a short window), slow queries, and tracked entities that were loaded but never modified. Do not enable in production.
func WithDialect ¶ added in v0.3.0
WithDialect overrides the SQL dialect used by the engine. When set, auto-detection is skipped for the dialect.
func WithDriver ¶ added in v0.3.0
WithDriver overrides the driver used by the engine. When set, auto-detection is skipped for the driver.
func WithLogger ¶ added in v0.3.0
WithLogger attaches a structured logger. Combined with WithQueryLog, WithSlowQueryThreshold, or WithDevMode it emits query and diagnostic logs.
func WithMaxConns ¶ added in v0.3.2
WithMaxConns sets the maximum number of open database connections in the pool.
func WithQueryLog ¶ added in v0.3.0
WithQueryLog logs every executed query (SQL, arg count, duration) at debug level. Requires a logger (WithLogger); if none is set, slog.Default is used.
func WithQueryTimeout ¶ added in v0.5.0
WithQueryTimeout sets a default deadline applied to every engine-level query and exec that does not already carry a shorter deadline. Zero (the default) means no default timeout. It composes with caller-supplied deadlines — the shorter one wins. Per-builder .Timeout(d) overrides this default for that query. The default is NOT auto-applied to queries issued inside an explicit Tx, because a timeout firing mid-transaction aborts the whole transaction; use .Timeout(d) explicitly there if you accept that semantics.
func WithReadReplica ¶ added in v0.3.0
WithReadReplica registers a read replica. Read queries issued through repositories (not within a transaction, and not forced to Primary) are routed round-robin across all registered replicas; writes and transactions always go to the primary.
func WithSimpleProtocol ¶ added in v0.5.0
func WithSimpleProtocol() Option
WithSimpleProtocol makes the Postgres driver use pgx's simple query protocol (no server-side prepared statements), required for PgBouncer transaction or statement pooling. It is a no-op for SQLite and libSQL/Turso. The equivalent DSN escape hatch is "?default_query_exec_mode=simple_protocol".
func WithSlowQueryThreshold ¶ added in v0.3.0
WithSlowQueryThreshold logs a warning for any query whose execution exceeds d.
func WithTracer ¶ added in v0.3.0
WithTracer emits an OpenTelemetry-style span per executed query.
type OrderExpr ¶
type OrderExpr struct {
// contains filtered or unexported fields
}
func (OrderExpr) NullsFirst ¶ added in v0.5.0
NullsFirst orders NULL values before non-NULL values. Chain after Asc()/Desc(). Pin this explicitly when paging over a nullable column so NULL rows are not silently dropped from cursor pages.
func (OrderExpr) NullsLast ¶ added in v0.5.0
NullsLast orders NULL values after non-NULL values. Chain after Asc()/Desc().
func (OrderExpr) ToAST ¶
func (o OrderExpr) ToAST() ast.OrderByExpr
type OrderedColumn ¶
func NewOrderedCol ¶
func NewOrderedCol[T cmp.Ordered](name string) OrderedColumn[T]
func (OrderedColumn[T]) Asc ¶
func (c OrderedColumn[T]) Asc() OrderExpr
func (OrderedColumn[T]) Between ¶
func (c OrderedColumn[T]) Between(low, high T) Predicate
func (OrderedColumn[T]) ColRef ¶ added in v0.3.0
func (c OrderedColumn[T]) ColRef() ColumnRef
ColRef returns a ColumnRef for use with Select projections and aggregates.
func (OrderedColumn[T]) Desc ¶
func (c OrderedColumn[T]) Desc() OrderExpr
func (OrderedColumn[T]) Eq ¶
func (c OrderedColumn[T]) Eq(v T) Predicate
func (OrderedColumn[T]) GT ¶
func (c OrderedColumn[T]) GT(v T) Predicate
func (OrderedColumn[T]) GTE ¶
func (c OrderedColumn[T]) GTE(v T) Predicate
func (OrderedColumn[T]) In ¶
func (c OrderedColumn[T]) In(vs ...T) Predicate
func (OrderedColumn[T]) IsNotNull ¶
func (c OrderedColumn[T]) IsNotNull() Predicate
func (OrderedColumn[T]) IsNull ¶
func (c OrderedColumn[T]) IsNull() Predicate
func (OrderedColumn[T]) LT ¶
func (c OrderedColumn[T]) LT(v T) Predicate
func (OrderedColumn[T]) LTE ¶
func (c OrderedColumn[T]) LTE(v T) Predicate
func (OrderedColumn[T]) NEQ ¶
func (c OrderedColumn[T]) NEQ(v T) Predicate
func (OrderedColumn[T]) Name ¶
func (c OrderedColumn[T]) Name() string
func (OrderedColumn[T]) NotIn ¶
func (c OrderedColumn[T]) NotIn(vs ...T) Predicate
type OutboxMessage ¶ added in v0.3.0
OutboxMessage is a row written to the transactional outbox. Type identifies the event kind; Payload is JSON-serialized into the outbox table's payload column. Messages are written within the same transaction as the changes that produced the events, giving exactly-once hand-off to an external relay (Debezium CDC, a polling worker, etc.). PartitionKey orders the relay publish. Messages that carry the same key are published in id order. Messages with different keys can go in parallel. Leave it empty when the message needs no order; the column then stays NULL.
type OutboxOption ¶ added in v0.3.0
type OutboxOption func(*outboxConfig)
OutboxOption configures UseOutbox.
func WithOutboxMapper ¶ added in v0.3.0
func WithOutboxMapper(fn func(event any) (OutboxMessage, bool)) OutboxOption
WithOutboxMapper customizes how domain events are mapped to outbox messages. Return ok=false to skip an event. The default maps every event to a message whose Type is the event's package-qualified Go type name (PkgPath + "." + Name, e.g. "github.com/acme/orders.OrderPlaced") and whose Payload is the event itself. The qualified name avoids cross-package collisions in the feature-slice layout where two packages may each define an "OrderPlaced".
type PoolStats ¶ added in v0.5.0
PoolStats is a dialect-neutral snapshot of connection-pool utilisation, suitable for a metrics endpoint. AcquiredConns is the number of connections currently in use; IdleConns are available; TotalConns is the sum currently held; MaxConns is the configured ceiling (0 means driver default).
type Predicate ¶
type Predicate struct {
// contains filtered or unexported fields
}
func Raw ¶
Raw creates a predicate from a raw SQL expression with bound arguments. Use ? as placeholder for each argument; they are rewritten to $N for Postgres. Placeholder counting is quote-aware: a '?' inside a single-quoted string, double-quoted identifier, or dollar-quoted region is not a placeholder. Panics if the number of placeholders does not match the number of arguments; use RawErr for a non-panicking variant.
func RawErr ¶ added in v0.5.0
RawErr is like Raw but returns an error wrapping ErrRawArgMismatch on a placeholder/argument-count mismatch instead of panicking. Use it when the raw SQL or its argument list is built dynamically and a mismatch is recoverable.
func True ¶ added in v0.5.0
func True() Predicate
True returns a no-op predicate that always matches. It is the identity for And and contributes nothing to a WHERE clause, so Where(True()) emits no WHERE at all. Use it as the "else" branch of conditional filtering.
func WhereIf ¶ added in v0.5.0
WhereIf returns pred when cond is true, otherwise a no-op (always-true) predicate that contributes nothing to the WHERE clause. It makes conditional filtering first-class instead of forcing callers to construct zero Predicate{} values or hand-rolled if/else chains around the builder.
func (Predicate) ToAST ¶
func (p Predicate) ToAST() ast.WhereClause
type Publisher ¶ added in v0.6.0
type Publisher interface {
Publish(ctx context.Context, msg ClaimedMessage) error
}
Publisher hands a claimed message to the transport. The host implements it. A nil error marks the message processed. An error records the failure and leaves the message for another attempt.
type PublisherFunc ¶ added in v0.6.0
type PublisherFunc func(ctx context.Context, msg ClaimedMessage) error
PublisherFunc adapts a function to the Publisher interface.
func (PublisherFunc) Publish ¶ added in v0.6.0
func (f PublisherFunc) Publish(ctx context.Context, msg ClaimedMessage) error
Publish calls f.
type QualifiedCol ¶ added in v0.5.0
type QualifiedCol struct {
// contains filtered or unexported fields
}
QualifiedCol is a table-qualified column reference (table.column) used to build JOIN ON expressions and cross-table projections.
func QualifiedColRef ¶ added in v0.5.0
func QualifiedColRef(table, column string) QualifiedCol
QualifiedColRef creates a table-qualified column reference.
func (QualifiedCol) EqCol ¶ added in v0.5.0
func (q QualifiedCol) EqCol(other QualifiedCol) JoinOn
EqCol builds an equality ON expression between two qualified columns, with each identifier segment quoted (e.g. "categories"."name" = "products"."category").
func (QualifiedCol) Qualified ¶ added in v0.5.0
func (q QualifiedCol) Qualified() string
Qualified returns the raw "table.column" string.
func (QualifiedCol) Ref ¶ added in v0.5.0
func (q QualifiedCol) Ref() ColumnRef
Ref returns a ColumnRef whose name is the qualified "table.column" string, for use as a Select projection column. The dialect quotes each segment.
type QueryBuilder ¶
type QueryBuilder[T any] struct { // contains filtered or unexported fields }
QueryBuilder constructs and executes typed queries with an immutable builder pattern.
func (*QueryBuilder[T]) After ¶ added in v0.3.0
func (q *QueryBuilder[T]) After(cursor string) *QueryBuilder[T]
After positions a cursor-paginated query immediately past the row encoded by the cursor (as returned in a prior CursorPage.NextCursor). Combine with OrderBy and Take, then call Page.
func (*QueryBuilder[T]) All ¶
func (q *QueryBuilder[T]) All(ctx context.Context) ([]*T, error)
All executes the query and returns all matching results.
func (*QueryBuilder[T]) AllRows ¶ added in v0.5.0
func (q *QueryBuilder[T]) AllRows() *QueryBuilder[T]
AllRows opts a BulkUpdate or BulkDelete out of the full-table safety guard, permitting a deliberate whole-table write with no Where predicate.
func (*QueryBuilder[T]) Before ¶ added in v0.5.0
func (q *QueryBuilder[T]) Before(cursor string) *QueryBuilder[T]
Before positions a cursor-paginated query immediately before the row encoded by the cursor, walking backward. Mutually exclusive with After. Combine with OrderBy and Take, then call Page; results are returned in natural (forward) order with PreviousCursor/HasPrev set for further backward navigation.
func (*QueryBuilder[T]) BulkDelete ¶
func (q *QueryBuilder[T]) BulkDelete(ctx context.Context) (int, error)
BulkDelete deletes all rows matching the builder's WHERE conditions. If the model has soft delete, it performs a soft delete instead. Returns the number of affected rows.
func (*QueryBuilder[T]) BulkUpdate ¶
BulkUpdate updates all rows matching the builder's WHERE conditions. Returns the number of affected rows.
func (*QueryBuilder[T]) Count ¶
func (q *QueryBuilder[T]) Count(ctx context.Context) (int, error)
Count returns the number of matching rows.
func (*QueryBuilder[T]) Distinct ¶ added in v0.5.0
func (q *QueryBuilder[T]) Distinct() *QueryBuilder[T]
Distinct makes the projection emit SELECT DISTINCT, de-duplicating result rows. It affects Select and GroupBy projections; it has no effect on All/First/Count/Exists.
func (*QueryBuilder[T]) Exists ¶
func (q *QueryBuilder[T]) Exists(ctx context.Context) (bool, error)
Exists returns true if at least one matching row exists.
func (*QueryBuilder[T]) First ¶
func (q *QueryBuilder[T]) First(ctx context.Context) (*T, error)
First returns the first matching result or ErrNotFound if none exist.
func (*QueryBuilder[T]) FirstOrNil ¶
func (q *QueryBuilder[T]) FirstOrNil(ctx context.Context) (*T, error)
FirstOrNil returns the first matching result or nil if none exist.
func (*QueryBuilder[T]) InnerJoin ¶ added in v0.5.0
func (q *QueryBuilder[T]) InnerJoin(table string, on JoinOn) *QueryBuilder[T]
InnerJoin adds an INNER JOIN to the given table on the supplied ON expression. See LeftJoin for column-qualification requirements.
func (*QueryBuilder[T]) LeftJoin ¶ added in v0.5.0
func (q *QueryBuilder[T]) LeftJoin(table string, on JoinOn) *QueryBuilder[T]
LeftJoin adds a LEFT JOIN to the given table on the supplied ON expression. Projection columns from the joined table must be table-qualified via QualifiedColRef(...).Ref(). Joins affect Select and GroupBy projections only.
func (*QueryBuilder[T]) Limit ¶
func (q *QueryBuilder[T]) Limit(n int) *QueryBuilder[T]
Limit restricts the number of results returned.
func (*QueryBuilder[T]) OrderBy ¶
func (q *QueryBuilder[T]) OrderBy(exprs ...OrderExpr) *QueryBuilder[T]
OrderBy sets the ordering for the query.
func (*QueryBuilder[T]) Page ¶ added in v0.3.0
func (q *QueryBuilder[T]) Page(ctx context.Context) (*CursorPage[T], error)
Page executes a keyset (cursor) page query. OrderBy is required and Take must be > 0. Any Skip/offset on the builder is ignored (keyset and OFFSET are mutually exclusive). When After is set the page begins past that cursor; when Before is set it walks backward and results are returned in natural order. Paging over a nullable ordering column requires NullsFirst()/NullsLast() on that column, otherwise Page returns ErrCursorColumnNullable.
func (*QueryBuilder[T]) PageOffset ¶ added in v0.3.0
func (q *QueryBuilder[T]) PageOffset(ctx context.Context) (*OffsetPage[T], error)
PageOffset executes an offset-based page query. Take (or Limit) sets the page size and Skip sets the offset. It runs a COUNT to populate Total/TotalPages.
func (*QueryBuilder[T]) Primary ¶ added in v0.3.0
func (q *QueryBuilder[T]) Primary() *QueryBuilder[T]
Primary forces this query to read from the primary connection instead of a read replica. Has no effect when no replicas are configured.
func (*QueryBuilder[T]) Skip ¶
func (q *QueryBuilder[T]) Skip(n int) *QueryBuilder[T]
Skip sets the offset for the query (number of rows to skip).
func (*QueryBuilder[T]) Take ¶ added in v0.3.0
func (q *QueryBuilder[T]) Take(n int) *QueryBuilder[T]
Take limits the number of results returned. It is an alias for Limit that reads naturally alongside Skip/After in pagination expressions.
func (*QueryBuilder[T]) Timeout ¶ added in v0.5.0
func (q *QueryBuilder[T]) Timeout(d time.Duration) *QueryBuilder[T]
Timeout overrides the engine's default query timeout for this query only. The shorter of this value and any caller-supplied context deadline wins. Pass a non-positive duration to disable any default for this query.
func (*QueryBuilder[T]) Unscoped ¶
func (q *QueryBuilder[T]) Unscoped() *QueryBuilder[T]
Unscoped returns a new builder with all global filters removed.
func (*QueryBuilder[T]) Where ¶
func (q *QueryBuilder[T]) Where(pred Predicate) *QueryBuilder[T]
Where adds a filter predicate. Multiple calls are ANDed together.
func (*QueryBuilder[T]) WithoutFilter ¶
func (q *QueryBuilder[T]) WithoutFilter(name string) *QueryBuilder[T]
WithoutFilter returns a new builder with the named filter removed.
type QueryEvent ¶
QueryEvent contains information about an executed query.
type QueryHook ¶
type QueryHook func(ctx context.Context, event QueryEvent)
QueryHook is called after every query execution.
type RawExpr ¶
type RawExpr struct {
SQL string
}
RawExpr represents a raw SQL expression to embed in a query (e.g., NOW()).
type Relation ¶
type Relation[T any] struct { // contains filtered or unexported fields }
func NewRelation ¶
type RelationInfo ¶
type RelationInfo struct {
Name string
Type RelationType
FKColumn string
JoinTable string // pivot table name (many-to-many only)
RefColumn string // target FK column in pivot table (many-to-many only)
RelatedMeta *ModelMetaBase
FieldSetter func(parent any, related any)
}
RelationInfo describes a relationship between two models.
type RelationType ¶
type RelationType int
RelationType describes the kind of relationship between two models.
const ( // HasMany indicates the parent has many related entities (1:N). HasMany RelationType = iota // HasOne indicates the parent has one related entity (1:1). HasOne // BelongsTo indicates the entity references a parent via a foreign key. BelongsTo // ManyToMany indicates a many-to-many relationship via a pivot table. ManyToMany )
type Relay ¶ added in v0.6.0
type Relay struct {
// contains filtered or unexported fields
}
Relay publishes outbox messages to a transport and marks them processed.
More than one replica can run a Relay against one table. A claim takes a lease on a batch of messages, so a second replica skips the messages that the first one holds. Postgres claims with FOR UPDATE SKIP LOCKED. SQLite and LibSQL claim with a conditional UPDATE, which is safe because SQLite serialises writers.
Delivery is at-least-once, not exactly-once. A publish that outlives its lease can run a second time on another replica. Make the transport or the consumer idempotent.
Every replica must run a synchronised clock. The lease compares the times that the replicas write.
func NewRelay ¶ added in v0.6.0
func NewRelay(e *Engine, table string, pub Publisher, opts ...RelayOption) *Relay
NewRelay creates a relay for one outbox table. The table must carry the lease columns that OutboxSchema emits.
func (*Relay) Run ¶ added in v0.6.0
Run polls the outbox until ctx ends. It returns the context error.
Run polls again at once after a full batch, and it waits for the poll interval after a short batch. A claim or publish error does not stop the loop. Run reports the error through the engine's error hooks and continues.
type RelayOption ¶ added in v0.6.0
type RelayOption func(*relayConfig)
RelayOption configures a Relay.
func WithRelayBatchSize ¶ added in v0.6.0
func WithRelayBatchSize(n int) RelayOption
WithRelayBatchSize sets how many messages one claim takes. The default is 100.
func WithRelayConcurrency ¶ added in v0.6.0
func WithRelayConcurrency(n int) RelayOption
WithRelayConcurrency limits how many partitions publish at the same time. The default is 8.
func WithRelayLease ¶ added in v0.6.0
func WithRelayLease(d time.Duration) RelayOption
WithRelayLease sets how long a claim holds a message. Another replica can claim the message again after the lease ends. Set it well above the time one publish takes. The default is 30 seconds.
func WithRelayMaxAttempts ¶ added in v0.6.0
func WithRelayMaxAttempts(n int) RelayOption
WithRelayMaxAttempts sets how many claims a message gets before the relay marks it dead. The default is 5. A value below 1 disables the dead-letter path, and the relay retries forever.
func WithRelayOnDead ¶ added in v0.6.0
func WithRelayOnDead(fn func(ctx context.Context, msg ClaimedMessage, err error)) RelayOption
WithRelayOnDead registers a callback that runs one time for each message that reaches the attempt limit. Use it to alert a person. The callback must not block for long.
func WithRelayOnError ¶ added in v0.6.0
func WithRelayOnError(fn func(ctx context.Context, err error)) RelayOption
WithRelayOnError registers a callback for an error that Run cannot return, because Run only ends when the context ends. Without this option Run logs the error through the engine logger at error level. Register it in production, so that a claim failure or a publish failure reaches your alerting.
func WithRelayPollInterval ¶ added in v0.6.0
func WithRelayPollInterval(d time.Duration) RelayOption
WithRelayPollInterval sets the wait between two empty polls. The default is one second. Run polls again at once after a full batch.
func WithRelayWorkerID ¶ added in v0.6.0
func WithRelayWorkerID(id string) RelayOption
WithRelayWorkerID names this replica in the claimed_by column. The default is the host name and the process ID.
type Repository ¶
type Repository[T any] struct { // contains filtered or unexported fields }
Repository provides typed query access for a specific model.
func NewRepository ¶
func NewRepository[T any](engine *Engine, meta ModelMeta[T]) *Repository[T]
NewRepository creates a new Repository for the given model metadata.
func (*Repository[T]) After ¶ added in v0.3.0
func (r *Repository[T]) After(cursor string) *QueryBuilder[T]
After starts a cursor-paginated query positioned past the given cursor.
func (*Repository[T]) All ¶
func (r *Repository[T]) All(ctx context.Context) ([]*T, error)
All returns all records for this model.
func (*Repository[T]) AllRows ¶ added in v0.5.0
func (r *Repository[T]) AllRows() *QueryBuilder[T]
AllRows opts a BulkUpdate or BulkDelete started from this repository out of the full-table safety guard, permitting a deliberate whole-table write with no Where predicate.
func (*Repository[T]) Before ¶ added in v0.5.0
func (r *Repository[T]) Before(cursor string) *QueryBuilder[T]
Before starts a cursor-paginated query positioned before the given cursor (backward).
func (*Repository[T]) BulkInsert ¶
func (r *Repository[T]) BulkInsert(ctx context.Context, entities []*T) (int, error)
BulkInsert inserts multiple entities in batches, bypassing change tracking. Returns the total number of rows affected.
IMPORTANT: BulkInsert is a fast path that opens its own transaction and does NOT go through the change tracker. Domain events recorded on the entities (RecordEvent) are NOT collected, NOT written to the outbox, and NOT dispatched to before/after-commit hooks. Use SaveChanges (Engine.Transaction or a UnitOfWork) when you need event dispatch, or BulkInsertWithEvents to persist events through the outbox path inside the bulk transaction.
func (*Repository[T]) BulkInsertWithEvents ¶ added in v0.5.0
func (r *Repository[T]) BulkInsertWithEvents(ctx context.Context, entities []*T) (int, error)
BulkInsertWithEvents inserts multiple entities in batches like BulkInsert, but additionally collects domain events recorded on the entities (RecordEvent), runs the engine's registered OnBeforeCommit hooks (e.g. the outbox writer from UseOutbox) inside the same transaction so event persistence commits atomically with the inserted rows, and dispatches the events to after-commit hooks once the transaction commits. Change tracking is still bypassed; this is a targeted opt-in for event delivery on the bulk path.
func (*Repository[T]) BulkUpsert ¶
func (r *Repository[T]) BulkUpsert(ctx context.Context, entities []*T, opts ...UpsertOption) (int, error)
func (*Repository[T]) Count ¶
func (r *Repository[T]) Count(ctx context.Context) (int, error)
Count returns the total number of records for this model.
func (*Repository[T]) Distinct ¶ added in v0.5.0
func (r *Repository[T]) Distinct() *QueryBuilder[T]
Distinct returns a query builder with SELECT DISTINCT enabled.
func (*Repository[T]) Exists ¶
func (r *Repository[T]) Exists(ctx context.Context) (bool, error)
Exists returns true if any records exist for this model.
func (*Repository[T]) Find ¶
func (r *Repository[T]) Find(ctx context.Context, id any) (*T, error)
Find looks up a single record by its primary key.
func (*Repository[T]) First ¶
func (r *Repository[T]) First(ctx context.Context) (*T, error)
First returns the first record or ErrNotFound.
func (*Repository[T]) FirstOrNil ¶
func (r *Repository[T]) FirstOrNil(ctx context.Context) (*T, error)
FirstOrNil returns the first record or nil.
func (*Repository[T]) Include ¶
func (r *Repository[T]) Include(rels ...IncludeSpec) *IncludableQuery[T]
Include begins a query that will eagerly load the given relationships.
func (*Repository[T]) InnerJoin ¶ added in v0.5.0
func (r *Repository[T]) InnerJoin(table string, on JoinOn) *QueryBuilder[T]
InnerJoin returns a query builder with an INNER JOIN added.
func (*Repository[T]) LeftJoin ¶ added in v0.5.0
func (r *Repository[T]) LeftJoin(table string, on JoinOn) *QueryBuilder[T]
LeftJoin returns a query builder with a LEFT JOIN added.
func (*Repository[T]) Limit ¶
func (r *Repository[T]) Limit(n int) *QueryBuilder[T]
Limit starts a query with a row limit.
func (*Repository[T]) OrderBy ¶
func (r *Repository[T]) OrderBy(exprs ...OrderExpr) *QueryBuilder[T]
OrderBy starts an ordered query.
func (*Repository[T]) Primary ¶ added in v0.3.0
func (r *Repository[T]) Primary() *QueryBuilder[T]
Primary returns a query builder that reads from the primary connection, bypassing read replicas (useful for read-your-writes consistency).
func (*Repository[T]) Skip ¶ added in v0.3.0
func (r *Repository[T]) Skip(n int) *QueryBuilder[T]
Skip starts a query with a row offset.
func (*Repository[T]) Take ¶ added in v0.3.0
func (r *Repository[T]) Take(n int) *QueryBuilder[T]
Take starts a query with a row limit (alias for Limit, reads naturally with pagination).
func (*Repository[T]) Unscoped ¶
func (r *Repository[T]) Unscoped() *QueryBuilder[T]
Unscoped returns a query builder with all global filters removed.
func (*Repository[T]) Where ¶
func (r *Repository[T]) Where(pred Predicate) *QueryBuilder[T]
Where starts a filtered query.
func (*Repository[T]) WithoutFilter ¶
func (r *Repository[T]) WithoutFilter(name string) *QueryBuilder[T]
WithoutFilter returns a query builder with the named filter removed.
type RetryConfig ¶ added in v0.5.0
type RetryConfig struct {
// MaxAttempts is the total number of tries, including the first. <=0 means 3.
MaxAttempts int
// BaseDelay is the first backoff delay; subsequent delays grow exponentially.
// <=0 means 50ms.
BaseDelay time.Duration
// MaxDelay caps the backoff delay. <=0 means 1s.
MaxDelay time.Duration
}
RetryConfig bounds serialization-failure retries for TransactionWithRetry. Zero fields fall back to sensible defaults (3 attempts, 50ms base delay growing exponentially with jitter, capped at 1s).
type SoftDelete ¶
type SoftDelete struct {
// contains filtered or unexported fields
}
func (SoftDelete) DeletedAt ¶
func (s SoftDelete) DeletedAt() *time.Time
func (*SoftDelete) DeletedAtPtr ¶
func (s *SoftDelete) DeletedAtPtr() **time.Time
func (SoftDelete) IsDeleted ¶
func (s SoftDelete) IsDeleted() bool
type Span ¶ added in v0.3.0
type Span interface {
End()
RecordError(err error)
}
Span is a minimal tracing span. It is satisfied by a thin adapter over any tracing library (e.g. OpenTelemetry), keeping drel free of tracing dependencies. End is called when the traced operation completes; RecordError attaches an error to the span (a nil error is ignored).
type StringColumn ¶
type StringColumn struct {
// contains filtered or unexported fields
}
func NewStringCol ¶
func NewStringCol(name string) StringColumn
func (StringColumn) Asc ¶
func (c StringColumn) Asc() OrderExpr
func (StringColumn) ColRef ¶ added in v0.3.0
func (c StringColumn) ColRef() ColumnRef
ColRef returns a ColumnRef for use with Select projections and aggregates.
func (StringColumn) Contains ¶
func (c StringColumn) Contains(substr string) Predicate
func (StringColumn) Desc ¶
func (c StringColumn) Desc() OrderExpr
func (StringColumn) Eq ¶
func (c StringColumn) Eq(v string) Predicate
func (StringColumn) GT ¶
func (c StringColumn) GT(v string) Predicate
func (StringColumn) GTE ¶
func (c StringColumn) GTE(v string) Predicate
func (StringColumn) HasPrefix ¶
func (c StringColumn) HasPrefix(prefix string) Predicate
func (StringColumn) HasSuffix ¶
func (c StringColumn) HasSuffix(suffix string) Predicate
func (StringColumn) ILike ¶
func (c StringColumn) ILike(pattern string) Predicate
func (StringColumn) In ¶
func (c StringColumn) In(vs ...string) Predicate
func (StringColumn) IsNotNull ¶
func (c StringColumn) IsNotNull() Predicate
func (StringColumn) IsNull ¶
func (c StringColumn) IsNull() Predicate
func (StringColumn) LT ¶
func (c StringColumn) LT(v string) Predicate
func (StringColumn) LTE ¶
func (c StringColumn) LTE(v string) Predicate
func (StringColumn) Like ¶
func (c StringColumn) Like(pattern string) Predicate
func (StringColumn) NEQ ¶
func (c StringColumn) NEQ(v string) Predicate
func (StringColumn) Name ¶
func (c StringColumn) Name() string
func (StringColumn) NotIn ¶
func (c StringColumn) NotIn(vs ...string) Predicate
type TimeColumn ¶ added in v0.5.0
type TimeColumn struct {
// contains filtered or unexported fields
}
TimeColumn is a dedicated column type for time.Time values. It provides range operators (GT/GTE/LT/LTE/Between/Before/After) in addition to the standard equality/null/in operators available on Column[T].
func NewTimeCol ¶ added in v0.5.0
func NewTimeCol(name string) TimeColumn
func (TimeColumn) After ¶ added in v0.5.0
func (c TimeColumn) After(t time.Time) Predicate
After is a convenience alias for GT.
func (TimeColumn) Asc ¶ added in v0.5.0
func (c TimeColumn) Asc() OrderExpr
func (TimeColumn) Before ¶ added in v0.5.0
func (c TimeColumn) Before(t time.Time) Predicate
Before is a convenience alias for LT.
func (TimeColumn) Between ¶ added in v0.5.0
func (c TimeColumn) Between(low, high time.Time) Predicate
Between returns a predicate matching rows where the column value is between low and high inclusive (SQL BETWEEN low AND high).
func (TimeColumn) ColRef ¶ added in v0.5.0
func (c TimeColumn) ColRef() ColumnRef
func (TimeColumn) Desc ¶ added in v0.5.0
func (c TimeColumn) Desc() OrderExpr
func (TimeColumn) IsNotNull ¶ added in v0.5.0
func (c TimeColumn) IsNotNull() Predicate
func (TimeColumn) IsNull ¶ added in v0.5.0
func (c TimeColumn) IsNull() Predicate
func (TimeColumn) Name ¶ added in v0.5.0
func (c TimeColumn) Name() string
type Tracer ¶ added in v0.3.0
type Tracer interface {
// Start begins a span named name and returns a context carrying it.
Start(ctx context.Context, name string) (context.Context, Span)
}
Tracer starts spans for drel operations. Provide one via WithTracer to emit a span per executed query. A nil Tracer disables tracing.
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Tx represents an active database transaction with change tracking.
func FromContext ¶ added in v0.6.0
FromContext returns the transaction that WithTx put in ctx. The second result is false when no transaction is present.
func MustFromContext ¶ added in v0.6.0
MustFromContext returns the transaction that WithTx put in ctx. It panics when no transaction is present. Use it in code that a transaction must always surround, so that a wiring fault fails at once.
func (*Tx) AdvisoryLock ¶ added in v0.5.0
AdvisoryLock acquires a Postgres transaction-scoped advisory lock for key, blocking until it is granted. The lock is released automatically when the transaction commits or rolls back. On SQLite this is a documented no-op (returns nil) because SQLite serializes writers at the database level and has no advisory-lock primitive. Must be called within a transaction.
func (*Tx) Exec ¶
Exec executes a raw SQL statement within the transaction. $N placeholders are rewritten to ? on dialects that use ? (SQLite/libSQL).
func (*Tx) HardRemove ¶
HardRemove marks a tracked entity for permanent (hard) deletion on the next flush, bypassing soft delete even when the model supports it.
func (*Tx) NewBatch ¶ added in v0.5.0
NewBatch creates a query batch that runs on this transaction's connection. Batched queries observe the transaction's own uncommitted writes. Because a pgx pipeline cannot span a transaction connection in the general case, a transaction batch always runs sequentially (no network pipelining). Batch results are read-only: they are not snapshotted into the change tracker.
func (*Tx) Query ¶ added in v0.5.0
Query executes a raw SQL query within the transaction and returns the result rows. The caller must close the returned Rows when done. $N placeholders are rewritten to ? on dialects that use ? (SQLite/libSQL). It mirrors Engine.Query so the raw escape hatch is identical inside and outside a transaction.
func (*Tx) QueryRow ¶
QueryRow executes a raw SQL query within the transaction that returns at most one row. $N placeholders are rewritten to ? on dialects that use ? (SQLite/libSQL).
func (*Tx) SaveChanges ¶
SaveChanges flushes all tracked changes within this transaction.
func (*Tx) Savepoint ¶ added in v0.3.0
Savepoint runs fn within a nested SAVEPOINT. If fn returns nil the savepoint is released; otherwise the transaction is rolled back to the savepoint and the change tracker is reverted to its state before the savepoint, so entities added inside fn are dropped and prior entities keep their earlier state. The outer transaction continues either way. Savepoints may be nested, including reusing the same name.
Note: rollback reverts the change tracker, not the in-memory Go structs. If a flush inside fn populated generated fields on an entity (id, version, created_at) and the savepoint is then rolled back, that entity still carries those values in memory even though its row no longer exists. Discard such entities rather than reusing them after a rolled-back savepoint.
func (*Tx) TryAdvisoryLock ¶ added in v0.5.0
TryAdvisoryLock attempts to acquire a Postgres transaction-scoped advisory lock for key without blocking, reporting whether it was acquired. The lock is released automatically when the transaction commits or rolls back. On SQLite this is a documented no-op and always returns (true, nil). Must be called within a transaction.
type TxIncludableQuery ¶ added in v0.5.0
type TxIncludableQuery[T any] struct { // contains filtered or unexported fields }
TxIncludableQuery eagerly loads relationships within an explicit transaction. Root reads and all split sub-queries run on the transaction connection, and loaded children are tracked by the transaction's change tracker (unless the root builder is AsNoTracking) so their edits are flushed on commit.
func (*TxIncludableQuery[T]) All ¶ added in v0.5.0
func (q *TxIncludableQuery[T]) All(ctx context.Context) ([]*T, error)
All returns all matching records and loads included relationships.
func (*TxIncludableQuery[T]) Find ¶ added in v0.5.0
func (q *TxIncludableQuery[T]) Find(ctx context.Context, id any) (*T, error)
Find looks up a single record by primary key and loads included relationships.
func (*TxIncludableQuery[T]) First ¶ added in v0.5.0
func (q *TxIncludableQuery[T]) First(ctx context.Context) (*T, error)
First returns the first matching record and loads included relationships.
func (*TxIncludableQuery[T]) Include ¶ added in v0.5.0
func (q *TxIncludableQuery[T]) Include(rels ...IncludeSpec) *TxIncludableQuery[T]
Include adds more relationships to eagerly load.
func (*TxIncludableQuery[T]) Limit ¶ added in v0.5.0
func (q *TxIncludableQuery[T]) Limit(n int) *TxIncludableQuery[T]
Limit restricts the number of root records returned.
func (*TxIncludableQuery[T]) OrderBy ¶ added in v0.5.0
func (q *TxIncludableQuery[T]) OrderBy(exprs ...OrderExpr) *TxIncludableQuery[T]
OrderBy sets the ordering for the root query.
func (*TxIncludableQuery[T]) Where ¶ added in v0.5.0
func (q *TxIncludableQuery[T]) Where(pred Predicate) *TxIncludableQuery[T]
Where adds a filter predicate to the root query.
type TxOption ¶
type TxOption func(*txConfig)
TxOption configures transaction behaviour.
func WithIsolation ¶
func WithIsolation(level IsolationLevel) TxOption
WithIsolation sets the isolation level for the transaction.
func WithReadOnly ¶ added in v0.5.0
func WithReadOnly() TxOption
WithReadOnly begins the transaction in read-only mode. On Postgres this lets the server skip snapshot bookkeeping and rejects any write inside the tx; on SQLite/libSQL the flag is forwarded to the driver. Compose it with WithIsolation; both reach the driver's BeginTx.
func WithRetry ¶ added in v0.5.0
func WithRetry(cfg RetryConfig) TxOption
WithRetry configures TransactionWithRetry to re-run the transaction on ErrSerializationFailure using the given bounds. It is read only by TransactionWithRetry; plain Transaction ignores it.
type TxQueryBuilder ¶
type TxQueryBuilder[T any] struct { // contains filtered or unexported fields }
TxQueryBuilder constructs and executes typed queries within a transaction. By default, results are tracked by the transaction's change tracker so that mutations are detected on SaveChanges; use AsNoTracking to opt out.
func (*TxQueryBuilder[T]) After ¶ added in v0.3.0
func (q *TxQueryBuilder[T]) After(cursor string) *TxQueryBuilder[T]
After positions a cursor-paginated query past the row encoded by the cursor.
func (*TxQueryBuilder[T]) All ¶
func (q *TxQueryBuilder[T]) All(ctx context.Context) ([]*T, error)
All executes the query and returns all matching results.
func (*TxQueryBuilder[T]) AsNoTracking ¶ added in v0.3.0
func (q *TxQueryBuilder[T]) AsNoTracking() *TxQueryBuilder[T]
AsNoTracking returns a copy of the builder whose results will not be tracked.
func (*TxQueryBuilder[T]) Before ¶ added in v0.5.0
func (q *TxQueryBuilder[T]) Before(cursor string) *TxQueryBuilder[T]
Before positions a cursor-paginated query before the given cursor (backward).
func (*TxQueryBuilder[T]) BulkDelete ¶ added in v0.5.0
func (q *TxQueryBuilder[T]) BulkDelete(ctx context.Context) (int, error)
BulkDelete deletes all rows matching the tx builder's WHERE conditions on the transaction connection. Soft-delete models are soft-deleted. Returns the number of affected rows.
func (*TxQueryBuilder[T]) BulkUpdate ¶ added in v0.5.0
BulkUpdate updates all rows matching the tx builder's WHERE conditions on the transaction connection. Returns the number of affected rows.
func (*TxQueryBuilder[T]) Count ¶
func (q *TxQueryBuilder[T]) Count(ctx context.Context) (int, error)
Count returns the number of matching rows.
func (*TxQueryBuilder[T]) Exists ¶
func (q *TxQueryBuilder[T]) Exists(ctx context.Context) (bool, error)
Exists returns true if at least one matching row exists.
func (*TxQueryBuilder[T]) First ¶
func (q *TxQueryBuilder[T]) First(ctx context.Context) (*T, error)
First returns the first matching result or ErrNotFound if none exist.
func (*TxQueryBuilder[T]) FirstOrNil ¶
func (q *TxQueryBuilder[T]) FirstOrNil(ctx context.Context) (*T, error)
FirstOrNil returns the first matching result or nil if none exist.
func (*TxQueryBuilder[T]) Limit ¶
func (q *TxQueryBuilder[T]) Limit(n int) *TxQueryBuilder[T]
Limit restricts the number of results returned.
func (*TxQueryBuilder[T]) OrderBy ¶
func (q *TxQueryBuilder[T]) OrderBy(exprs ...OrderExpr) *TxQueryBuilder[T]
OrderBy sets the ordering for the query.
func (*TxQueryBuilder[T]) Page ¶ added in v0.3.0
func (q *TxQueryBuilder[T]) Page(ctx context.Context) (*CursorPage[T], error)
Page executes a keyset (cursor) page query within the transaction.
func (*TxQueryBuilder[T]) PageOffset ¶ added in v0.3.0
func (q *TxQueryBuilder[T]) PageOffset(ctx context.Context) (*OffsetPage[T], error)
PageOffset executes an offset-based page query within the transaction.
func (*TxQueryBuilder[T]) Skip ¶
func (q *TxQueryBuilder[T]) Skip(n int) *TxQueryBuilder[T]
Skip sets the offset for the query (number of rows to skip).
func (*TxQueryBuilder[T]) Take ¶ added in v0.3.0
func (q *TxQueryBuilder[T]) Take(n int) *TxQueryBuilder[T]
Take limits the number of results returned. Alias for Limit.
func (*TxQueryBuilder[T]) Unscoped ¶
func (q *TxQueryBuilder[T]) Unscoped() *TxQueryBuilder[T]
Unscoped returns a new builder with all global filters removed.
func (*TxQueryBuilder[T]) Where ¶
func (q *TxQueryBuilder[T]) Where(pred Predicate) *TxQueryBuilder[T]
Where adds a filter predicate. Multiple calls are ANDed together.
func (*TxQueryBuilder[T]) WithoutFilter ¶
func (q *TxQueryBuilder[T]) WithoutFilter(name string) *TxQueryBuilder[T]
WithoutFilter returns a new builder with the named filter removed.
type TxRepository ¶
type TxRepository[T any] struct { // contains filtered or unexported fields }
TxRepository provides tracked query and mutation access within a transaction.
func NewTxRepository ¶
func NewTxRepository[T any](tx *Tx, meta ModelMeta[T]) *TxRepository[T]
NewTxRepository creates a new TxRepository for the given transaction and model metadata.
func Repo ¶ added in v0.4.0
func Repo[T any](tx *Tx, meta ModelMeta[T]) *TxRepository[T]
Repo returns a transaction-bound repository for the given model metadata. It is sugar for NewTxRepository(tx, meta). (A method form is impossible in Go because methods cannot have their own type parameters.)
func (*TxRepository[T]) Add ¶
func (r *TxRepository[T]) Add(entity *T)
Add marks an entity for insertion on the next flush.
func (*TxRepository[T]) All ¶
func (r *TxRepository[T]) All(ctx context.Context) ([]*T, error)
All returns all records for this model within the transaction, tracking them.
func (*TxRepository[T]) AsNoTracking ¶ added in v0.3.0
func (r *TxRepository[T]) AsNoTracking() *TxQueryBuilder[T]
AsNoTracking returns a query builder whose results are not tracked, for read-only queries within the transaction.
func (*TxRepository[T]) Attach ¶ added in v0.3.0
func (r *TxRepository[T]) Attach(entity *T, state EntityState)
Attach begins tracking an externally-constructed entity (e.g. deserialized from a request) in the given state. StateModified flushes a full-column UPDATE; StateAdded behaves like Add; StateUnchanged snapshots the entity so subsequent mutations are detected.
func (*TxRepository[T]) BulkInsert ¶ added in v0.5.0
func (r *TxRepository[T]) BulkInsert(ctx context.Context, entities []*T) (int, error)
BulkInsert inserts multiple entities in batches on the transaction connection, bypassing change tracking. The inserts participate in the surrounding transaction and roll back with it on failure.
func (*TxRepository[T]) BulkUpsert ¶ added in v0.5.0
func (r *TxRepository[T]) BulkUpsert(ctx context.Context, entities []*T, opts ...UpsertOption) (int, error)
BulkUpsert inserts or updates multiple entities on the transaction connection, participating in the surrounding transaction.
func (*TxRepository[T]) Detach ¶ added in v0.3.0
func (r *TxRepository[T]) Detach(entity *T)
Detach stops tracking an entity so its mutations are no longer flushed.
func (*TxRepository[T]) Find ¶
func (r *TxRepository[T]) Find(ctx context.Context, id any) (*T, error)
Find looks up a single record by primary key and begins tracking it.
func (*TxRepository[T]) Include ¶ added in v0.5.0
func (r *TxRepository[T]) Include(rels ...IncludeSpec) *TxIncludableQuery[T]
Include begins a tracked query that eagerly loads the given relationships within the transaction. Root reads and all split sub-queries run on the transaction connection, observing the transaction's own uncommitted writes.
func (*TxRepository[T]) OrderBy ¶ added in v0.3.0
func (r *TxRepository[T]) OrderBy(exprs ...OrderExpr) *TxQueryBuilder[T]
OrderBy starts an ordered, tracked query within the transaction.
func (*TxRepository[T]) Remove ¶
func (r *TxRepository[T]) Remove(entity *T) error
Remove marks a tracked entity for deletion on the next flush.
func (*TxRepository[T]) Unscoped ¶
func (r *TxRepository[T]) Unscoped() *TxQueryBuilder[T]
Unscoped returns a query builder with all global filters removed.
func (*TxRepository[T]) Where ¶
func (r *TxRepository[T]) Where(pred Predicate) *TxQueryBuilder[T]
Where starts a filtered, tracked query within the transaction.
func (*TxRepository[T]) WithoutFilter ¶
func (r *TxRepository[T]) WithoutFilter(name string) *TxQueryBuilder[T]
WithoutFilter returns a query builder with the named filter removed.
type UpsertOption ¶
type UpsertOption func(*upsertConfig)
UpsertOption configures BulkUpsert behavior.
func ConflictColumns ¶
func ConflictColumns[C interface{ Name() string }](cols ...C) UpsertOption
ConflictColumns specifies which columns form the conflict target for an upsert.
func DoNothing ¶ added in v0.5.0
func DoNothing() UpsertOption
DoNothing configures the upsert to emit ON CONFLICT (...) DO NOTHING: rows that conflict on the conflict target are skipped instead of updated. When set, UpdateOnConflict becomes optional and is ignored.
func UpdateOnConflict ¶
func UpdateOnConflict[C interface{ Name() string }](cols ...C) UpsertOption
UpdateOnConflict specifies which columns to update when a conflict is detected.
Source Files
¶
- audit.go
- batch.go
- bulk.go
- bulk_query.go
- column.go
- context_tx.go
- engine.go
- errors.go
- errors_projection.go
- events.go
- field_change.go
- filter.go
- health.go
- inbox.go
- include.go
- json.go
- keys.go
- libsql.go
- logging.go
- model.go
- multi_column.go
- mutation.go
- observability.go
- order.go
- outbox.go
- pagination.go
- placeholder.go
- predicate.go
- query.go
- rawquery.go
- relation.go
- relay.go
- repository.go
- retry.go
- row.go
- scanplan.go
- select.go
- tracker.go
- transaction.go
- tx.go
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
drel
command
|
|
|
Package es holds an append-only event store.
|
Package es holds an append-only event store. |
|
examples
|
|
|
api
command
Example: api
|
Example: api |
|
bulk-ops
command
Example: bulk-ops
|
Example: bulk-ops |
|
enums
command
Example: enums
|
Example: enums |
|
event-sourcing
command
Example: event-sourcing
|
Example: event-sourcing |
|
feature-slices
command
Example: feature-slices
|
Example: feature-slices |
|
getting-started
command
Example: getting-started
|
Example: getting-started |
|
inbox
command
Example: inbox
|
Example: inbox |
|
internals
command
Example: internals
|
Example: internals |
|
model-features
command
Example: model-features
|
Example: model-features |
|
multi-model
command
Example: multi-model
|
Example: multi-model |
|
observability
command
Example: observability
|
Example: observability |
|
outbox
command
Example: outbox
|
Example: outbox |
|
relationships
command
Example: relationships
|
Example: relationships |
|
sqlite-todo
command
Example: sqlite-todo
|
Example: sqlite-todo |
|
uuid-keys
command
Example: uuid-keys
|
Example: uuid-keys |
|
value-objects
command
|
|
|
internal
|
|
|
dberr
Package dberr classifies driver-specific database errors into a small set of dialect-neutral sentinel errors that callers can match with errors.Is, without importing pgconn or the sqlite driver themselves.
|
Package dberr classifies driver-specific database errors into a small set of dialect-neutral sentinel errors that callers can match with errors.Is, without importing pgconn or the sqlite driver themselves. |
|
driver/libsqldriver
Package libsqldriver implements driver.Driver for libSQL / Turso using the database/sql libsql driver.
|
Package libsqldriver implements driver.Driver for libSQL / Turso using the database/sql libsql driver. |
|
dsn
Package dsn centralises DSN dialect detection, driver opening, and auth-token injection so the runtime engine and the migrate CLI share one implementation and cannot drift apart.
|
Package dsn centralises DSN dialect detection, driver opening, and auth-token injection so the runtime engine and the migrate CLI share one implementation and cannot drift apart. |