Documentation
¶
Overview ¶
Package ant is a Go ORM with plain struct models, compiler-checked queries, and change tracking, and no code generation.
Declare a context, open it, and query through field probes:
type AppDB struct {
ant.Context
Users ant.Table[User]
}
var U = ant.Fields[User]()
db, err := ant.Open[AppDB](ctx, postgres.Dialect, dsn)
adults, err := db.Users.Where(ant.Gt(&U.Age, 18)).All(ctx)
Index ¶
- Constants
- Variables
- func Add[T any](h Handle, entity *T) error
- func Attach[T any](h Handle, entity *T) error
- func AvgOf[T any, V Number](ctx context.Context, q *Query[T], field *V) (float64, error)
- func Begin[DB any](ctx context.Context, db *DB, options ...TxOption) (*DB, error)
- func Clone[T any](entity *T) *T
- func CurrentTx(h Handle) *sql.Tx
- func Detach[T any](h Handle, entity *T)
- func FailedSQL(err error) string
- func Fields[T any]() *T
- func GenerateKey[E, V any](b *ModelBuilder[E], field *V, fn func() V)
- func IsCheckViolation(err error) bool
- func IsDirty[T, V any](e *EntityEntry[T], field *V) bool
- func IsForeignKeyViolation(err error) bool
- func IsNotNullViolation(err error) bool
- func IsRetryable(err error) bool
- func IsUniqueViolation(err error) bool
- func Link[T, R any](ctx context.Context, h Handle, owner *T, rel *[]R, targets ...*R) error
- func MarkModified[T any](h Handle, entity *T) error
- func MaxOf[T any, V Ordered](ctx context.Context, q *Query[T], field *V) (V, error)
- func MinOf[T any, V Ordered](ctx context.Context, q *Query[T], field *V) (V, error)
- func Observe[T any](h Handle, o Observer[T]) error
- func OnPrimary(ctx context.Context) context.Context
- func Open[DB any](ctx context.Context, d dialect.Dialect, dsn string, options ...Option) (*DB, error)
- func Original[T, V any](e *EntityEntry[T], field *V) (V, error)
- func Pluck[T, V any](ctx context.Context, q *Query[T], field *V) ([]V, error)
- func Pointers[T any](values []T) []*T
- func Remove[T any](h Handle, entity *T) error
- func SQLState(err error) string
- func SchemaOf[DB any](d dialect.Dialect) (*schema.Schema, error)
- func Session[DB any](db *DB, options ...Option) *DB
- func SumOf[T any, V Number](ctx context.Context, q *Query[T], field *V) (V, error)
- func SyncLinks[T, R any](ctx context.Context, h Handle, owner *T, rel *[]R, targets ...*R) error
- func TableOf[T any]() (schemaName, table string, err error)
- func Toggle[T, R any](ctx context.Context, h Handle, owner *T, rel *[]R, targets ...*R) error
- func TrackGraph[T any](h Handle, root *T, decide func(GraphNode) State) error
- func Tracked[T any](h Handle) []*T
- func Unlink[T, R any](ctx context.Context, h Handle, owner *T, rel *[]R, targets ...*R) error
- func UseConn[DB any](db *DB, conn *sql.Conn) (*DB, error)
- func UseTx[DB any](db *DB, tx *sql.Tx) (*DB, error)
- func Watch(ctx context.Context) context.Context
- func WithoutHooks(ctx context.Context) context.Context
- func Wrap[DB any](d dialect.Dialect, pool *sql.DB, options ...Option) (*DB, error)
- type Action
- type AfterDeleter
- type AfterIncluder
- type AfterInserter
- type AfterLoader
- type AfterUpdater
- type Alert
- type Assignment
- type Base
- type BeforeDeleter
- type BeforeInserter
- type BeforeUpdater
- type BulkRows
- type CaseExpr
- type Change
- type ColumnBuilder
- func (c *ColumnBuilder) Collation(name string) *ColumnBuilder
- func (c *ColumnBuilder) Comment(text string) *ColumnBuilder
- func (c *ColumnBuilder) Default(expr string) *ColumnBuilder
- func (c *ColumnBuilder) Enum(name string, values ...string) *ColumnBuilder
- func (c *ColumnBuilder) Fixed(n int) *ColumnBuilder
- func (c *ColumnBuilder) Generated(expr string) *ColumnBuilder
- func (c *ColumnBuilder) Length(n int) *ColumnBuilder
- func (c *ColumnBuilder) NotNull() *ColumnBuilder
- func (c *ColumnBuilder) Nullable() *ColumnBuilder
- func (c *ColumnBuilder) Precision(precision, scale int) *ColumnBuilder
- func (c *ColumnBuilder) Sensitive() *ColumnBuilder
- func (c *ColumnBuilder) Sequence(name string, options ...SequenceOption) *ColumnBuilder
- func (c *ColumnBuilder) Type(sql string) *ColumnBuilder
- func (c *ColumnBuilder) Unique(name ...string) *ColumnBuilder
- type ConcurrencyError
- type Cond
- func AllOf[V comparable](v V, fields ...*V) Cond
- func And(conds ...Cond) Cond
- func AnyOf[V comparable](v V, fields ...*V) Cond
- func Between[V Ordered](field *V, low, high V) Cond
- func Eq[V comparable](field *V, v V) Cond
- func EqCol[V comparable](a, b *V) Cond
- func Exists(q Selectable) Cond
- func FailedCond(err error) Cond
- func Future(field *time.Time) Cond
- func Gt[V Ordered](field *V, v V) Cond
- func Gte[V Ordered](field *V, v V) Cond
- func Has[R any](rel *[]R, conds ...Cond) Cond
- func HasNone[R any](rel *[]R, conds ...Cond) Cond
- func HasOne[R any](rel **R, conds ...Cond) Cond
- func ILike[V ~string](field *V, pattern V) Cond
- func In[V comparable](field *V, values ...V) Cond
- func InSub[V any](field *V, sub Sub[V]) Cond
- func InTuples(fields []FieldRef, tuples ...[]any) Cond
- func IsNotNull[V any](field *V) Cond
- func IsNull[V any](field *V) Cond
- func Like[V ~string](field *V, pattern V) Cond
- func Lt[V Ordered](field *V, v V) Cond
- func Lte[V Ordered](field *V, v V) Cond
- func Ne[V comparable](field *V, v V) Cond
- func NoneOf[V comparable](v V, fields ...*V) Cond
- func Not(c Cond) Cond
- func NotExists(q Selectable) Cond
- func NotIn[V comparable](field *V, values ...V) Cond
- func NotInSub[V any](field *V, sub Sub[V]) Cond
- func Or(conds ...Cond) Cond
- func Past(field *time.Time) Cond
- func SQLCond(text string, args ...any) Cond
- func Today(field *time.Time) Cond
- type Conflict
- type Context
- func (c *Context) ClearTracked()
- func (c *Context) Close() error
- func (c *Context) Commit() error
- func (c *Context) DB() *sql.DB
- func (c *Context) DebugTracked() string
- func (c *Context) Dialect() dialect.Dialect
- func (c *Context) EnsureCreated(ctx context.Context) error
- func (c *Context) EnsureDeleted(ctx context.Context) error
- func (c *Context) HasChanges() bool
- func (c *Context) Release(ctx context.Context, name string) error
- func (c *Context) Rollback() error
- func (c *Context) RollbackTo(ctx context.Context, name string) error
- func (c *Context) SaveChanges(ctx context.Context) error
- func (c *Context) Savepoint(ctx context.Context, name string) error
- func (c *Context) Tx[DB any](ctx context.Context, f func(tx *DB) error, options ...TxOption) error
- type CursorPage
- type DeletedAt
- type Diagnostics
- type Entity
- type EntityEntry
- type Events
- type Expr
- func Avg[V Number](field *V) Expr[float64]
- func AvgRelated[R any, V Number](rel *[]R, field *V, conds ...Cond) Expr[sql.Null[float64]]
- func Coalesce[V any](field *V, fallback V) Expr[V]
- func Col[V any](field *V) Expr[V]
- func Collate[V ~string](field *V, collation string) Expr[V]
- func Count() Expr[int64]
- func CountDistinct[V any](field *V) Expr[int64]
- func CountOf[V any](field *V) Expr[int64]
- func CountRelated[R any](rel *[]R, conds ...Cond) Expr[int64]
- func DatePart(field *time.Time, part string) Expr[float64]
- func DenseRank() Expr[int64]
- func FailedExpr[V any](err error) Expr[V]
- func Func[R any](name string, args ...any) Expr[R]
- func Lag[V any](field *V) Expr[sql.Null[V]]
- func Lead[V any](field *V) Expr[sql.Null[V]]
- func Length[V ~string](field *V) Expr[int]
- func Lower[V ~string](field *V) Expr[V]
- func Max[V Ordered](field *V) Expr[V]
- func MaxRelated[R any, V Ordered](rel *[]R, field *V, conds ...Cond) Expr[sql.Null[V]]
- func Min[V Ordered](field *V) Expr[V]
- func MinRelated[R any, V Ordered](rel *[]R, field *V, conds ...Cond) Expr[sql.Null[V]]
- func Rank() Expr[int64]
- func RowNumber() Expr[int64]
- func SQL[V any](text string, args ...any) Expr[V]
- func Sum[V Number](field *V) Expr[V]
- func SumRelated[R any, V Number](rel *[]R, field *V, conds ...Cond) Expr[V]
- func Upper[V ~string](field *V) Expr[V]
- func (e Expr[V]) Asc() Sort
- func (e Expr[V]) Desc() Sort
- func (e Expr[V]) Div(v V) Expr[V]
- func (e Expr[V]) Eq(v V) Cond
- func (e Expr[V]) EqExpr(other Expr[V]) Cond
- func (e Expr[V]) Filter(conds ...Cond) Expr[V]
- func (e Expr[V]) Gt(v V) Cond
- func (e Expr[V]) GtExpr(other Expr[V]) Cond
- func (e Expr[V]) Gte(v V) Cond
- func (e Expr[V]) IsNotNull() Cond
- func (e Expr[V]) IsNull() Cond
- func (e Expr[V]) Lt(v V) Cond
- func (e Expr[V]) LtExpr(other Expr[V]) Cond
- func (e Expr[V]) Lte(v V) Cond
- func (e Expr[V]) Minus(v V) Expr[V]
- func (e Expr[V]) Ne(v V) Cond
- func (e Expr[V]) Over(w Window) Expr[V]
- func (e Expr[V]) Plus(v V) Expr[V]
- func (e Expr[V]) Times(v V) Expr[V]
- type FieldConvention
- type FieldRef
- type ForeignKeyBuilder
- func (k *ForeignKeyBuilder) Name(name string) *ForeignKeyBuilder
- func (k *ForeignKeyBuilder) NoIndex() *ForeignKeyBuilder
- func (k *ForeignKeyBuilder) OnDelete(action Action) *ForeignKeyBuilder
- func (k *ForeignKeyBuilder) OnUpdate(action Action) *ForeignKeyBuilder
- func (k *ForeignKeyBuilder) References(fields ...FieldRef) *ForeignKeyBuilder
- type Gob
- type GraphNode
- type Grouped
- type Handle
- type IndexBuilder
- func (i *IndexBuilder) And[V any](field *V) *IndexBuilder
- func (i *IndexBuilder) AndExpr(expr string) *IndexBuilder
- func (i *IndexBuilder) Concurrently() *IndexBuilder
- func (i *IndexBuilder) Desc() *IndexBuilder
- func (i *IndexBuilder) Include[V any](field *V) *IndexBuilder
- func (i *IndexBuilder) Name(name string) *IndexBuilder
- func (i *IndexBuilder) Unique() *IndexBuilder
- func (i *IndexBuilder) Using(method string) *IndexBuilder
- func (i *IndexBuilder) Where(condition string) *IndexBuilder
- type InsertOption
- type Interceptor
- type JSON
- type Join2
- func JoinLateral[T, J any](q *Query[T], sub *Query[J], on ...Cond) *Join2[T, J]
- func JoinSub[T, J any](q *Query[T], sub *Query[J], on ...Cond) *Join2[T, J]
- func LeftJoinLateral[T, J any](q *Query[T], sub *Query[J], on ...Cond) *Join2[T, J]
- func LeftJoinSub[T, J any](q *Query[T], sub *Query[J], on ...Cond) *Join2[T, J]
- func (j *Join2[A, B]) Distinct() *Join2[A, B]
- func (j *Join2[A, B]) GroupBy[V any](field *V) *Grouped
- func (j *Join2[A, B]) GroupByExpr[V any](e Expr[V]) *Grouped
- func (j *Join2[A, B]) Join[C any](rel **C) *Join3[A, B, C]
- func (j *Join2[A, B]) JoinMany[C any](rel *[]C) *Join3[A, B, C]
- func (j *Join2[A, B]) JoinOn[C any](on ...Cond) *Join3[A, B, C]
- func (j *Join2[A, B]) LeftJoin[C any](rel **C) *Join3[A, B, C]
- func (j *Join2[A, B]) LeftJoinMany[C any](rel *[]C) *Join3[A, B, C]
- func (j *Join2[A, B]) LeftJoinOn[C any](on ...Cond) *Join3[A, B, C]
- func (j *Join2[A, B]) Limit(limit int) *Join2[A, B]
- func (j *Join2[A, B]) Offset(offset int) *Join2[A, B]
- func (j *Join2[A, B]) Order(terms ...Sort) *Join2[A, B]
- func (j *Join2[A, B]) OrderBy[V Ordered](field *V) *Join2[A, B]
- func (j *Join2[A, B]) OrderByDesc[V Ordered](field *V) *Join2[A, B]
- func (j *Join2[A, B]) Select[R any](f func(*A, *B) R) *Projection[R]
- func (j *Join2[A, B]) Where(c ...Cond) *Join2[A, B]
- type Join3
- func (j *Join3[A, B, C]) Distinct() *Join3[A, B, C]
- func (j *Join3[A, B, C]) GroupBy[V any](field *V) *Grouped
- func (j *Join3[A, B, C]) GroupByExpr[V any](e Expr[V]) *Grouped
- func (j *Join3[A, B, C]) Join[D any](rel **D) *Join4[A, B, C, D]
- func (j *Join3[A, B, C]) JoinMany[D any](rel *[]D) *Join4[A, B, C, D]
- func (j *Join3[A, B, C]) JoinOn[D any](on ...Cond) *Join4[A, B, C, D]
- func (j *Join3[A, B, C]) LeftJoin[D any](rel **D) *Join4[A, B, C, D]
- func (j *Join3[A, B, C]) LeftJoinMany[D any](rel *[]D) *Join4[A, B, C, D]
- func (j *Join3[A, B, C]) LeftJoinOn[D any](on ...Cond) *Join4[A, B, C, D]
- func (j *Join3[A, B, C]) Limit(limit int) *Join3[A, B, C]
- func (j *Join3[A, B, C]) Offset(offset int) *Join3[A, B, C]
- func (j *Join3[A, B, C]) Order(terms ...Sort) *Join3[A, B, C]
- func (j *Join3[A, B, C]) OrderBy[V Ordered](field *V) *Join3[A, B, C]
- func (j *Join3[A, B, C]) OrderByDesc[V Ordered](field *V) *Join3[A, B, C]
- func (j *Join3[A, B, C]) Select[R any](f func(*A, *B, *C) R) *Projection[R]
- func (j *Join3[A, B, C]) Where(c ...Cond) *Join3[A, B, C]
- type Join4
- func (j *Join4[A, B, C, D]) Distinct() *Join4[A, B, C, D]
- func (j *Join4[A, B, C, D]) GroupBy[V any](field *V) *Grouped
- func (j *Join4[A, B, C, D]) GroupByExpr[V any](e Expr[V]) *Grouped
- func (j *Join4[A, B, C, D]) Limit(limit int) *Join4[A, B, C, D]
- func (j *Join4[A, B, C, D]) Offset(offset int) *Join4[A, B, C, D]
- func (j *Join4[A, B, C, D]) Order(terms ...Sort) *Join4[A, B, C, D]
- func (j *Join4[A, B, C, D]) OrderBy[V Ordered](field *V) *Join4[A, B, C, D]
- func (j *Join4[A, B, C, D]) OrderByDesc[V Ordered](field *V) *Join4[A, B, C, D]
- func (j *Join4[A, B, C, D]) Select[R any](f func(*A, *B, *C, *D) R) *Projection[R]
- func (j *Join4[A, B, C, D]) Where(c ...Cond) *Join4[A, B, C, D]
- type KeyBuilder
- type LogOption
- type Mapping
- type Merger
- type Mixin
- type MixinConfigurer
- type ModelBuilder
- func (b *ModelBuilder[E]) BelongsTo[R any](rel **R) *RelationBuilder
- func (b *ModelBuilder[E]) Check(name, expr string)
- func (b *ModelBuilder[E]) Column[V any](field *V) *ColumnBuilder
- func (b *ModelBuilder[E]) Comment(text string)
- func (b *ModelBuilder[E]) Comparer[V any](field *V, equal func(a, b V) bool)
- func (b *ModelBuilder[E]) CompositeKey(fields ...FieldRef)
- func (b *ModelBuilder[E]) Discriminator[V comparable](field *V, value V)
- func (b *ModelBuilder[E]) ExcludeFromMigrations()
- func (b *ModelBuilder[E]) Filter(name string, filter func(context.Context) Cond)
- func (b *ModelBuilder[E]) ForeignKey(fields ...FieldRef) *ForeignKeyBuilder
- func (b *ModelBuilder[E]) HasMany[R any](rel *[]R) *RelationBuilder
- func (b *ModelBuilder[E]) HasManyThrough[R, A, C any](rel *[]R, parentKey *A, throughKey *C) *RelationBuilder
- func (b *ModelBuilder[E]) HasOne[R any](rel **R) *RelationBuilder
- func (b *ModelBuilder[E]) HasOneThrough[R, A, C any](rel **R, parentKey *A, throughKey *C) *RelationBuilder
- func (b *ModelBuilder[E]) Index[V any](field *V) *IndexBuilder
- func (b *ModelBuilder[E]) IndexExpr(expr string) *IndexBuilder
- func (b *ModelBuilder[E]) Key[V any](field *V) *KeyBuilder
- func (b *ModelBuilder[E]) KeyName(name string)
- func (b *ModelBuilder[E]) ManyToMany[R any](rel *[]R) *RelationBuilder
- func (b *ModelBuilder[E]) NoKey()
- func (b *ModelBuilder[E]) NoTimestamps()
- func (b *ModelBuilder[E]) PartitionByHash(fields ...FieldRef)
- func (b *ModelBuilder[E]) PartitionByList(fields ...FieldRef)
- func (b *ModelBuilder[E]) PartitionByRange(fields ...FieldRef)
- func (b *ModelBuilder[E]) Schema(name string)
- func (b *ModelBuilder[E]) Table(name string)
- func (b *ModelBuilder[E]) Validate[V any](field *V, rule func(V) error)
- func (b *ModelBuilder[E]) View(name string)
- type ModelConvention
- type Naming
- type Number
- type Observer
- type Option
- func WithConvention(rule func(*ModelConvention)) Option
- func WithDetailedErrors() Option
- func WithDiagnostics(d Diagnostics) Option
- func WithEvents(e Events) Option
- func WithInterceptor(i Interceptor) Option
- func WithLogger(logger *slog.Logger, options ...LogOption) Option
- func WithLooseScan() Option
- func WithNaming(naming Naming) Option
- func WithNow(now func() time.Time) Option
- func WithReplicas(pools ...*sql.DB) Option
- func WithRetry(policy Retry) Option
- func WithStickyWrites(d time.Duration) Option
- func WithStrict() Option
- func WithTracking(on bool) Option
- func WithoutAutoTx() Option
- type Ordered
- type Outcome
- type Page
- type Projection
- type Query
- func FromFunc[T any](h Handle, call string, args ...any) *Query[T]
- func FromRaw[T any](h Handle, text string, args ...any) *Query[T]
- func Related[T, R any](h Handle, entity *T, rel *[]R) *Query[R]
- func RelatedOne[T, R any](h Handle, entity *T, rel **R) *Query[R]
- func Values[T any](h Handle, rows ...T) *Query[T]
- func (q *Query[T]) After(ctx context.Context, cursor string, size int) (*CursorPage[T], error)
- func (q *Query[T]) All(ctx context.Context) ([]*T, error)
- func (q *Query[T]) Chunk(ctx context.Context, size int, f func([]*T) error) error
- func (q *Query[T]) ChunkByKey(ctx context.Context, size int, f func([]*T) error) error
- func (q *Query[T]) ClearOrder() *Query[T]
- func (q *Query[T]) Column[V any](field *V) *Query[T]
- func (q *Query[T]) Count(ctx context.Context) (int64, error)
- func (q *Query[T]) CrossJoin[J any]() *Join2[T, J]
- func (q *Query[T]) Debug() *Query[T]
- func (q *Query[T]) Delete(ctx context.Context) (int64, error)
- func (q *Query[T]) DeleteReturning(ctx context.Context) ([]*T, error)
- func (q *Query[T]) DeleteSQL(ctx context.Context) (string, []any, error)
- func (q *Query[T]) Distinct() *Query[T]
- func (q *Query[T]) DoesNotExist(ctx context.Context) (bool, error)
- func (q *Query[T]) Each(ctx context.Context) iter.Seq2[T, error]
- func (q *Query[T]) Except(other *Query[T]) *Query[T]
- func (q *Query[T]) Exists(ctx context.Context) (bool, error)
- func (q *Query[T]) Explain(ctx context.Context) (string, error)
- func (q *Query[T]) Find[K comparable](ctx context.Context, key K) (*T, error)
- func (q *Query[T]) First(ctx context.Context) (*T, error)
- func (q *Query[T]) ForShare() *Query[T]
- func (q *Query[T]) ForUpdate() *Query[T]
- func (q *Query[T]) ForceDelete(ctx context.Context) (int64, error)
- func (q *Query[T]) From(sub *Query[T]) *Query[T]
- func (q *Query[T]) FromCTE(name string, sub *Query[T]) *Query[T]
- func (q *Query[T]) FullJoinOn[J any](on ...Cond) *Join2[T, J]
- func (q *Query[T]) GroupBy[V any](field *V) *Grouped
- func (q *Query[T]) GroupByExpr[V any](e Expr[V]) *Grouped
- func (q *Query[T]) Hint(hint string) *Query[T]
- func (q *Query[T]) IgnoreFilters(names ...string) *Query[T]
- func (q *Query[T]) Include[R any](rel *[]R, shape ...func(*Query[R]) *Query[R]) *Query[T]
- func (q *Query[T]) IncludeJoined[R any](rel **R) *Query[T]
- func (q *Query[T]) IncludeOne[R any](rel **R, shape ...func(*Query[R]) *Query[R]) *Query[T]
- func (q *Query[T]) Intersect(other *Query[T]) *Query[T]
- func (q *Query[T]) Join[J any](rel **J) *Join2[T, J]
- func (q *Query[T]) JoinMany[J any](rel *[]J) *Join2[T, J]
- func (q *Query[T]) JoinOn[J any](on ...Cond) *Join2[T, J]
- func (q *Query[T]) JoinUsing[J, V any](field *V) *Join2[T, J]
- func (q *Query[T]) Latest(field *time.Time) *Query[T]
- func (q *Query[T]) LeftJoin[J any](rel **J) *Join2[T, J]
- func (q *Query[T]) LeftJoinMany[J any](rel *[]J) *Join2[T, J]
- func (q *Query[T]) LeftJoinOn[J any](on ...Cond) *Join2[T, J]
- func (q *Query[T]) Limit(n int) *Query[T]
- func (q *Query[T]) NoTracking() *Query[T]
- func (q *Query[T]) NoTrackingResolved() *Query[T]
- func (q *Query[T]) NoWait() *Query[T]
- func (q *Query[T]) Offset(n int) *Query[T]
- func (q *Query[T]) Oldest(field *time.Time) *Query[T]
- func (q *Query[T]) Omit[V any](field *V) *Query[T]
- func (q *Query[T]) OnlyDeleted() *Query[T]
- func (q *Query[T]) Order(terms ...Sort) *Query[T]
- func (q *Query[T]) OrderBy[V Ordered](field *V) *Query[T]
- func (q *Query[T]) OrderByDesc[V Ordered](field *V) *Query[T]
- func (q *Query[T]) OrderByRandom() *Query[T]
- func (q *Query[T]) Page(ctx context.Context, number, size int) (*Page[T], error)
- func (q *Query[T]) Recursive(rel *[]T) *Query[T]
- func (q *Query[T]) RecursiveOne(rel **T) *Query[T]
- func (q *Query[T]) Restore(ctx context.Context) (int64, error)
- func (q *Query[T]) RightJoinOn[J any](on ...Cond) *Join2[T, J]
- func (q *Query[T]) Scope(scopes ...func(*Query[T]) *Query[T]) *Query[T]
- func (q *Query[T]) Single(ctx context.Context) (*T, error)
- func (q *Query[T]) SkipLocked() *Query[T]
- func (q *Query[T]) Tag(name string) *Query[T]
- func (q *Query[T]) ThenBy[V Ordered](field *V) *Query[T]
- func (q *Query[T]) ThenByDesc[V Ordered](field *V) *Query[T]
- func (q *Query[T]) ToSQL() (string, []any, error)
- func (q *Query[T]) ToSQLContext(ctx context.Context) (string, []any, error)
- func (q *Query[T]) Unfiltered() *Query[T]
- func (q *Query[T]) Union(other *Query[T]) *Query[T]
- func (q *Query[T]) UnionAll(other *Query[T]) *Query[T]
- func (q *Query[T]) Update(ctx context.Context, a ...Assignment) (int64, error)
- func (q *Query[T]) UpdateReturning(ctx context.Context, a ...Assignment) ([]*T, error)
- func (q *Query[T]) UpdateSQL(ctx context.Context, set ...Assignment) (string, []any, error)
- func (q *Query[T]) When(ok bool, f func(*Query[T]) *Query[T]) *Query[T]
- func (q *Query[T]) Where(c ...Cond) *Query[T]
- func (q *Query[T]) With[V any](field *V, value Expr[V]) *Query[T]
- func (q *Query[T]) WithDeleted() *Query[T]
- type RawQuery
- type RelationBuilder
- func (r *RelationBuilder) ConstraintName(name string) *RelationBuilder
- func (r *RelationBuilder) ForeignKey[V any](field *V) *RelationBuilder
- func (r *RelationBuilder) Inverse[P any](back **P) *RelationBuilder
- func (r *RelationBuilder) Latest[V Ordered](field *V) *RelationBuilder
- func (r *RelationBuilder) Morph[V comparable](field *V, value V) *RelationBuilder
- func (r *RelationBuilder) NoForeignKey() *RelationBuilder
- func (r *RelationBuilder) NoIndex() *RelationBuilder
- func (r *RelationBuilder) Oldest[V Ordered](field *V) *RelationBuilder
- func (r *RelationBuilder) OnDelete(action Action) *RelationBuilder
- func (r *RelationBuilder) OnUpdate(action Action) *RelationBuilder
- func (r *RelationBuilder) PivotColumns(local, foreign string) *RelationBuilder
- func (r *RelationBuilder) References[V any](field *V) *RelationBuilder
- func (r *RelationBuilder) Through(table string) *RelationBuilder
- func (r *RelationBuilder) Touch() *RelationBuilder
- func (r *RelationBuilder) Where(conds ...Cond) *RelationBuilder
- type Retry
- type SaveInterceptor
- type Selectable
- type SequenceOption
- type Sort
- type State
- type Statement
- type Sub
- type Table
- func (t *Table[T]) All(ctx context.Context) ([]*T, error)
- func (t *Table[T]) Column[V any](field *V) *Query[T]
- func (t *Table[T]) Count(ctx context.Context) (int64, error)
- func (t *Table[T]) CrossJoin[J any]() *Join2[T, J]
- func (t *Table[T]) DeleteByID[K comparable](ctx context.Context, key K) error
- func (t *Table[T]) Distinct() *Query[T]
- func (t *Table[T]) Each(ctx context.Context) iter.Seq2[T, error]
- func (t *Table[T]) Exists(ctx context.Context) (bool, error)
- func (t *Table[T]) Find[K comparable](ctx context.Context, key K) (*T, error)
- func (t *Table[T]) FindKey(ctx context.Context, parts ...any) (*T, error)
- func (t *Table[T]) First(ctx context.Context) (*T, error)
- func (t *Table[T]) FirstOrCreate(ctx context.Context, e *T, conds ...Cond) (*T, bool, error)
- func (t *Table[T]) FirstOrNew(ctx context.Context, e *T, conds ...Cond) (*T, bool, error)
- func (t *Table[T]) FullJoinOn[J any](on ...Cond) *Join2[T, J]
- func (t *Table[T]) GroupBy[V any](field *V) *Grouped
- func (t *Table[T]) GroupByExpr[V any](e Expr[V]) *Grouped
- func (t *Table[T]) IgnoreFilters(names ...string) *Query[T]
- func (t *Table[T]) Include[R any](rel *[]R, shape ...func(*Query[R]) *Query[R]) *Query[T]
- func (t *Table[T]) IncludeJoined[R any](rel **R) *Query[T]
- func (t *Table[T]) IncludeOne[R any](rel **R, shape ...func(*Query[R]) *Query[R]) *Query[T]
- func (t *Table[T]) Insert(ctx context.Context, entities ...*T) error
- func (t *Table[T]) InsertFrom(ctx context.Context, rows *Projection[T]) (int64, error)
- func (t *Table[T]) InsertMany(ctx context.Context, entities []*T, options ...InsertOption) (int64, error)
- func (t *Table[T]) InsertOnly(ctx context.Context, entities ...*T) error
- func (t *Table[T]) Join[J any](rel **J) *Join2[T, J]
- func (t *Table[T]) JoinMany[J any](rel *[]J) *Join2[T, J]
- func (t *Table[T]) JoinOn[J any](on ...Cond) *Join2[T, J]
- func (t *Table[T]) LeftJoin[J any](rel **J) *Join2[T, J]
- func (t *Table[T]) LeftJoinMany[J any](rel *[]J) *Join2[T, J]
- func (t *Table[T]) LeftJoinOn[J any](on ...Cond) *Join2[T, J]
- func (t *Table[T]) Limit(n int) *Query[T]
- func (t *Table[T]) Load[R any](ctx context.Context, rel *[]R, entities ...*T) error
- func (t *Table[T]) LoadMissing[R any](ctx context.Context, rel *[]R, entities ...*T) error
- func (t *Table[T]) LoadOne[R any](ctx context.Context, rel **R, entities ...*T) error
- func (t *Table[T]) NoTracking() *Query[T]
- func (t *Table[T]) Offset(n int) *Query[T]
- func (t *Table[T]) Omit[V any](field *V) *Query[T]
- func (t *Table[T]) OnlyDeleted() *Query[T]
- func (t *Table[T]) Order(terms ...Sort) *Query[T]
- func (t *Table[T]) OrderBy[V Ordered](field *V) *Query[T]
- func (t *Table[T]) OrderByDesc[V Ordered](field *V) *Query[T]
- func (t *Table[T]) Prune(ctx context.Context, conds ...Cond) (int64, error)
- func (t *Table[T]) Query() *Query[T]
- func (t *Table[T]) Reload(ctx context.Context, e *T) error
- func (t *Table[T]) RightJoinOn[J any](on ...Cond) *Join2[T, J]
- func (t *Table[T]) Scope(scopes ...func(*Query[T]) *Query[T]) *Query[T]
- func (t *Table[T]) Single(ctx context.Context) (*T, error)
- func (t *Table[T]) Truncate(ctx context.Context) error
- func (t *Table[T]) Unfiltered() *Query[T]
- func (t *Table[T]) UpdateMany(ctx context.Context, entities []*T, fields ...FieldRef) (int64, error)
- func (t *Table[T]) Upsert(ctx context.Context, e *T, conflict *Conflict) (bool, error)
- func (t *Table[T]) Where(c ...Cond) *Query[T]
- func (t *Table[T]) With[V any](field *V, value Expr[V]) *Query[T]
- func (t *Table[T]) WithDeleted() *Query[T]
- type TxOption
- type UnixTime
- type ValidationError
- type Validator
- type Window
Examples ¶
Constants ¶
const ( // Detached entities are not tracked. Detached = track.Detached // Added entities are inserted by the next SaveChanges. Added = track.Added // Unchanged entities match what was loaded. Unchanged = track.Unchanged // Modified entities are updated by the next SaveChanges. Modified = track.Modified // Deleted entities are removed by the next SaveChanges. Deleted = track.Deleted )
Entity states.
Variables ¶
var ( // ErrNotFound reports that a query for one row matched none. ErrNotFound = errors.New("ant: not found") // ErrMultipleRows reports that Single matched more than one row. ErrMultipleRows = errors.New("ant: query matched more than one row") // ErrNotImplemented reports a feature with no implementation yet. ErrNotImplemented = errs.ErrNotImplemented // ErrUnsupported reports something the connected database cannot do, such as // MERGE on MySQL. dialect.Supports asks in advance. ErrUnsupported = errs.ErrUnsupported // ErrNotProbe reports a field pointer that does not come from Fields. ErrNotProbe = errors.New("ant: pointer is not a field of a probe from ant.Fields") // ErrNotColumn reports a probe field that is a relation, used as a column. ErrNotColumn = errors.New("ant: field is a relation, not a column") // ErrNotRelation reports a probe field that is not a relation. ErrNotRelation = errors.New("ant: field is not a relation") // ErrWrongModel reports a probe from a model the query does not use. ErrWrongModel = errors.New("ant: field belongs to a model outside this query") // ErrNoContext reports a type passed to Open that does not embed Context. ErrNoContext = errors.New("ant: type does not embed ant.Context") // ErrNotOpen reports a table or context that did not come from Open. ErrNotOpen = errors.New("ant: context is not open") // ErrNoKey reports a key operation on a model with no primary key. ErrNoKey = errors.New("ant: model has no primary key") // ErrKeyType reports a key whose type does not match the primary key. ErrKeyType = errors.New("ant: key type does not match the primary key") // ErrNoForeignKey reports a relation whose foreign key cannot be found by // convention. Name it in Configure. ErrNoForeignKey = errs.ErrNoForeignKey // ErrNoColumnType reports a field whose database type cannot be worked out // from its Go type. Set it with Column(...).Type(...). ErrNoColumnType = errors.New("ant: no database type for field") // ErrBadSchema reports models that cannot become a valid schema. ErrBadSchema = errors.New("ant: invalid schema") // ErrUnknownColumn reports a result column with no field, under WithStrict. ErrUnknownColumn = errors.New("ant: result column has no field") // ErrNoRows reports an operation given no rows to work on. ErrNoRows = errors.New("ant: no rows given") // ErrNilEntity reports a nil pointer passed to a write. ErrNilEntity = errors.New("ant: entity is nil") // ErrNoCondition reports a bulk write with no condition. Call Unfiltered // to affect every row on purpose. ErrNoCondition = errors.New("ant: bulk write has no condition") // ErrNoAssignment reports an Update with nothing to set. ErrNoAssignment = errors.New("ant: update has no assignments") // ErrThenWithoutOrder reports ThenBy on a query with no OrderBy. ErrThenWithoutOrder = errors.New("ant: ThenBy needs a preceding OrderBy") // ErrIncludeInEach reports Include with Each, which would need a second // query while rows stream. Use All, or Chunk for large results. ErrIncludeInEach = errors.New("ant: Each does not support Include") // ErrConcurrency reports that SaveChanges found a row changed or removed // since it was loaded. Nothing was saved. ErrConcurrency = errors.New("ant: row was changed or removed since it was loaded") // ErrKeyChanged reports a tracked entity whose primary key was modified. A // key identifies the row, so use a new entity instead. ErrKeyChanged = errors.New("ant: primary key of a tracked entity was changed") // ErrCycle reports new entities that depend on each other, so neither can // be inserted first. Save them in two steps. ErrCycle = errors.New("ant: new entities depend on each other") // ErrNotTracked reports an operation on an entity the context is not // tracking. ErrNotTracked = errors.New("ant: entity is not tracked") // ErrNotInTx reports Commit, Rollback, or a savepoint outside a transaction. ErrNotInTx = errors.New("ant: not in a transaction") // ErrTxDone reports use of a transaction after it ended. ErrTxDone = errors.New("ant: transaction has ended") // ErrTxType reports a Tx closure whose parameter is not this context's type. ErrTxType = errors.New("ant: Tx closure takes a different context type") // ErrIncludeInSubquery reports a query with Include used as a subquery. ErrIncludeInSubquery = errors.New("ant: subquery cannot use Include") // ErrCursor reports a cursor that this query cannot use. ErrCursor = errors.New("ant: invalid cursor") // ErrNotManyToMany reports a link operation on another kind of relation. ErrNotManyToMany = errors.New("ant: relation is not many-to-many") // ErrReadOnly reports a write to a read-only model, such as a view. ErrReadOnly = errors.New("ant: model is read-only") // ErrNotSoftDeleted reports Restore on a model with no DeletedAt field. ErrNotSoftDeleted = errors.New("ant: model has no DeletedAt field") // ErrNoColumns reports a query whose selection leaves no columns. ErrNoColumns = errors.New("ant: query selects no columns") )
Errors returned by terminal calls.
Functions ¶
func Begin ¶
Begin starts a transaction and returns a context bound to it. End it with Commit or Rollback. Prefer Context.Tx, which cannot leave one open.
func Clone ¶
func Clone[T any](entity *T) *T
Clone returns a copy of entity with its key and relations cleared, ready to be inserted as a new row.
func CurrentTx ¶
CurrentTx returns the transaction a context is bound to, or nil. Pass it to UseTx to share one transaction between contexts of different types.
func FailedSQL ¶
FailedSQL returns the statement behind a query error, or "". Values are not in it, only their placeholders, so it is safe for an internal log.
func Fields ¶
func Fields[T any]() *T
Fields returns a probe for T. A probe holds no data. Its field addresses identify columns, so &U.Age names the age column of User:
var U = ant.Fields[User]()
Declare one probe per model at package level.
func GenerateKey ¶
func GenerateKey[E, V any](b *ModelBuilder[E], field *V, fn func() V)
GenerateKey sets a primary key that fn fills in Go when it is zero, such as a UUID.
func IsCheckViolation ¶
IsCheckViolation reports whether err is a check constraint failure.
func IsDirty ¶
func IsDirty[T, V any](e *EntityEntry[T], field *V) bool
IsDirty reports whether a field differs from what was loaded.
func IsForeignKeyViolation ¶
IsForeignKeyViolation reports whether err is a foreign key failure.
func IsNotNullViolation ¶
IsNotNullViolation reports whether err is a NOT NULL failure.
func IsRetryable ¶
IsRetryable reports whether a transaction failed from a deadlock or a serialization conflict, and would likely work if run again.
func IsUniqueViolation ¶
IsUniqueViolation reports whether err is a unique constraint failure.
func Link ¶
Link adds rows to a many-to-many relation's join table, skipping pairs that are already there. It does not change owner's relation field.
func MarkModified ¶
MarkModified makes the next SaveChanges write every field of an entity. Use it for a disconnected entity whose earlier values are unknown.
func Open ¶
func Open[DB any]( ctx context.Context, d dialect.Dialect, dsn string, options ...Option, ) (*DB, error)
Open connects to a database and returns a populated context. DB must be a struct that embeds Context. The application imports the database driver.
func Original ¶
func Original[T, V any](e *EntityEntry[T], field *V) (V, error)
Original returns a field's value as it was loaded. It returns ErrNotTracked for an entity with no loaded values.
func Pointers ¶
func Pointers[T any](values []T) []*T
Pointers returns pointers to the elements of values, for passing a slice of values to Load.
func SQLState ¶
SQLState returns the database's error code for err, or "". Dialects translate their own codes to SQLSTATE, so one value means one thing on every database.
func SchemaOf ¶
SchemaOf returns the schema DB's models describe: its Table fields, and models reached through their relations. It needs no connection. Views and models excluded from migrations have no table in the result.
func Session ¶
Session returns a new context on the same connections with its own tracker, which suits one unit of work, such as one web request. Tracking on a long-lived context grows without end, so prefer a session per request.
A session takes its settings from db, and options change them for the session. An application that keeps tracking off on its shared context passes WithTracking(true) to the sessions that use SaveChanges, which otherwise has nothing to save.
func TrackGraph ¶
TrackGraph walks a graph that came from outside, such as a request body, and tracks each entity in the state decide returns for it. Returning Detached skips the entity and everything below it. It is the way to save a tree whose earlier values are unknown:
ant.TrackGraph(db, order, func(n ant.GraphNode) ant.State {
if n.HasKey {
return ant.Modified
}
return ant.Added
})
err := db.SaveChanges(ctx)
Foreign keys between the entities are filled in by SaveChanges.
func Unlink ¶
Unlink removes rows from a many-to-many relation's join table. The targets themselves stay.
func UseConn ¶
UseConn returns a context on one connection from database/sql, such as one holding a session setting or an advisory lock. Everything it does, including transactions, stays on conn. It shares db's tracker. The caller closes conn.
func UseTx ¶
UseTx returns a context bound to a transaction started outside ant, so that ant's queries can join it. The caller commits or rolls back tx. Observers wait for a commit that ant cannot see, so they do not run.
func Watch ¶
Watch returns a context that counts statements for Diagnostics. Use one per request, in middleware.
func WithoutHooks ¶
WithoutHooks skips model hooks for writes made with ctx.
Types ¶
type Action ¶
Action is what happens to dependent rows when their parent is deleted or its key changes.
type AfterDeleter ¶
AfterDeleter runs after an entity is deleted.
type AfterIncluder ¶
AfterIncluder runs on each entity a query returns, after Include, so its relations are there.
type AfterInserter ¶
AfterInserter runs after an entity is inserted.
type AfterLoader ¶
AfterLoader runs on each entity a query returns, before Include.
type AfterUpdater ¶
AfterUpdater runs after an entity is updated.
type Assignment ¶
type Assignment struct {
// contains filtered or unexported fields
}
Assignment sets a column in a bulk update.
func Dec ¶
func Dec[V Number](field *V, n V) Assignment
Dec subtracts n from a numeric column, in the database.
func Inc ¶
func Inc[V Number](field *V, n V) Assignment
Inc adds n to a numeric column, in the database.
func Set ¶
func Set[V any](field *V, v V) Assignment
Set assigns v to field. Zero values are written like any other value.
func SetExpr ¶
func SetExpr[V any](field *V, value Expr[V]) Assignment
SetExpr assigns an expression to field, such as another column.
type Base ¶
Base is an optional embeddable model base. ID is a generated primary key. Any model's time.Time fields named CreatedAt and UpdatedAt are maintained for it.
type BeforeDeleter ¶
BeforeDeleter runs before an entity is deleted.
type BeforeInserter ¶
BeforeInserter runs before an entity is inserted.
type BeforeUpdater ¶
BeforeUpdater runs before a changed entity is updated. Changes it makes are saved too.
type CaseExpr ¶
type CaseExpr[V any] struct { // contains filtered or unexported fields }
CaseExpr builds a CASE expression. See Case.
func Case ¶
Case starts a CASE expression:
ant.Case[string]().When(ant.Lt(&U.Age, 18), "minor").Else("adult")
func (CaseExpr[V]) ElseExpr ¶
ElseExpr finishes the expression, with an expression for rows no branch matched.
type Change ¶
type Change struct {
Model string
State State
Entity any // a pointer to the entity
Changed []string // field names, for an update
}
Change describes one entity a SaveChanges is about to write.
type ColumnBuilder ¶
type ColumnBuilder struct {
// contains filtered or unexported fields
}
ColumnBuilder configures how a column is declared in migrations. Queries are not affected, except by Default and Generated, which say where a value comes from.
func (*ColumnBuilder) Collation ¶
func (c *ColumnBuilder) Collation(name string) *ColumnBuilder
Collation sets the column's collation.
func (*ColumnBuilder) Comment ¶
func (c *ColumnBuilder) Comment(text string) *ColumnBuilder
Comment describes the column in the database.
func (*ColumnBuilder) Default ¶
func (c *ColumnBuilder) Default(expr string) *ColumnBuilder
Default sets the column's default, a SQL expression such as now() or 'draft'. As with the ant:"default" tag, a zero field is left for the database to fill.
func (*ColumnBuilder) Enum ¶
func (c *ColumnBuilder) Enum(name string, values ...string) *ColumnBuilder
Enum stores the column as a native enum type, which migrations create and extend. Removing a value takes a migration by hand, since rows may hold it.
func (*ColumnBuilder) Fixed ¶
func (c *ColumnBuilder) Fixed(n int) *ColumnBuilder
Fixed makes a string column exactly n characters.
func (*ColumnBuilder) Generated ¶
func (c *ColumnBuilder) Generated(expr string) *ColumnBuilder
Generated makes the column a stored generated column, computed by the database from expr. The field is read-only.
func (*ColumnBuilder) Length ¶
func (c *ColumnBuilder) Length(n int) *ColumnBuilder
Length limits a string column to n characters.
func (*ColumnBuilder) NotNull ¶
func (c *ColumnBuilder) NotNull() *ColumnBuilder
NotNull refuses NULL in a column whose Go type could hold it.
func (*ColumnBuilder) Nullable ¶
func (c *ColumnBuilder) Nullable() *ColumnBuilder
Nullable allows NULL in a column whose Go type has no way to hold it.
func (*ColumnBuilder) Precision ¶
func (c *ColumnBuilder) Precision(precision, scale int) *ColumnBuilder
Precision makes the column an exact number with the given digits in total and after the point.
func (*ColumnBuilder) Sensitive ¶
func (c *ColumnBuilder) Sensitive() *ColumnBuilder
Sensitive keeps the column's values out of logs, even with LogValues.
func (*ColumnBuilder) Sequence ¶
func (c *ColumnBuilder) Sequence(name string, options ...SequenceOption) *ColumnBuilder
Sequence fills the column from a database sequence, which migrations create. As with Default, a zero field is left for the database.
func (*ColumnBuilder) Type ¶
func (c *ColumnBuilder) Type(sql string) *ColumnBuilder
Type sets the database type, written as it would be in SQL. It overrides the type that comes from the Go type, and is how a custom Go type joins migrations.
func (*ColumnBuilder) Unique ¶
func (c *ColumnBuilder) Unique(name ...string) *ColumnBuilder
Unique adds a unique constraint on the column, like the ant:"unique" tag. An optional name replaces table_column_key.
type ConcurrencyError ¶
ConcurrencyError is the ErrConcurrency from SaveChanges, naming the row.
func (*ConcurrencyError) Unwrap ¶
func (e *ConcurrencyError) Unwrap() error
Unwrap makes errors.Is(err, ErrConcurrency) true.
type Cond ¶
type Cond struct {
// contains filtered or unexported fields
}
Cond is a query condition. Errors in a condition surface at the terminal call of the query that uses it.
func AllOf ¶
func AllOf[V comparable](v V, fields ...*V) Cond
AllOf matches rows where every one of fields equals v.
func And ¶
And matches rows where every condition matches. With no conditions, it matches everything.
func AnyOf ¶
func AnyOf[V comparable](v V, fields ...*V) Cond
AnyOf matches rows where at least one of fields equals v.
func Eq ¶
func Eq[V comparable](field *V, v V) Cond
Eq matches rows where field equals v. A v stored as NULL, such as a nil pointer, matches NULL. A non-nil pointer compares the pointed-to value.
Example ¶
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/skudra-go/ant"
"github.com/skudra-go/ant/dialect/postgres"
)
type User struct {
ant.Base
Name string
Email string `ant:"unique"`
Age int
Bio *string
Posts []Post
}
type Post struct {
ant.Base
UserID int64
Title string
Published bool
User *User
}
type AppDB struct {
ant.Context
Users ant.Table[User]
Posts ant.Table[Post]
}
var Us = ant.Fields[User]()
func db() *AppDB {
pool, err := sql.Open("pgx", "postgres://nobody@127.0.0.1:1/none")
if err != nil {
log.Fatal(err)
}
out, err := ant.Wrap[AppDB](postgres.Dialect, pool)
if err != nil {
log.Fatal(err)
}
return out
}
func show(text string, args []any, err error) {
if err != nil {
log.Fatal(err)
}
fmt.Println(text)
fmt.Println(args)
}
func main() {
show(db().Users.Where(ant.Eq(&Us.Name, "Ada")).ToSQL())
}
Output: SELECT "users"."id", "users"."created_at", "users"."updated_at", "users"."name", "users"."email", "users"."age", "users"."bio" FROM "users" WHERE "users"."name" = $1 [Ada]
func Exists ¶
func Exists(q Selectable) Cond
Exists matches rows for which q returns anything. Conditions in q can refer to the outer query's models.
func FailedCond ¶
FailedCond returns a condition that reports err at the terminal call, for use by condition helpers that can fail.
func Has ¶
Has matches rows with at least one related row in a one-to-many relation that meets conds. Build it at run time, not in a package variable, because it needs the related model's configuration.
Example ¶
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/skudra-go/ant"
"github.com/skudra-go/ant/dialect/postgres"
)
type User struct {
ant.Base
Name string
Email string `ant:"unique"`
Age int
Bio *string
Posts []Post
}
type Post struct {
ant.Base
UserID int64
Title string
Published bool
User *User
}
type AppDB struct {
ant.Context
Users ant.Table[User]
Posts ant.Table[Post]
}
var (
Us = ant.Fields[User]()
Ps = ant.Fields[Post]()
)
func db() *AppDB {
pool, err := sql.Open("pgx", "postgres://nobody@127.0.0.1:1/none")
if err != nil {
log.Fatal(err)
}
out, err := ant.Wrap[AppDB](postgres.Dialect, pool)
if err != nil {
log.Fatal(err)
}
return out
}
func show(text string, args []any, err error) {
if err != nil {
log.Fatal(err)
}
fmt.Println(text)
fmt.Println(args)
}
func main() {
show(db().Users.Column(&Us.ID).Where(ant.Has(&Us.Posts, ant.Eq(&Ps.Published, true))).ToSQL())
}
Output: SELECT "users"."id" FROM "users" WHERE EXISTS (SELECT 1 FROM "posts" AS "ant_related" WHERE "ant_related"."user_id" = "users"."id" AND ("ant_related"."published" = $1)) [true]
func HasOne ¶
HasOne matches rows with a related row in a many-to-one or one-to-one relation that meets conds. See Has.
func In ¶
func In[V comparable](field *V, values ...V) Cond
In matches rows where field equals one of values. With no values, it matches nothing.
Example ¶
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/skudra-go/ant"
"github.com/skudra-go/ant/dialect/postgres"
)
type User struct {
ant.Base
Name string
Email string `ant:"unique"`
Age int
Bio *string
Posts []Post
}
type Post struct {
ant.Base
UserID int64
Title string
Published bool
User *User
}
type AppDB struct {
ant.Context
Users ant.Table[User]
Posts ant.Table[Post]
}
var Us = ant.Fields[User]()
func db() *AppDB {
pool, err := sql.Open("pgx", "postgres://nobody@127.0.0.1:1/none")
if err != nil {
log.Fatal(err)
}
out, err := ant.Wrap[AppDB](postgres.Dialect, pool)
if err != nil {
log.Fatal(err)
}
return out
}
func show(text string, args []any, err error) {
if err != nil {
log.Fatal(err)
}
fmt.Println(text)
fmt.Println(args)
}
func main() {
show(db().Users.Column(&Us.ID).Where(ant.In(&Us.Age, 18, 21)).ToSQL())
}
Output: SELECT "users"."id" FROM "users" WHERE "users"."age" IN ($1, $2) [18 21]
func InTuples ¶
InTuples matches rows whose columns, taken together, equal one of the tuples:
ant.InTuples([]ant.FieldRef{ant.F(&O.Region), ant.F(&O.Number)},
[]any{"eu", 1}, []any{"us", 7})
As with In, an empty list matches nothing.
func Like ¶
Like matches rows where field matches a SQL LIKE pattern, in which % matches any text and _ matches one character.
func Ne ¶
func Ne[V comparable](field *V, v V) Cond
Ne matches rows where field does not equal v. A v stored as NULL matches non-NULL values. As in SQL, a NULL column never matches a non-NULL v.
func NoneOf ¶
func NoneOf[V comparable](v V, fields ...*V) Cond
NoneOf matches rows where none of fields equals v.
func NotExists ¶
func NotExists(q Selectable) Cond
NotExists matches rows for which q returns nothing.
func NotIn ¶
func NotIn[V comparable](field *V, values ...V) Cond
NotIn matches rows where field equals none of values. With no values, it matches everything, including NULL.
func NotInSub ¶
NotInSub matches rows where field is none of the subquery's values. As in SQL, a NULL among the values means nothing matches.
func Or ¶
Or matches rows where any condition matches. With no conditions, it matches nothing.
Example ¶
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/skudra-go/ant"
"github.com/skudra-go/ant/dialect/postgres"
)
type User struct {
ant.Base
Name string
Email string `ant:"unique"`
Age int
Bio *string
Posts []Post
}
type Post struct {
ant.Base
UserID int64
Title string
Published bool
User *User
}
type AppDB struct {
ant.Context
Users ant.Table[User]
Posts ant.Table[Post]
}
var Us = ant.Fields[User]()
func db() *AppDB {
pool, err := sql.Open("pgx", "postgres://nobody@127.0.0.1:1/none")
if err != nil {
log.Fatal(err)
}
out, err := ant.Wrap[AppDB](postgres.Dialect, pool)
if err != nil {
log.Fatal(err)
}
return out
}
func show(text string, args []any, err error) {
if err != nil {
log.Fatal(err)
}
fmt.Println(text)
fmt.Println(args)
}
func main() {
show(db().Users.Column(&Us.ID).Where(ant.Or(ant.Lt(&Us.Age, 18), ant.IsNull(&Us.Bio))).ToSQL())
}
Output: SELECT "users"."id" FROM "users" WHERE ("users"."age" < $1 OR "users"."bio" IS NULL) [18]
type Conflict ¶
type Conflict struct {
// contains filtered or unexported fields
}
Conflict says what to do when an insert hits a unique constraint. Start one with OnConflict.
func OnConflict ¶
OnConflict names the column of the unique constraint. Add more with And.
func (*Conflict) DoUpdate ¶
DoUpdate overwrites only the named columns of the existing row. By default, every column except the key and the constraint's own is overwritten.
func (*Conflict) Set ¶
func (c *Conflict) Set(assignments ...Assignment) *Conflict
Set assigns values on conflict, as well as any named in DoUpdate.
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
Context is embedded in a user's database struct. Its methods are promoted, so they are called directly on that struct.
func (*Context) ClearTracked ¶
func (c *Context) ClearTracked()
ClearTracked stops tracking everything, forgetting unsaved changes.
func (*Context) Close ¶
Close closes the underlying connection pool, for every context that shares it.
func (*Context) DebugTracked ¶
DebugTracked describes every tracked entity, for logs and debugging.
func (*Context) EnsureCreated ¶
EnsureCreated creates the tables, indexes, and foreign keys of models that have no table yet, directly from the structs, and leaves existing tables as they are. It is for tests and prototypes. Use migrations for anything with data to keep.
func (*Context) EnsureDeleted ¶
EnsureDeleted drops the tables of the context's models, with their data and whatever depends on them. It is for tests.
func (*Context) HasChanges ¶
HasChanges reports whether SaveChanges has anything to write.
func (*Context) RollbackTo ¶
RollbackTo undoes the statements since a savepoint. The tracker is not rewound, so reload entities whose changes it undid.
func (*Context) SaveChanges ¶
SaveChanges writes every change to tracked entities in one transaction: inserts and updates with parents first, then deletes with children first. It updates only the columns that changed. If anything fails, nothing is saved and the tracker keeps its pending changes, so the call can be retried.
func (*Context) Tx ¶
Tx runs f in a transaction, passing a context of the same type bound to it. The transaction commits if f returns nil, and rolls back if it returns an error or panics. Inside a transaction, Tx uses a savepoint instead, so only the inner part rolls back. The context shares this one's tracker, and a rollback restores the tracker's view of what was saved.
type CursorPage ¶
type CursorPage[T any] struct { Items []*T // Next is the cursor for the following page, empty on the last page. Next string }
CursorPage is one page from After.
type DeletedAt ¶
DeletedAt is the type of a soft delete field. A model with one is marked deleted instead of removed, and queries skip such rows unless asked.
type Diagnostics ¶
type Diagnostics struct {
// Budget alerts when statements in a scope spend longer than this in total,
// which a slow-query log cannot see if each one is fast.
Budget time.Duration
// RepeatLimit alerts when one statement runs more than this many times in a
// scope, which is what an N+1 pattern looks like.
RepeatLimit int
// Alert receives warnings. The default logs them with slog.
Alert func(ctx context.Context, a Alert)
}
Diagnostics configures warnings about query patterns. They need a scope to count in, usually one web request: pass a context from Watch to the calls in it.
type Entity ¶
type Entity[E Entity[E]] interface { Configure(b *ModelBuilder[E]) }
Entity is implemented by models that override conventions. Configure runs once, when a context with the model opens, or on first use by Raw.
type EntityEntry ¶
type EntityEntry[T any] struct { // contains filtered or unexported fields }
EntityEntry inspects one entity's tracking state.
func Entry ¶
func Entry[T any](h Handle, entity *T) *EntityEntry[T]
Entry returns the tracking state of an entity. An untracked entity is Detached.
func (*EntityEntry[T]) Changed ¶
func (e *EntityEntry[T]) Changed() []string
Changed returns the names of the fields that differ from what was loaded.
func (*EntityEntry[T]) State ¶
func (e *EntityEntry[T]) State() State
State returns the entity's state, comparing it with what was loaded.
type Events ¶
type Events struct {
// Saving runs before SaveChanges writes.
Saving func(ctx context.Context, changes []Change)
// Saved runs after SaveChanges commits, or, in a transaction, after it wrote.
Saved func(ctx context.Context, changes []Change)
// SaveFailed runs when SaveChanges fails.
SaveFailed func(ctx context.Context, err error)
// Tracked runs when the tracker starts following an entity. It must not call
// back into the context.
Tracked func(model string, entity any)
// StateChanged runs when an entity is marked with a new state, such as by
// Remove. It must not call back into the context.
StateChanged func(model string, entity any, from, to State)
}
Events are callbacks on a context's unit of work. Interceptors watch statements, and observers watch one model, and these watch the unit of work as a whole. A nil callback is skipped. They cannot stop anything: use a SaveInterceptor for that.
type Expr ¶
type Expr[V any] struct { // contains filtered or unexported fields }
Expr is a typed SQL expression: a column, an aggregate, or a raw fragment. V is the Go type it produces, so comparisons and mappings are checked by the compiler.
func AvgRelated ¶
AvgRelated averages a field of the related rows. It is NULL if there are none.
func CountDistinct ¶
CountDistinct counts the different non-NULL values of field.
func CountRelated ¶
CountRelated counts the rows related through a one-to-many relation that meet conds. Use it with Query.With or in a Mapping.
func FailedExpr ¶
FailedExpr returns an expression that reports err at the terminal call, for helpers that can fail while building one.
func Func ¶
Func calls a database function by name. Arguments that are an Expr render inline, and any other is a bound value. The name is not quoted, so it must never come from untrusted input.
func MaxRelated ¶
MaxRelated returns the largest value of a field of the related rows. It is NULL if there are none.
func MinRelated ¶
MinRelated returns the smallest value of a field of the related rows. It is NULL if there are none.
func SQL ¶
SQL returns an expression from raw SQL. Each ? takes the next argument. An argument that is an Expr renders inline, and any other is a bound value. Never build the text from untrusted values.
func SumRelated ¶
SumRelated adds up a field of the related rows, giving zero if there are none.
func (Expr[V]) GtExpr ¶
GtExpr matches rows where the expression is greater than another expression.
type FieldConvention ¶
type FieldConvention struct {
Name string
Column string
Type reflect.Type
// contains filtered or unexported fields
}
FieldConvention is one column, offered to a rule from WithConvention.
func (*FieldConvention) SetLength ¶
func (f *FieldConvention) SetLength(n int)
SetLength limits a string column, as ColumnBuilder.Length does.
func (*FieldConvention) SetSensitive ¶
func (f *FieldConvention) SetSensitive()
SetSensitive keeps the column out of logs, as ColumnBuilder.Sensitive does.
func (*FieldConvention) SetType ¶
func (f *FieldConvention) SetType(sql string)
SetType sets the database type, as ColumnBuilder.Type does.
type FieldRef ¶
type FieldRef struct {
// contains filtered or unexported fields
}
FieldRef names a column of any type, from F.
type ForeignKeyBuilder ¶
type ForeignKeyBuilder struct {
// contains filtered or unexported fields
}
ForeignKeyBuilder configures a foreign key from ModelBuilder.ForeignKey.
func (*ForeignKeyBuilder) Name ¶
func (k *ForeignKeyBuilder) Name(name string) *ForeignKeyBuilder
Name names the constraint, in place of table_columns_fkey.
func (*ForeignKeyBuilder) NoIndex ¶
func (k *ForeignKeyBuilder) NoIndex() *ForeignKeyBuilder
NoIndex leaves out the index migrations otherwise add on the columns.
func (*ForeignKeyBuilder) OnDelete ¶
func (k *ForeignKeyBuilder) OnDelete(action Action) *ForeignKeyBuilder
OnDelete sets the action when the parent is deleted.
func (*ForeignKeyBuilder) OnUpdate ¶
func (k *ForeignKeyBuilder) OnUpdate(action Action) *ForeignKeyBuilder
OnUpdate sets the action when the parent's key changes.
func (*ForeignKeyBuilder) References ¶
func (k *ForeignKeyBuilder) References(fields ...FieldRef) *ForeignKeyBuilder
References names the columns the key points to, in order.
type Gob ¶
type Gob[V any] struct { V V }
Gob stores a Go value in a binary column with encoding/gob, for a value that only Go reads and JSON does not fit.
func (Gob[V]) ColumnType ¶
ColumnType implements schema.Typed.
type GraphNode ¶
type GraphNode struct {
Model string // the entity's type name
Entity any // a pointer to the entity
Parent any // a pointer to the entity it was reached from, or nil
// HasKey reports whether the entity has a key already, which usually means the
// row exists.
HasKey bool
}
GraphNode is one entity TrackGraph reached.
type Grouped ¶
type Grouped struct {
// contains filtered or unexported fields
}
Grouped is a query with GROUP BY. Read it with Project.
func (*Grouped) Having ¶
Having keeps groups that meet conds, which can use aggregates such as ant.Count().Gt(1).
type Handle ¶
type Handle interface {
// contains filtered or unexported methods
}
Handle is any value that embeds Context, such as a *AppDB.
type IndexBuilder ¶
type IndexBuilder struct {
// contains filtered or unexported fields
}
IndexBuilder configures an index.
func (*IndexBuilder) And ¶
func (i *IndexBuilder) And[V any](field *V) *IndexBuilder
And adds a column to the index.
func (*IndexBuilder) AndExpr ¶
func (i *IndexBuilder) AndExpr(expr string) *IndexBuilder
AndExpr adds a SQL expression to the index.
func (*IndexBuilder) Concurrently ¶
func (i *IndexBuilder) Concurrently() *IndexBuilder
Concurrently builds the index without blocking writes, when it is added to a table that already exists. PostgreSQL cannot do that in a transaction, so the migration holding it runs without one.
func (*IndexBuilder) Desc ¶
func (i *IndexBuilder) Desc() *IndexBuilder
Desc sorts the most recently added column in descending order.
func (*IndexBuilder) Include ¶
func (i *IndexBuilder) Include[V any](field *V) *IndexBuilder
Include stores a column in the index without indexing it.
func (*IndexBuilder) Name ¶
func (i *IndexBuilder) Name(name string) *IndexBuilder
Name sets the index name, in place of table_columns_idx.
func (*IndexBuilder) Unique ¶
func (i *IndexBuilder) Unique() *IndexBuilder
Unique makes the index unique.
func (*IndexBuilder) Using ¶
func (i *IndexBuilder) Using(method string) *IndexBuilder
Using sets the index method, such as gin.
func (*IndexBuilder) Where ¶
func (i *IndexBuilder) Where(condition string) *IndexBuilder
Where makes the index partial, covering rows that match a SQL condition.
type InsertOption ¶
type InsertOption func(*insertOptions)
InsertOption configures InsertMany.
func BatchSize ¶
func BatchSize(n int) InsertOption
BatchSize sets the most rows in one statement. The default is 1000.
func WithConflict ¶
func WithConflict(c *Conflict) InsertOption
WithConflict applies a Conflict to every row of InsertMany.
type Interceptor ¶
type Interceptor = exec.Interceptor
Interceptor observes every statement a context runs, for logging, metrics, and tracing. Before can return a new context, as tracing needs, and an error from it stops the statement.
type JSON ¶
type JSON[V any] struct { V V }
JSON stores a Go value in a JSON column. The zero value of V is stored as its JSON form, and a NULL column reads as the zero value.
func (JSON[V]) ColumnType ¶
ColumnType implements schema.Typed.
func (JSON[V]) MarshalJSON ¶
MarshalJSON writes the value inside, so that an API response shows the document and not this wrapper.
func (*JSON[V]) UnmarshalJSON ¶
UnmarshalJSON reads the value inside.
type Join2 ¶
type Join2[A, B any] struct { // contains filtered or unexported fields }
Join2 is a query across two joined models.
func JoinLateral ¶
JoinLateral joins a query that runs once per row of T, so its conditions can refer to T's columns. With Limit, this reads the top rows per parent, which a plain join cannot express:
ant.JoinLateral(db.Users.Query(), db.Posts. Where(ant.EqCol(&P.UserID, &U.ID)). OrderByDesc(&P.CreatedAt).Limit(3))
func JoinSub ¶
JoinSub joins the results of another query. Probes of J refer to its columns, so sub can filter, group, or limit first. Its global filters already applied.
func LeftJoinLateral ¶
LeftJoinLateral is JoinLateral, keeping rows of T with no match.
func LeftJoinSub ¶
LeftJoinSub is JoinSub, keeping rows of T with no match.
func (*Join2[A, B]) GroupByExpr ¶
GroupByExpr groups the joined rows by an expression.
func (*Join2[A, B]) Join ¶
Join adds a many-to-one or one-to-one relation of any model in the query.
func (*Join2[A, B]) LeftJoin ¶
LeftJoin adds a many-to-one or one-to-one relation, keeping unmatched rows.
func (*Join2[A, B]) LeftJoinMany ¶
LeftJoinMany adds a one-to-many relation, keeping rows with no related row.
func (*Join2[A, B]) LeftJoinOn ¶
LeftJoinOn adds a model on conditions, keeping unmatched rows.
func (*Join2[A, B]) Order ¶
Order orders results by terms from Asc and Desc, replacing any earlier ordering.
func (*Join2[A, B]) OrderBy ¶
OrderBy orders results by a field of any joined model, ascending, replacing any earlier ordering.
func (*Join2[A, B]) OrderByDesc ¶
OrderByDesc orders results by a field of any joined model, descending, replacing any earlier ordering.
func (*Join2[A, B]) Select ¶
func (j *Join2[A, B]) Select[R any](f func(*A, *B) R) *Projection[R]
Select projects each joined row through f. The join, filters, and ordering run in the database, and f runs in Go once per row. Every stored column of each model is fetched, because Go cannot inspect what f reads. Use Project to fetch only some columns. A side a left, right, or full join did not match is nil. Results are not tracked.
type Join3 ¶
type Join3[A, B, C any] struct { // contains filtered or unexported fields }
Join3 is a query across three joined models.
func (*Join3[A, B, C]) GroupByExpr ¶
GroupByExpr groups the joined rows by an expression.
func (*Join3[A, B, C]) Join ¶
Join adds a many-to-one or one-to-one relation of any model in the query.
func (*Join3[A, B, C]) LeftJoin ¶
LeftJoin adds a many-to-one or one-to-one relation, keeping unmatched rows.
func (*Join3[A, B, C]) LeftJoinMany ¶
LeftJoinMany adds a one-to-many relation, keeping rows with no related row.
func (*Join3[A, B, C]) LeftJoinOn ¶
LeftJoinOn adds a model on conditions, keeping unmatched rows.
func (*Join3[A, B, C]) Order ¶
Order orders results by terms from Asc and Desc, replacing any earlier ordering.
func (*Join3[A, B, C]) OrderBy ¶
OrderBy orders results by a field of any joined model, ascending, replacing any earlier ordering.
func (*Join3[A, B, C]) OrderByDesc ¶
OrderByDesc orders results by a field of any joined model, descending, replacing any earlier ordering.
func (*Join3[A, B, C]) Select ¶
func (j *Join3[A, B, C]) Select[R any](f func(*A, *B, *C) R) *Projection[R]
Select projects each joined row through f. The join, filters, and ordering run in the database, and f runs in Go once per row. Every stored column of each model is fetched, because Go cannot inspect what f reads. Use Project to fetch only some columns. A side a left, right, or full join did not match is nil. Results are not tracked.
type Join4 ¶
type Join4[A, B, C, D any] struct { // contains filtered or unexported fields }
Join4 is a query across four joined models.
func (*Join4[A, B, C, D]) GroupByExpr ¶
GroupByExpr groups the joined rows by an expression.
func (*Join4[A, B, C, D]) Order ¶
Order orders results by terms from Asc and Desc, replacing any earlier ordering.
func (*Join4[A, B, C, D]) OrderBy ¶
OrderBy orders results by a field of any joined model, ascending, replacing any earlier ordering.
func (*Join4[A, B, C, D]) OrderByDesc ¶
OrderByDesc orders results by a field of any joined model, descending, replacing any earlier ordering.
func (*Join4[A, B, C, D]) Select ¶
func (j *Join4[A, B, C, D]) Select[R any](f func(*A, *B, *C, *D) R) *Projection[R]
Select projects each joined row through f. The join, filters, and ordering run in the database, and f runs in Go once per row. Every stored column of each model is fetched, because Go cannot inspect what f reads. Use Project to fetch only some columns. A side a left, right, or full join did not match is nil. Results are not tracked.
type KeyBuilder ¶
type KeyBuilder struct {
// contains filtered or unexported fields
}
KeyBuilder configures a primary key.
func (*KeyBuilder) NotGenerated ¶
func (k *KeyBuilder) NotGenerated() *KeyBuilder
NotGenerated means the application always supplies the key, so a zero key is written as zero.
type LogOption ¶
type LogOption func(*logging)
LogOption configures WithLogger.
func LogValues ¶
func LogValues() LogOption
LogValues includes argument values in logs. They are left out by default, because they may be passwords or personal data.
func SlowThreshold ¶
SlowThreshold logs statements at or over d at warning level.
type Mapping ¶
type Mapping struct {
// contains filtered or unexported fields
}
Mapping sets one field of a projection, from Into or IntoExpr.
type Merger ¶
type Merger[T any] struct { // contains filtered or unexported fields }
Merger builds a MERGE. Start one with Merge.
func Merge ¶
Merge combines source rows into T's table, deciding per row what to do, which Upsert cannot: one statement can update, insert, and delete. Clauses run in the order added, and the first that fits a row wins. PostgreSQL has it from version 15.
ant.Merge(&db.Stock, db.Staged.Query(), ant.EqCol(&Stock.SKU, &Staged.SKU)). WhenMatchedIf(ant.Eq(&Staged.Count, 0)).Delete(). WhenMatched(ant.SetExpr(&Stock.Count, ant.Col(&Staged.Count))). WhenNotMatched(ant.Into(&Stock.SKU, &Staged.SKU), ant.Into(&Stock.Count, &Staged.Count)). Exec(ctx)
func (*Merger[T]) Delete ¶
Delete turns the last clause, which must have no assignments, into a delete.
func (*Merger[T]) WhenMatched ¶
func (m *Merger[T]) WhenMatched(set ...Assignment) *Merger[T]
WhenMatched updates target rows that have a source row.
func (*Merger[T]) WhenMatchedIf ¶
func (m *Merger[T]) WhenMatchedIf(c Cond, set ...Assignment) *Merger[T]
WhenMatchedIf updates matched rows that also meet a condition.
func (*Merger[T]) WhenNotMatched ¶
WhenNotMatched inserts source rows with no target row. Each mapping names a target column and the source value for it.
type Mixin ¶
type Mixin struct {
// contains filtered or unexported fields
}
Mixin configures whichever model embeds a MixinConfigurer.
func (*Mixin) Eq ¶
Eq is a condition on a column by name, for use in a Filter. It works in joins, as ant.Eq does, because it knows which table it belongs to.
func (*Mixin) Index ¶
func (m *Mixin) Index(columns ...string) *IndexBuilder
Index adds an index on columns of the model, named after them.
type MixinConfigurer ¶
type MixinConfigurer interface {
ConfigureMixin(m *Mixin)
}
MixinConfigurer is implemented by a struct meant to be embedded in many models, to add the configuration that goes with its fields. It works by column name, since it does not know which model embeds it.
type ModelBuilder ¶
type ModelBuilder[E any] struct { // contains filtered or unexported fields }
ModelBuilder collects configuration for model E. Errors surface from Open.
func (*ModelBuilder[E]) BelongsTo ¶
func (b *ModelBuilder[E]) BelongsTo[R any](rel **R) *RelationBuilder
BelongsTo configures a many-to-one relation.
func (*ModelBuilder[E]) Check ¶
func (b *ModelBuilder[E]) Check(name, expr string)
Check adds a check constraint. expr is SQL, as in age >= 0.
func (*ModelBuilder[E]) Column ¶
func (b *ModelBuilder[E]) Column[V any](field *V) *ColumnBuilder
Column configures how a column is declared in migrations.
func (*ModelBuilder[E]) Comment ¶
func (b *ModelBuilder[E]) Comment(text string)
Comment describes the table in the database.
func (*ModelBuilder[E]) Comparer ¶
func (b *ModelBuilder[E]) Comparer[V any](field *V, equal func(a, b V) bool)
Comparer sets how change tracking compares a field, in place of a deep comparison. It suits a slice whose order does not matter, or a map with volatile entries. A change the comparer does not see is not saved.
func (*ModelBuilder[E]) CompositeKey ¶
func (b *ModelBuilder[E]) CompositeKey(fields ...FieldRef)
CompositeKey sets a primary key of several columns. Rows are read with FindKey.
func (*ModelBuilder[E]) Discriminator ¶
func (b *ModelBuilder[E]) Discriminator[V comparable](field *V, value V)
Discriminator shares a table between several models: rows of this one hold value in field. Queries see only those rows, and inserts set it. It is single-table inheritance, without the inheritance Go does not have:
func (Dog) Configure(b *ant.ModelBuilder[Dog]) {
b.Table("animals")
b.Discriminator(&D.Kind, "dog")
}
Migrations merge the models into one table, and a column only some of them declare allows NULL.
func (*ModelBuilder[E]) ExcludeFromMigrations ¶
func (b *ModelBuilder[E]) ExcludeFromMigrations()
ExcludeFromMigrations means migrations leave this model's table alone, because something else owns it. Queries still work.
func (*ModelBuilder[E]) Filter ¶
func (b *ModelBuilder[E]) Filter(name string, filter func(context.Context) Cond)
Filter adds a global filter, applied to every query of this model, including joins and subqueries. It receives the call's context, which suits tenancy. A filter that returns a Cond with an error fails the query. Query.IgnoreFilters switches it off.
func (*ModelBuilder[E]) ForeignKey ¶
func (b *ModelBuilder[E]) ForeignKey(fields ...FieldRef) *ForeignKeyBuilder
ForeignKey declares a foreign key on its own, for one no relation can express, such as a key of several columns. It adds a constraint and nothing else, so relations and queries do not know about it.
b.ForeignKey(ant.F(&L.OrderID), ant.F(&L.Region)).References(ant.F(&O.ID), ant.F(&O.Region))
func (*ModelBuilder[E]) HasMany ¶
func (b *ModelBuilder[E]) HasMany[R any]( rel *[]R, ) *RelationBuilder
HasMany configures a one-to-many relation.
func (*ModelBuilder[E]) HasManyThrough ¶
func (b *ModelBuilder[E]) HasManyThrough[R, A, C any]( rel *[]R, parentKey *A, throughKey *C, ) *RelationBuilder
HasManyThrough configures a read-only relation that crosses a table in between: a Country has many Posts through Users. parentKey is the column on the middle model that refers to the owner, and throughKey the column on the target that refers to the middle model's key.
b.HasManyThrough(&C.Posts, &U.CountryID, &P.UserID)
func (*ModelBuilder[E]) HasOne ¶
func (b *ModelBuilder[E]) HasOne[R any]( rel **R, ) *RelationBuilder
HasOne configures a one-to-one relation.
func (*ModelBuilder[E]) HasOneThrough ¶
func (b *ModelBuilder[E]) HasOneThrough[R, A, C any]( rel **R, parentKey *A, throughKey *C, ) *RelationBuilder
HasOneThrough is HasManyThrough for a single related row.
func (*ModelBuilder[E]) Index ¶
func (b *ModelBuilder[E]) Index[V any](field *V) *IndexBuilder
Index declares an index on field. Add more columns with And, and more options with the other IndexBuilder methods.
func (*ModelBuilder[E]) IndexExpr ¶
func (b *ModelBuilder[E]) IndexExpr(expr string) *IndexBuilder
IndexExpr declares an index on a SQL expression, such as lower(email). Name it with Name.
func (*ModelBuilder[E]) Key ¶
func (b *ModelBuilder[E]) Key[V any](field *V) *KeyBuilder
Key sets the primary key. An integer key is database-generated unless NotGenerated says otherwise.
func (*ModelBuilder[E]) KeyName ¶
func (b *ModelBuilder[E]) KeyName(name string)
KeyName names the primary key constraint, in place of table_pkey. It is for matching an existing database.
func (*ModelBuilder[E]) ManyToMany ¶
func (b *ModelBuilder[E]) ManyToMany[R any](rel *[]R) *RelationBuilder
ManyToMany configures a many-to-many relation through a join table, named with Through. Its columns default to the singular model names plus _id, such as user_id and role_id. For extra columns on the join table, model it instead and use two one-to-many relations.
func (*ModelBuilder[E]) NoKey ¶
func (b *ModelBuilder[E]) NoKey()
NoKey removes the primary key, for rows with no identity.
func (*ModelBuilder[E]) NoTimestamps ¶
func (b *ModelBuilder[E]) NoTimestamps()
NoTimestamps stops CreatedAt and UpdatedAt being maintained.
func (*ModelBuilder[E]) PartitionByHash ¶
func (b *ModelBuilder[E]) PartitionByHash(fields ...FieldRef)
PartitionByHash declares the table partitioned by a hash of the columns.
func (*ModelBuilder[E]) PartitionByList ¶
func (b *ModelBuilder[E]) PartitionByList(fields ...FieldRef)
PartitionByList declares the table partitioned by lists of column values.
func (*ModelBuilder[E]) PartitionByRange ¶
func (b *ModelBuilder[E]) PartitionByRange(fields ...FieldRef)
PartitionByRange declares the table partitioned by ranges of the columns. A partitioned table's primary key and unique constraints must include them, so a time-partitioned table usually has CompositeKey(id, time). Migrations create the parent, and package postgres manages the partitions themselves. See postgres.Partitions.
func (*ModelBuilder[E]) Schema ¶
func (b *ModelBuilder[E]) Schema(name string)
Schema sets the database schema.
func (*ModelBuilder[E]) Table ¶
func (b *ModelBuilder[E]) Table(name string)
Table sets the table name.
func (*ModelBuilder[E]) Validate ¶
func (b *ModelBuilder[E]) Validate[V any](field *V, rule func(V) error)
Validate adds a rule for a field, checked before Insert and SaveChanges write it, as a Validate hook is. A failure is a *ValidationError. Rules do not run for bulk writes, which load no entities. Package validate has common ones.
func (*ModelBuilder[E]) View ¶
func (b *ModelBuilder[E]) View(name string)
View maps the model to a view, which can be queried but not written.
type ModelConvention ¶
type ModelConvention struct {
// contains filtered or unexported fields
}
ModelConvention is one model, offered to a rule from WithConvention.
func (*ModelConvention) Fields ¶
func (m *ModelConvention) Fields() []*FieldConvention
Fields returns the model's columns.
func (*ModelConvention) Name ¶
func (m *ModelConvention) Name() string
Name returns the model's type name.
func (*ModelConvention) SetTable ¶
func (m *ModelConvention) SetTable(name string)
SetTable changes the model's table name.
func (*ModelConvention) Table ¶
func (m *ModelConvention) Table() string
Table returns the model's table name.
type Naming ¶
Naming replaces the conventions that turn Go names into database names. A nil function keeps the convention. It receives the type or field name.
type Number ¶
type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
~float32 | ~float64
}
Number is a type that SUM and AVG accept.
type Observer ¶
type Observer[T any] struct { Inserted func(ctx context.Context, entity *T) Updated func(ctx context.Context, entity *T) Deleted func(ctx context.Context, entity *T) }
Observer receives entities after their change is committed, so it never sees a write that rolled back. It runs once per SaveChanges or Insert entity, after the outermost transaction ends, and cannot affect the write.
type Option ¶
type Option func(*settings)
Option configures a context in Open.
func WithConvention ¶
func WithConvention(rule func(*ModelConvention)) Option
WithConvention adds a rule applied to every model as it is configured, before its Configure method, which can override it. Metadata is global, so a process has one set of rules, added in the first Open.
ant.WithConvention(func(m *ant.ModelConvention) {
for _, f := range m.Fields() {
if f.Type.Kind() == reflect.String {
f.SetLength(255)
}
}
})
func WithDetailedErrors ¶
func WithDetailedErrors() Option
WithDetailedErrors adds the failing statement to every query error's message, which helps in development. SQL text can reveal a schema, and raw SQL can hold values, so leave it off where errors reach users. FailedSQL reads the statement from an error whether this is on or not.
func WithDiagnostics ¶
func WithDiagnostics(d Diagnostics) Option
WithDiagnostics turns on warnings. They cost a little per statement, and only count in contexts from Watch. Joining two one-to-many relations in one query multiplies its rows, and that warns too, with or without a scope.
func WithEvents ¶
WithEvents registers callbacks on the context and its sessions.
func WithInterceptor ¶
func WithInterceptor(i Interceptor) Option
WithInterceptor adds an interceptor. Several run in order, and After runs in reverse order.
func WithLogger ¶
WithLogger logs every statement to logger: failures at error level, slow ones at warning level, and the rest at debug level. Values are never logged unless LogValues asks.
func WithLooseScan ¶
func WithLooseScan() Option
WithLooseScan ignores result columns with no field. It is the default, and exists to say so where WithStrict is on for other contexts.
func WithNaming ¶
WithNaming sets a naming strategy, such as PascalCase table names for an existing database. Names set explicitly are kept. Metadata is global, and each model is named once, on first use, so a process has one strategy, set in the first Open.
func WithReplicas ¶
WithReplicas sends reads outside transactions to these pools in turn. Writes, locks, and transactions use the primary. Close closes them. A failing replica is an error for that read, not a retry elsewhere.
func WithRetry ¶
WithRetry applies a retry policy to every Tx and SaveChanges of this context, unless Attempts says otherwise for one call. The work must be safe to run again, so a function given to Tx should change nothing outside the database.
func WithStickyWrites ¶
WithStickyWrites sends a context's reads to the primary for d after each of its writes, so that replication lag cannot hide what it just wrote.
func WithStrict ¶
func WithStrict() Option
WithStrict makes a query fail if a result column has no field, which usually means a model has fallen behind the schema, or a SELECT * picked up something new.
func WithTracking ¶
WithTracking sets whether queries track what they load. It is on by default. Turn it off for contexts that only read, or that use explicit updates.
func WithoutAutoTx ¶
func WithoutAutoTx() Option
WithoutAutoTx stops SaveChanges and Insert from opening a transaction of their own, so a failure partway leaves earlier statements in place. Use it only to control transactions yourself, or where a transaction is unavailable.
type Ordered ¶
Ordered is a type with a database ordering. It extends cmp.Ordered with time.Time, which cmp.Ordered excludes.
type Outcome ¶
Outcome is what happened to a statement. Duration ends when the database answered, before rows are read.
type Page ¶
Page is one page of a query, with the totals needed to show paging links.
type Projection ¶
type Projection[R any] struct { // contains filtered or unexported fields }
Projection is a query that returns values of R. Results are not tracked.
func Project ¶
func Project[R any](q Selectable, mappings ...Mapping) *Projection[R]
Project selects only the mapped expressions, and scans them into R. Use it instead of Select to avoid fetching whole rows:
var S = ant.Fields[Summary]() ant.Project[Summary](db.Posts.Join(&P.User), ant.Into(&S.Author, &U.Name), ant.Into(&S.Title, &P.Title))
func (*Projection[R]) All ¶
func (p *Projection[R]) All(ctx context.Context) (out []R, err error)
All returns every projected row, as an empty slice if there are none.
type Query ¶
type Query[T any] struct { // contains filtered or unexported fields }
Query is a query for rows of T. Queries are immutable: every builder method returns a new query, so one can safely be the base of several others. Terminal methods run it.
func FromFunc ¶
FromFunc reads from a table-valued function, written with ? for its arguments, as in generate_series(?, ?). Name its result columns if they differ from T's: unnest(?) AS "users"(name).
func FromRaw ¶
FromRaw returns a query over raw SQL, which conditions, ordering, and paging then build on. The SQL must return T's columns. Results are not tracked.
func Related ¶
Related returns a query for the rows related to entity through a one-to-many relation.
func RelatedOne ¶
RelatedOne returns a query for the row related to entity through a many-to-one or one-to-one relation.
func Values ¶
Values reads rows held in memory as if they were a table, for joining against a list or using it in a subquery. Each value takes the column's type, so this needs a dialect with migration support. Results are not tracked.
wanted := ant.Values(db, Wanted{ID: 1, Limit: 5}, Wanted{ID: 2, Limit: 9})
ant.JoinSub(db.Users.Query(), wanted, ant.EqCol(&U.ID, &W.ID))
func (*Query[T]) After ¶
After returns the page following cursor, which is empty for the first page. Each page costs the same however deep it is, and rows added meanwhile do not shift it. The ordering must use columns of this table that are never NULL. Pass Next from the previous page to continue.
func (*Query[T]) Chunk ¶
Chunk reads matching rows in groups of size, calling f with each until f returns an error or the rows run out. Paging uses Offset, so order the query and do not change matching rows in f. Use ChunkByKey when f changes them.
func (*Query[T]) ChunkByKey ¶
ChunkByKey reads matching rows in key order, in groups of size. It tracks its place by key, so f can change or delete the rows it receives.
func (*Query[T]) ClearOrder ¶
ClearOrder removes any ordering.
func (*Query[T]) Column ¶
Column limits the query to the named columns, and can be repeated. Other fields keep their zero value, so the results are never tracked.
func (*Query[T]) Count ¶
Count returns the number of matching rows. Limit, Offset, and Distinct are honored, by counting over a subquery.
func (*Query[T]) Debug ¶
Debug logs this query's SQL and values when it runs, at info level, through slog's default logger. It is for a moment of curiosity at a desk: unlike WithLogger, it shows values, so do not leave it in code.
func (*Query[T]) Delete ¶
Delete removes every matching row and returns the number removed. A model with a DeletedAt field is soft-deleted. With Limit or Offset, it removes only the rows the query selects. Tracked instances of those rows stay tracked, so prefer Remove with SaveChanges for loaded entities.
func (*Query[T]) DeleteReturning ¶
DeleteReturning is Delete, returning the removed rows.
func (*Query[T]) DeleteSQL ¶
DeleteSQL returns the statement Delete would run.
Example ¶
package main
import (
"context"
"database/sql"
"fmt"
"log"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/skudra-go/ant"
"github.com/skudra-go/ant/dialect/postgres"
)
type User struct {
ant.Base
Name string
Email string `ant:"unique"`
Age int
Bio *string
Posts []Post
}
type Post struct {
ant.Base
UserID int64
Title string
Published bool
User *User
}
type AppDB struct {
ant.Context
Users ant.Table[User]
Posts ant.Table[Post]
}
var Ps = ant.Fields[Post]()
func db() *AppDB {
pool, err := sql.Open("pgx", "postgres://nobody@127.0.0.1:1/none")
if err != nil {
log.Fatal(err)
}
out, err := ant.Wrap[AppDB](postgres.Dialect, pool)
if err != nil {
log.Fatal(err)
}
return out
}
func ctx() context.Context { return context.Background() }
func show(text string, args []any, err error) {
if err != nil {
log.Fatal(err)
}
fmt.Println(text)
fmt.Println(args)
}
func main() {
show(db().Posts.Where(ant.Eq(&Ps.Published, false)).DeleteSQL(ctx()))
}
Output: DELETE FROM "posts" WHERE "posts"."published" = $1 [false]
func (*Query[T]) DoesNotExist ¶
DoesNotExist reports whether no row matches.
func (*Query[T]) Each ¶
Each streams matching rows, stopping after the first error. Values are copies, so streamed rows are not tracked.
func (*Query[T]) Find ¶
func (q *Query[T]) Find[K comparable](ctx context.Context, key K) (*T, error)
Find returns the entity with the given primary key, within this query's conditions, or ErrNotFound.
func (*Query[T]) First ¶
First returns the first matching row, or ErrNotFound. Without an ordering, which row is first is up to the database.
func (*Query[T]) ForShare ¶
ForShare locks the selected rows against changes until the transaction ends, while allowing other readers.
func (*Query[T]) ForceDelete ¶
ForceDelete removes rows for real, even from a soft-deleted model. Use WithDeleted to reach rows that are already soft-deleted.
func (*Query[T]) From ¶
From reads from sub instead of the table. Conditions, ordering, and paging apply to its results, and they are not tracked.
func (*Query[T]) FullJoinOn ¶
FullJoinOn joins J on conditions, keeping unmatched rows of both.
func (*Query[T]) GroupBy ¶
GroupBy groups rows by a column. Add more with Then, and read the results with Project:
ant.Project[Stat](db.Posts.GroupBy(&P.UserID), ant.Into(&S.UserID, &P.UserID), ant.IntoExpr(&S.Posts, ant.Count()))
func (*Query[T]) GroupByExpr ¶
GroupByExpr groups rows by an expression.
func (*Query[T]) Hint ¶
Hint adds an optimizer hint, written /*+ hint */ before the statement, in the form extensions such as pg_hint_plan read. A database that does not know it sees a comment. Prefer fixing the query, since a hint outlives the reason for it.
func (*Query[T]) IgnoreFilters ¶
IgnoreFilters switches off the named global filters for this query, or all of them with no names. Related queries from Include keep theirs.
func (*Query[T]) Include ¶
Include loads a one-to-many relation in one extra query per relation, however many parents there are. Parents with no related rows get an empty slice, so a nil slice always means the relation was not loaded.
The optional function shapes the related query. It can filter, order, and limit, per parent, and call Include again for nested relations:
db.Users.Include(&U.Posts, func(q *ant.Query[Post]) *ant.Query[Post] {
return q.Where(ant.Eq(&P.Published, true)).OrderByDesc(&P.ID).Limit(3)
})
func (*Query[T]) IncludeJoined ¶
IncludeJoined loads a many-to-one or one-to-one relation in the same query, through a left join, instead of the extra query IncludeOne runs. It suits a relation most rows have, read often enough that a round trip matters. Parents with the same related row each get their own value unless tracked.
Example ¶
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/skudra-go/ant"
"github.com/skudra-go/ant/dialect/postgres"
)
type User struct {
ant.Base
Name string
Email string `ant:"unique"`
Age int
Bio *string
Posts []Post
}
type Post struct {
ant.Base
UserID int64
Title string
Published bool
User *User
}
type AppDB struct {
ant.Context
Users ant.Table[User]
Posts ant.Table[Post]
}
var Ps = ant.Fields[Post]()
func db() *AppDB {
pool, err := sql.Open("pgx", "postgres://nobody@127.0.0.1:1/none")
if err != nil {
log.Fatal(err)
}
out, err := ant.Wrap[AppDB](postgres.Dialect, pool)
if err != nil {
log.Fatal(err)
}
return out
}
func main() {
text, _, err := db().Posts.Column(&Ps.ID).IncludeJoined(&Ps.User).ToSQL()
if err != nil {
log.Fatal(err)
}
fmt.Println(text[:len("SELECT \"posts\".\"id\"")])
}
Output: SELECT "posts"."id"
func (*Query[T]) IncludeOne ¶
IncludeOne loads a many-to-one or one-to-one relation in one extra query. An unmatched relation stays nil. Parents with the same related row share one value. See Include for the optional function.
func (*Query[T]) Join ¶
Join joins through a many-to-one or one-to-one relation. Unmatched rows are dropped.
func (*Query[T]) JoinMany ¶
JoinMany joins through a one-to-many relation, with one result per related row.
func (*Query[T]) LeftJoin ¶
LeftJoin joins through a many-to-one or one-to-one relation, keeping unmatched rows. Their joined value is nil in Select.
func (*Query[T]) LeftJoinMany ¶
LeftJoinMany joins through a one-to-many relation, keeping rows with no related row.
func (*Query[T]) LeftJoinOn ¶
LeftJoinOn joins J on conditions, keeping unmatched rows of T.
func (*Query[T]) NoTracking ¶
NoTracking returns entities the change tracker does not see, including those from Include.
func (*Query[T]) NoTrackingResolved ¶
NoTrackingResolved is NoTracking, except that one row is one instance in the results, as it is with tracking. It suits a read-only query that joins or includes the same row many times, and costs less than tracking it.
func (*Query[T]) NoWait ¶
NoWait makes a lock fail at once instead of waiting for another transaction.
func (*Query[T]) Offset ¶
Offset skips the first n rows. Without an ordering, which rows are skipped is up to the database.
func (*Query[T]) Omit ¶
Omit leaves a column out of the query. Its field keeps its zero value, so the results are never tracked.
func (*Query[T]) OnlyDeleted ¶
OnlyDeleted returns only soft-deleted rows.
func (*Query[T]) Order ¶
Order orders results by terms from Asc and Desc, replacing any earlier ordering.
func (*Query[T]) OrderBy ¶
OrderBy orders results by field, ascending, replacing any earlier ordering.
func (*Query[T]) OrderByDesc ¶
OrderByDesc orders results by field, descending, replacing any earlier ordering.
Example ¶
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/skudra-go/ant"
"github.com/skudra-go/ant/dialect/postgres"
)
type User struct {
ant.Base
Name string
Email string `ant:"unique"`
Age int
Bio *string
Posts []Post
}
type Post struct {
ant.Base
UserID int64
Title string
Published bool
User *User
}
type AppDB struct {
ant.Context
Users ant.Table[User]
Posts ant.Table[Post]
}
var Us = ant.Fields[User]()
func db() *AppDB {
pool, err := sql.Open("pgx", "postgres://nobody@127.0.0.1:1/none")
if err != nil {
log.Fatal(err)
}
out, err := ant.Wrap[AppDB](postgres.Dialect, pool)
if err != nil {
log.Fatal(err)
}
return out
}
func show(text string, args []any, err error) {
if err != nil {
log.Fatal(err)
}
fmt.Println(text)
fmt.Println(args)
}
func main() {
show(db().Users.Column(&Us.ID).OrderByDesc(&Us.Age).ThenBy(&Us.Name).Limit(10).ToSQL())
}
Output: SELECT "users"."id" FROM "users" ORDER BY "users"."age" DESC, "users"."name" LIMIT $1 [10]
func (*Query[T]) OrderByRandom ¶
OrderByRandom shuffles the results.
func (*Query[T]) Page ¶
Page returns one page, counted from 1, with the total row count. Order the query, or pages may overlap. Use After for large tables, where counting and skipping rows gets slow.
func (*Query[T]) Recursive ¶
Recursive extends q with rows reached by repeatedly following a one-to-many relation of the same model, such as a folder and everything under it.
func (*Query[T]) RecursiveOne ¶
RecursiveOne extends q with rows reached by repeatedly following a many-to-one relation of the same model, such as a folder and all its ancestors.
func (*Query[T]) RightJoinOn ¶
RightJoinOn joins J on conditions, keeping unmatched rows of J. Their T value is nil in Select.
func (*Query[T]) Scope ¶
Scope applies reusable query logic:
func Adults(q *ant.Query[User]) *ant.Query[User] {
return q.Where(ant.Gte(&U.Age, 18))
}
db.Users.Query().Scope(Adults).All(ctx)
func (*Query[T]) Single ¶
Single returns the only matching row. It returns ErrNotFound if there are none, and ErrMultipleRows if there are several.
func (*Query[T]) SkipLocked ¶
SkipLocked leaves out rows that another transaction has locked, which suits job queues.
func (*Query[T]) ThenByDesc ¶
ThenByDesc adds a descending ordering after OrderBy.
func (*Query[T]) ToSQL ¶
ToSQL returns the SELECT this query would run. Global filters that need a context see an empty one.
func (*Query[T]) ToSQLContext ¶
ToSQLContext is ToSQL with global filters resolved against ctx.
func (*Query[T]) Unfiltered ¶
Unfiltered allows Update and Delete to affect every row. Without it, they return ErrNoCondition unless a condition can exclude rows, which an empty ant.And or ant.NotIn cannot.
func (*Query[T]) Union ¶
Union returns the rows of q or other, without duplicates. Conditions, ordering, and paging added afterward apply to the combined rows.
func (*Query[T]) Update ¶
Update applies assignments to every matching row and returns the number of rows changed. Zero values are written like any other value. With Limit or Offset, it changes only the rows the query selects.
func (*Query[T]) UpdateReturning ¶
func (q *Query[T]) UpdateReturning(ctx context.Context, a ...Assignment) ([]*T, error)
UpdateReturning is Update, returning the changed rows. They are not tracked.
func (*Query[T]) UpdateSQL ¶
UpdateSQL returns the statement Update would run, for sending it some other way, such as in a pipelined batch.
func (*Query[T]) With ¶
With fills a field tagged ant:"computed" from an expression, such as a count of related rows.
func (*Query[T]) WithDeleted ¶
WithDeleted includes soft-deleted rows.
type RawQuery ¶
type RawQuery[T any] struct { // contains filtered or unexported fields }
RawQuery is a raw SQL statement. Its text reaches the database as written, so pass values as arguments, never by building the text from them.
func Raw ¶
Raw prepares a raw SQL statement. Pass arguments in one of three forms: the dialect's placeholders such as $1, sql.Named arguments written @name, or portable ? marks. A slice inside IN (@ids) or IN (?) expands to its elements. See dialect.Bind for the exact rules.
T is what each row scans into. A struct takes columns by name, ignoring columns with no field, and need not be a model. A value type such as int takes a single column. T is unused by Exec, so ant.Raw[any] suits it.
func RawFile ¶
RawFile is Raw with the statement read from a file in fsys, such as an embed.FS. A file that cannot be read is an error at the terminal call.
func (*RawQuery[T]) All ¶
All runs the statement and returns every row, as an empty slice if there are none.
type RelationBuilder ¶
type RelationBuilder struct {
// contains filtered or unexported fields
}
RelationBuilder configures a relation.
func (*RelationBuilder) ConstraintName ¶
func (r *RelationBuilder) ConstraintName(name string) *RelationBuilder
ConstraintName names the foreign key, in place of table_column_fkey.
func (*RelationBuilder) ForeignKey ¶
func (r *RelationBuilder) ForeignKey[V any](field *V) *RelationBuilder
ForeignKey sets the foreign key column, on either model.
func (*RelationBuilder) Inverse ¶
func (r *RelationBuilder) Inverse[P any](back **P) *RelationBuilder
Inverse fills a pointer on each loaded child back to its parent, so a Post from Include(&U.Posts) has its User without another query.
func (*RelationBuilder) Latest ¶
func (r *RelationBuilder) Latest[V Ordered](field *V) *RelationBuilder
Latest makes a has-one relation the newest of many, by field: Include reads that row for each parent.
func (*RelationBuilder) Morph ¶
func (r *RelationBuilder) Morph[V comparable](field *V, value V) *RelationBuilder
Morph makes the relation polymorphic: the foreign key can refer to several tables, and field says which. Set it on each relation with the value for that target, which is also the place to keep a map of type names:
b.HasMany(&Post{}.Comments).ForeignKey(&C.OwnerID).Morph(&C.OwnerType, "post")
b.BelongsTo(&C.Post).ForeignKey(&C.OwnerID).Morph(&C.OwnerType, "post")
Saving through the relation sets field. A foreign key cannot point at several tables, so migrations declare none.
func (*RelationBuilder) NoForeignKey ¶
func (r *RelationBuilder) NoForeignKey() *RelationBuilder
NoForeignKey keeps the relation in queries and leaves its foreign key out of migrations. It suits a relation across databases, or a very busy table.
func (*RelationBuilder) NoIndex ¶
func (r *RelationBuilder) NoIndex() *RelationBuilder
NoIndex leaves out the index migrations otherwise add on the foreign key.
func (*RelationBuilder) Oldest ¶
func (r *RelationBuilder) Oldest[V Ordered](field *V) *RelationBuilder
Oldest makes a has-one relation the oldest of many, by field.
func (*RelationBuilder) OnDelete ¶
func (r *RelationBuilder) OnDelete(action Action) *RelationBuilder
OnDelete sets the action when the parent is deleted.
func (*RelationBuilder) OnUpdate ¶
func (r *RelationBuilder) OnUpdate(action Action) *RelationBuilder
OnUpdate sets the action when the parent's key changes.
func (*RelationBuilder) PivotColumns ¶
func (r *RelationBuilder) PivotColumns(local, foreign string) *RelationBuilder
PivotColumns names the join table's columns, for the owner and the target.
func (*RelationBuilder) References ¶
func (r *RelationBuilder) References[V any](field *V) *RelationBuilder
References sets the column the foreign key points to, in place of the primary key.
func (*RelationBuilder) Through ¶
func (r *RelationBuilder) Through(table string) *RelationBuilder
Through names the join table of a many-to-many relation.
func (*RelationBuilder) Touch ¶
func (r *RelationBuilder) Touch() *RelationBuilder
Touch updates the parent's UpdatedAt whenever SaveChanges writes this child, as a comment makes its post look recently active. Set it on the child's relation to the parent.
func (*RelationBuilder) Where ¶
func (r *RelationBuilder) Where(conds ...Cond) *RelationBuilder
Where scopes the relation: Include, Has, joins, and counts see only the target rows that meet conds.
b.HasMany(&U.LivePosts).ForeignKey(&P.UserID).Where(ant.Eq(&P.Published, true))
type Retry ¶
type Retry struct {
// Attempts is the number of runs in all.
Attempts int
}
Retry says how to run a transaction again after a deadlock or serialization failure, which a database reports when two transactions collide and only one can win.
type SaveInterceptor ¶
SaveInterceptor is an Interceptor that also sees each SaveChanges before it writes, for auditing. An error cancels the save.
type Selectable ¶
type Selectable interface {
// contains filtered or unexported methods
}
Selectable is a query that Project can read from.
type SequenceOption ¶
SequenceOption configures a sequence.
type Sort ¶
type Sort struct {
// contains filtered or unexported fields
}
Sort is one term of an ordering, from Asc or Desc.
func (Sort) NullsFirst ¶
NullsFirst sorts NULL values before all others.
type Statement ¶
Statement is one SQL statement on its way to the database. An interceptor can change it. Args holds real values, so take care what you record.
func DryRun ¶
DryRun runs fn in a transaction and rolls it back, returning every statement it ran. Nothing stays, though sequences move on, and whatever fn does outside the database still happens. It shows what a piece of code really does to a database, including what the unit of work decides to write.
type Sub ¶
type Sub[V any] struct { // contains filtered or unexported fields }
Sub is a query for one column of type V, for use in a condition or as a value.
func SubExpr ¶
func SubExpr[V any](q Selectable, value Expr[V]) Sub[V]
SubExpr makes q a subquery selecting an expression.
func SubOf ¶
func SubOf[V any](q Selectable, field *V) Sub[V]
SubOf makes q a subquery selecting field. A subquery can refer to models of the outer query in its conditions.
type Table ¶
type Table[T any] struct { // contains filtered or unexported fields }
Table is a typed entry point to one model. Declare Table fields on a struct that embeds Context, and Open populates them.
func (*Table[T]) DeleteByID ¶
func (t *Table[T]) DeleteByID[K comparable](ctx context.Context, key K) error
DeleteByID removes the entity with the given primary key, and stops tracking it, or returns ErrNotFound.
func (*Table[T]) Find ¶
func (t *Table[T]) Find[K comparable](ctx context.Context, key K) (*T, error)
Find returns the entity with the given primary key, or ErrNotFound. A tracked entity is returned without a query, with any unsaved changes.
func (*Table[T]) FindKey ¶
FindKey returns the entity with a composite primary key, given its parts in key order, or ErrNotFound.
func (*Table[T]) FirstOrCreate ¶
FirstOrCreate returns the first row that meets conds, or inserts e and returns it. If another writer inserts a matching row first and a unique constraint stops this insert, it returns that row. The bool reports whether e was created.
func (*Table[T]) FirstOrNew ¶
FirstOrNew returns the first row that meets conds, or e, not saved. The bool reports whether a row was found.
func (*Table[T]) FullJoinOn ¶
FullJoinOn starts a query fully joined on conditions.
func (*Table[T]) GroupByExpr ¶
GroupByExpr starts a query grouped by an expression.
func (*Table[T]) IgnoreFilters ¶
IgnoreFilters starts a query with the named global filters off.
func (*Table[T]) Include ¶
Include starts a query that loads a one-to-many relation. See Query.Include.
func (*Table[T]) IncludeJoined ¶
IncludeJoined starts a query that reads a relation in the same statement. See Query.IncludeJoined.
func (*Table[T]) IncludeOne ¶
IncludeOne starts a query that loads a many-to-one or one-to-one relation.
func (*Table[T]) Insert ¶
Insert writes entities and the new entities related to them, parents first, in one transaction, so either all are saved or none are. Generated keys and foreign keys are filled in. A zero value in a generated key means the database assigns it, and every other field is written as it is, zero or not. A related entity that already has a generated key is linked, not inserted.
func (*Table[T]) InsertFrom ¶
InsertFrom inserts the rows of a projection, and returns how many. The projection's mappings name the columns:
db.Archive.InsertFrom(ctx, ant.Project[Archive](db.Posts.Where(old), ant.Into(&A.Title, &P.Title)))
func (*Table[T]) InsertMany ¶
func (t *Table[T]) InsertMany( ctx context.Context, entities []*T, options ...InsertOption, ) (int64, error)
InsertMany writes many rows quickly, in multi-row statements inside one transaction, and returns how many were inserted. Unlike Insert, it ignores relations and does not track the rows. Generated keys are copied back, except with WithConflict, where rows may be skipped.
func (*Table[T]) InsertOnly ¶
InsertOnly writes entities and ignores their relation fields.
func (*Table[T]) LeftJoinMany ¶
LeftJoinMany starts a query left-joined through a one-to-many relation.
func (*Table[T]) LeftJoinOn ¶
LeftJoinOn starts a query left-joined on conditions.
func (*Table[T]) Load ¶
Load fills a one-to-many relation on entities already in memory, in one extra query. See Include for the optional shape, passed through LoadShaped.
func (*Table[T]) LoadMissing ¶
LoadMissing is Load for only the entities whose relation is still nil.
func (*Table[T]) LoadOne ¶
LoadOne fills a many-to-one or one-to-one relation on entities already in memory, in one extra query.
func (*Table[T]) NoTracking ¶
NoTracking starts a query whose results are not tracked.
func (*Table[T]) OnlyDeleted ¶
OnlyDeleted starts a query for soft-deleted rows.
func (*Table[T]) OrderByDesc ¶
OrderByDesc starts a query ordered by field, descending.
func (*Table[T]) Prune ¶
Prune removes rows that meet conds for good, soft-deleted or not, in batches, so that clearing out old rows does not hold one long transaction. It returns how many went, and stops at the first error.
func (*Table[T]) Reload ¶
Reload overwrites the columns of e with the stored row, found by e's primary key, or returns ErrNotFound. Relations are left alone.
func (*Table[T]) RightJoinOn ¶
RightJoinOn starts a query right-joined on conditions.
func (*Table[T]) Truncate ¶
Truncate removes every row, faster than Delete, and cannot be used on a table that others refer to unless they are empty too. It stops tracking nothing, so call ClearTracked if the context holds these rows.
func (*Table[T]) Unfiltered ¶
Unfiltered starts a query whose Update or Delete affects every row.
func (*Table[T]) UpdateMany ¶
func (t *Table[T]) UpdateMany( ctx context.Context, entities []*T, fields ...FieldRef, ) (int64, error)
UpdateMany writes the named columns of each entity to its own row, in one transaction, and returns how many rows changed. Use it for values that differ per row. Tracked entities keep their snapshots, so prefer SaveChanges for them.
func (*Table[T]) Upsert ¶
Upsert inserts e, or follows conflict if a unique constraint already holds the row. With an update, e receives the stored row, including its key. With DoNothing, it stays as it was and Upsert reports false.
func (*Table[T]) WithDeleted ¶
WithDeleted starts a query that includes soft-deleted rows.
type TxOption ¶
type TxOption func(*txOptions)
TxOption configures a transaction.
func Attempts ¶
Attempts retries a transaction that fails from a deadlock or serialization conflict, up to n runs in all, waiting a little longer each time. f must be safe to run again, so it should not change anything outside the database.
func Isolation ¶
func Isolation(level sql.IsolationLevel) TxOption
Isolation sets the transaction isolation level.
type UnixTime ¶
UnixTime is a time stored as whole seconds since 1970. On CreatedAt and UpdatedAt, it is maintained like a time.Time.
type ValidationError ¶
ValidationError reports a field that failed a rule from ModelBuilder.Validate.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
func (*ValidationError) Unwrap ¶
func (e *ValidationError) Unwrap() error
Unwrap returns the rule's error.
type Window ¶
type Window struct {
// contains filtered or unexported fields
}
Window is an OVER clause, from PartitionBy or OrderedBy.
func PartitionBy ¶
PartitionBy starts a window divided by a column.
func (Window) PartitionBy ¶
PartitionBy divides the window by more expressions.
Source Files
¶
- aggregate.go
- ant.go
- assign.go
- builder.go
- cond.go
- config.go
- conventions.go
- diagnostics.go
- entry.go
- errors.go
- errors_kind.go
- events.go
- expr.go
- fields.go
- graph.go
- hooks.go
- include.go
- intercept.go
- join.go
- joined.go
- json.go
- merge.go
- options.go
- paging.go
- pivot.go
- projection.go
- query.go
- raw.go
- run.go
- schema.go
- subquery.go
- table.go
- tx.go
- unit.go
- upsert.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package anttest holds helpers for testing code that uses ant, against a real database:
|
Package anttest holds helpers for testing code that uses ant, against a real database: |
|
contrib
|
|
|
otel
module
|
|
|
Package dialect defines the interface each database implements, plus helpers they share.
|
Package dialect defines the interface each database implements, plus helpers they share. |
|
mysql
Package mysql holds the MySQL and MariaDB dialects.
|
Package mysql holds the MySQL and MariaDB dialects. |
|
postgres
Package postgres is the PostgreSQL dialect.
|
Package postgres is the PostgreSQL dialect. |
|
postgres/pgxext
Package pgxext holds PostgreSQL features that database/sql cannot reach and that need pgx itself, so that ant and dialect/postgres stay free of any driver.
|
Package pgxext holds PostgreSQL features that database/sql cannot reach and that need pgx itself, so that ant and dialect/postgres stay free of any driver. |
|
sqlite
Package sqlite is the SQLite dialect.
|
Package sqlite is the SQLite dialect. |
|
sqlserver
Package sqlserver is the SQL Server dialect.
|
Package sqlserver is the SQL Server dialect. |
|
Package ids makes unique keys in Go, for use with ant.GenerateKey:
|
Package ids makes unique keys in Go, for use with ant.GenerateKey: |
|
internal
|
|
|
errs
Package errs holds sentinel errors shared by ant's packages.
|
Package errs holds sentinel errors shared by ant's packages. |
|
exec
Package exec defines the seam between ant and database/sql.
|
Package exec defines the seam between ant and database/sql. |
|
meta
Package meta is the model registry.
|
Package meta is the model registry. |
|
scan
Package scan maps database rows onto Go values.
|
Package scan maps database rows onto Go values. |
|
testdb
Package testdb runs ant's integration tests against every database listed in ANT_TEST_DATABASES.
|
Package testdb runs ant's integration tests against every database listed in ANT_TEST_DATABASES. |
|
track
Package track implements the change tracker: identity map, snapshots, and diffing.
|
Package track implements the change tracker: identity map, snapshots, and diffing. |
|
Package metrics counts statements, with no dependencies, and writes them in Prometheus text format, which most monitoring systems read:
|
Package metrics counts statements, with no dependencies, and writes them in Prometheus text format, which most monitoring systems read: |
|
Package migrate keeps a database in step with its models.
|
Package migrate keeps a database in step with its models. |
|
Package qb is the dialect-neutral query AST.
|
Package qb is the dialect-neutral query AST. |
|
Package schema describes a database schema as plain data, and works out the changes that turn one schema into another.
|
Package schema describes a database schema as plain data, and works out the changes that turn one schema into another. |
|
Package secure stores values encrypted, with AES-256-GCM, so that a database dump reveals nothing.
|
Package secure stores values encrypted, with AES-256-GCM, so that a database dump reveals nothing. |
|
tests
|
|
|
features/fixture
Package fixture holds the models and setup shared by the feature examples.
|
Package fixture holds the models and setup shared by the feature examples. |
|
tools
|
|
|
antfmt
module
|
|
|
antvet
module
|
|
|
Package validate holds common rules for ModelBuilder.Validate:
|
Package validate holds common rules for ModelBuilder.Validate: |