Documentation
¶
Overview ¶
Package query is liteorm's explicit, generics-first front-end: a typed query builder plus a Repo[T] for CRUD, operating against a liteorm.Session (a *DB or a transaction) so the same code runs on a connection or inside a tx. It builds SQL via internal/sqlgen and maps rows via internal/scan, and imports no backend — the driver is wired in at the Session.
Queries are built with typed, column-validated predicates (Filter + Col[V] operators, And/Or/Not) for value safety and runtime column checking, with a raw Where("frag", args...) escape hatch. Terminals: All, Iter (iter.Seq2), First, Count, Exists. Repo[T] has Get/Find/Insert/InsertMany/Update/Delete/ Upsert; InsertMany uses the backend's BulkInserter (pgx CopyFrom) when present, else chunked multi-row VALUES.
Index ¶
- func Avg[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (float64, error)
- func CountCol[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (int64, error)
- func InsertCapturingPK[T any](ctx context.Context, sess liteorm.Session, ins sqlgen.Insert, v *T) error
- func InsertManyCapturingPK[T any](ctx context.Context, sess liteorm.Session, ins sqlgen.Insert, vs []*T) error
- func Into[T any, R any](ctx context.Context, b *SelectBuilder[T], fields ...Field) ([]R, error)
- func Max[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (V, error)
- func Min[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (V, error)
- func Pluck[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) ([]V, error)
- func PluckExpr[T any, V any](ctx context.Context, b *SelectBuilder[T], expr string, args ...any) ([]V, error)
- func PluckExprFirst[T any, V any](ctx context.Context, b *SelectBuilder[T], expr string, args ...any) (V, error)
- func Raw[T any](ctx context.Context, sess liteorm.Session, query string, args ...any) ([]T, error)
- func Sum[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (V, error)
- type ArrayColumn
- type Column
- func (c Column[V]) Contains(sub string) Predicate
- func (c Column[V]) Eq(v V) Predicate
- func (c Column[V]) EqCol(other Column[V]) Predicate
- func (c Column[V]) Field() Field
- func (c Column[V]) Ge(v V) Predicate
- func (c Column[V]) Gt(v V) Predicate
- func (c Column[V]) HasPrefix(prefix string) Predicate
- func (c Column[V]) HasSuffix(suffix string) Predicate
- func (c Column[V]) In(vs ...V) Predicate
- func (c Column[V]) InQuery(sub Subquery) Predicate
- func (c Column[V]) IsNotNull() Predicate
- func (c Column[V]) IsNull() Predicate
- func (c Column[V]) Le(v V) Predicate
- func (c Column[V]) Like(pattern string) Predicate
- func (c Column[V]) Lt(v V) Predicate
- func (c Column[V]) Ne(v V) Predicate
- func (c Column[V]) NotIn(vs ...V) Predicate
- func (c Column[V]) NotInQuery(sub Subquery) Predicate
- func (c Column[V]) Of(table string) Column[V]
- func (c Column[V]) Unvalidated() Column[V]
- type DeleteBuilder
- type Field
- func AvgAs[V any](c Column[V], alias string) Field
- func CountAs[V any](c Column[V], alias string) Field
- func ExistsField[T any](alias string, sub *SelectBuilder[T]) Field
- func Expr(raw string) Field
- func MaxAs[V any](c Column[V], alias string) Field
- func MinAs[V any](c Column[V], alias string) Field
- func Name(col string) Field
- func ScalarSubquery(alias string, sub Subquery) Field
- func SumAs[V any](c Column[V], alias string) Field
- type JSONPath
- type OnConflictSpec
- type OrderTerm
- type Predicate
- type Repo
- func (r *Repo[T]) Delete(ctx context.Context, keys ...any) error
- func (r *Repo[T]) Find(ctx context.Context, preds ...Predicate) ([]T, error)
- func (r *Repo[T]) Get(ctx context.Context, keys ...any) (T, error)
- func (r *Repo[T]) Insert(ctx context.Context, v *T) error
- func (r *Repo[T]) InsertMany(ctx context.Context, vs []T) error
- func (r *Repo[T]) Update(ctx context.Context, v *T) error
- func (r *Repo[T]) Upsert(ctx context.Context, v *T, oc OnConflictSpec) error
- type SelectBuilder
- func (b *SelectBuilder[T]) All(ctx context.Context) ([]T, error)
- func (b *SelectBuilder[T]) Count(ctx context.Context) (int64, error)
- func (b *SelectBuilder[T]) CrossJoin(table string) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Distinct() *SelectBuilder[T]
- func (b *SelectBuilder[T]) DistinctOn(cols ...Field) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Except(other *SelectBuilder[T]) *SelectBuilder[T]
- func (b *SelectBuilder[T]) ExceptAll(other *SelectBuilder[T]) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Exists(ctx context.Context) (bool, error)
- func (b *SelectBuilder[T]) Filter(preds ...Predicate) *SelectBuilder[T]
- func (b *SelectBuilder[T]) First(ctx context.Context) (T, error)
- func (b *SelectBuilder[T]) ForShare() *SelectBuilder[T]
- func (b *SelectBuilder[T]) ForUpdate() *SelectBuilder[T]
- func (b *SelectBuilder[T]) From(name string) *SelectBuilder[T]
- func (b *SelectBuilder[T]) GroupBy(cols ...string) *SelectBuilder[T]
- func (b *SelectBuilder[T]) GroupByCols(fields ...Field) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Having(frag string, args ...any) *SelectBuilder[T]
- func (b *SelectBuilder[T]) InnerJoin(table, on string, args ...any) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Intersect(other *SelectBuilder[T]) *SelectBuilder[T]
- func (b *SelectBuilder[T]) IntersectAll(other *SelectBuilder[T]) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Iter(ctx context.Context) iter.Seq2[T, error]
- func (b *SelectBuilder[T]) Join(clause string, args ...any) *SelectBuilder[T]
- func (b *SelectBuilder[T]) JoinLateral(kind, alias string, sub Subquery, on string, args ...any) *SelectBuilder[T]
- func (b *SelectBuilder[T]) JoinSub(kind, alias string, sub Subquery, on string, args ...any) *SelectBuilder[T]
- func (b *SelectBuilder[T]) LeftJoin(table, on string, args ...any) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Limit(n int) *SelectBuilder[T]
- func (b *SelectBuilder[T]) NoWait() *SelectBuilder[T]
- func (b *SelectBuilder[T]) Offset(n int) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Order(terms ...OrderTerm) *SelectBuilder[T]
- func (b *SelectBuilder[T]) OrderBy(terms ...string) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Project(cols ...string) *SelectBuilder[T]
- func (b *SelectBuilder[T]) RightJoin(table, on string, args ...any) *SelectBuilder[T]
- func (b *SelectBuilder[T]) SkipLocked() *SelectBuilder[T]
- func (b *SelectBuilder[T]) Union(other *SelectBuilder[T]) *SelectBuilder[T]
- func (b *SelectBuilder[T]) UnionAll(other *SelectBuilder[T]) *SelectBuilder[T]
- func (b *SelectBuilder[T]) Where(frag string, args ...any) *SelectBuilder[T]
- func (b *SelectBuilder[T]) With(name string, sub inlineSelect) *SelectBuilder[T]
- func (b *SelectBuilder[T]) WithRecursive(name string, sub inlineSelect) *SelectBuilder[T]
- type Subquery
- type UpdateBuilder
- func (u *UpdateBuilder[T]) Dec(col string, by int64) *UpdateBuilder[T]
- func (u *UpdateBuilder[T]) Exec(ctx context.Context) (int64, error)
- func (u *UpdateBuilder[T]) Filter(preds ...Predicate) *UpdateBuilder[T]
- func (u *UpdateBuilder[T]) From(source string, args ...any) *UpdateBuilder[T]
- func (u *UpdateBuilder[T]) Inc(col string, by int64) *UpdateBuilder[T]
- func (u *UpdateBuilder[T]) Returning(ctx context.Context) ([]T, error)
- func (u *UpdateBuilder[T]) Set(col string, val any) *UpdateBuilder[T]
- func (u *UpdateBuilder[T]) SetExpr(col, sqlExpr string, args ...any) *UpdateBuilder[T]
- func (u *UpdateBuilder[T]) Where(frag string, args ...any) *UpdateBuilder[T]
- type Window
- type WindowFunc
- func DenseRank() WindowFunc
- func Lag[V any](c Column[V], offset int) WindowFunc
- func Lead[V any](c Column[V], offset int) WindowFunc
- func Rank() WindowFunc
- func RowNumber() WindowFunc
- func WindowAvg[V any](c Column[V]) WindowFunc
- func WindowCount[V any](c Column[V]) WindowFunc
- func WindowMax[V any](c Column[V]) WindowFunc
- func WindowMin[V any](c Column[V]) WindowFunc
- func WindowSum[V any](c Column[V]) WindowFunc
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func InsertCapturingPK ¶
func InsertCapturingPK[T any](ctx context.Context, sess liteorm.Session, ins sqlgen.Insert, v *T) error
InsertCapturingPK runs an INSERT and writes the generated primary key back into v, using the best mechanism the dialect supports: RETURNING (Postgres/SQLite) or OUTPUT (MSSQL) read back via a query, else LastInsertId (MySQL/SQLite). It is exported so the orm front-end can reuse the same capture logic.
func InsertManyCapturingPK ¶
func InsertManyCapturingPK[T any](ctx context.Context, sess liteorm.Session, ins sqlgen.Insert, vs []*T) error
InsertManyCapturingPK runs one multi-row INSERT (ins.Rows holds the batch) and, on a dialect with RETURNING/OUTPUT, writes each generated primary key back into the matching element of vs by position. Without RETURNING it inserts the batch without reading keys back (callers that need generated keys on such dialects insert per row). It is exported so the orm front-end can reuse the capture logic for batched creates.
func Into ¶
Into runs b projected onto the given fields and scans each row into R (a result struct whose columns match the projection's names/aliases). It is the typed projection terminal — column-validated, dialect-quoted — and pairs with GroupByCols + the AggAs helpers for grouped aggregates. For a fully custom shape, Raw[R] remains the escape hatch.
func Pluck ¶
Pluck projects a single typed column and returns its values as []V — the column-validated, dialect-quoted equivalent of gorm's Pluck / xorm's Cols, for the common "give me all the emails / ids" read without allocating full rows. It honors the builder's filters/order/limit.
func PluckExpr ¶ added in v0.10.0
func PluckExpr[T any, V any](ctx context.Context, b *SelectBuilder[T], expr string, args ...any) ([]V, error)
PluckExpr projects a single raw scalar expression — not a typed column — and returns the values as []V. It is the escape-hatch sibling of Pluck for aggregates, functions, or implicit columns (MAX(x), COALESCE(a, b), LENGTH(t), rowid, a window expression). The expression is emitted verbatim (not column-validated) and may carry "?" markers bound by args; it honors the builder's filters/order/limit.
func PluckExprFirst ¶ added in v0.10.0
func PluckExprFirst[T any, V any](ctx context.Context, b *SelectBuilder[T], expr string, args ...any) (V, error)
PluckExprFirst is PluckExpr returning only the first row's value (V's zero value if no rows) — for a single-scalar read like PluckExprFirst[ItemModel, int64](ctx, b, "MAX(updated_count)").
Types ¶
type ArrayColumn ¶
type ArrayColumn[E any] struct { // contains filtered or unexported fields }
ArrayColumn is a Postgres array column of element type E. Its operators are Postgres-only (FeatArray).
func Array ¶
func Array[E any](name string) ArrayColumn[E]
Array names a Postgres array column, e.g. Array[string]("tags").
func (ArrayColumn[E]) ContainedBy ¶
func (a ArrayColumn[E]) ContainedBy(elems ...E) Predicate
ContainedBy tests that every element of the column is in elems (col <@ ARRAY[...]).
func (ArrayColumn[E]) Contains ¶
func (a ArrayColumn[E]) Contains(elems ...E) Predicate
Contains tests that the array column contains all of elems (col @> ARRAY[...]).
func (ArrayColumn[E]) Has ¶
func (a ArrayColumn[E]) Has(v E) Predicate
Has tests element membership: v = ANY(col).
func (ArrayColumn[E]) Overlaps ¶
func (a ArrayColumn[E]) Overlaps(elems ...E) Predicate
Overlaps tests that the column and elems share at least one element (col && ARRAY[...]).
type Column ¶
type Column[V any] struct { // contains filtered or unexported fields }
Column is a typed column token. Its operators take values of type V.
func (Column[V]) EqCol ¶ added in v0.10.0
EqCol renders a column-to-column equality (c = other) — for correlating a subquery to its outer query, e.g. inside an ExistsField subquery: Col[int64]("post_id").EqCol(Col[int64]("id").Of("posts")). Only c is validated against the (subquery's) model; other references an outer scope and is emitted as written, so qualify it with Of.
func (Column[V]) Field ¶
Field erases a typed column for a clause position; it is quoted by the dialect (and validated against the model unless the column is Unvalidated).
func (Column[V]) HasPrefix ¶ added in v0.10.0
HasPrefix/HasSuffix/Contains match a literal substring at the start / end / anywhere in the column, escaping any LIKE metacharacters (% and _) in the needle so they match literally — HasPrefix("100") will not match "100% off" on the %. They render `col LIKE ? ESCAPE '~'` and are portable across all four backends.
func (Column[V]) InQuery ¶
InQuery renders `col IN (subquery)`; the subquery must Project one column.
func (Column[V]) Like ¶
Like matches a SQL LIKE pattern. The pattern is bound verbatim, so its % and _ are wildcards — use HasPrefix/HasSuffix/Contains when you want a literal needle with its wildcards escaped.
func (Column[V]) NotInQuery ¶
NotInQuery renders `col NOT IN (subquery)`.
func (Column[V]) Of ¶ added in v0.10.0
Of qualifies the column with a table name or alias, so it renders "table"."col" — for correlating a subquery to its outer query (see EqCol).
func (Column[V]) Unvalidated ¶ added in v0.11.0
Unvalidated waives the model-schema validation that normally rejects a column not declared on the model (a typo guard). Use it for columns that exist on the underlying table but aren't fields on the model: a virtual table's HIDDEN constraint columns (e.g. spellfix1's "scope", which drives xFilter), or the implicit "rowid"/"oid". The column is still typed and dialect-quoted — only the "is this a declared column?" check is skipped:
Filter(query.Col[int]("scope").Unvalidated().Le(2)) // renders "scope" <= ?
Everything else (operators, Of, Field, Asc/Desc, Pluck) composes as usual.
type DeleteBuilder ¶
type DeleteBuilder[T any] struct { // contains filtered or unexported fields }
DeleteBuilder builds a multi-row DELETE over T's table — the WHERE-based counterpart to Repo.Delete (which deletes one row by primary key). Correlated deletes are expressed via Where/Filter with a subquery predicate (InQuery / Exists). Returning yields the deleted rows.
func Delete ¶
func Delete[T any](sess liteorm.Session) *DeleteBuilder[T]
Delete starts a DELETE over T's table.
func (*DeleteBuilder[T]) Exec ¶
func (b *DeleteBuilder[T]) Exec(ctx context.Context) (int64, error)
Exec runs the DELETE and returns the number of rows affected.
func (*DeleteBuilder[T]) Filter ¶
func (b *DeleteBuilder[T]) Filter(preds ...Predicate) *DeleteBuilder[T]
Filter adds typed, column-validated predicates (AND-joined).
func (*DeleteBuilder[T]) Returning ¶
func (b *DeleteBuilder[T]) Returning(ctx context.Context) ([]T, error)
Returning runs the DELETE and returns the deleted rows as []T via RETURNING (Postgres/SQLite) or OUTPUT (SQL Server). It errors on a dialect with neither.
func (*DeleteBuilder[T]) Where ¶
func (b *DeleteBuilder[T]) Where(frag string, args ...any) *DeleteBuilder[T]
Where adds a raw AND-joined predicate fragment ("?" markers bound by args).
type Field ¶
type Field struct {
// contains filtered or unexported fields
}
Field is a value-type-erased reference to something selectable or groupable — a column whose Go type is irrelevant in this position (GROUP BY, a typed projection). Build one from a typed column with Column.Field, by name with Name, a raw expression with Expr, or an aggregate with SumAs/AvgAs/MinAs/MaxAs/ CountAs. The referenced columns are validated against the model.
func ExistsField ¶ added in v0.10.0
func ExistsField[T any](alias string, sub *SelectBuilder[T]) Field
ExistsField projects a correlated EXISTS subquery as a 0/1 result column — CASE WHEN EXISTS (<sub>) THEN 1 ELSE 0 END AS "alias" — for use in Into alongside Name/Column fields, scanning into a bool. The CASE wrapper (rather than a bare EXISTS) is what makes it valid on all four backends, including SQL Server, where EXISTS may not appear in a SELECT list. The subquery correlates to the outer row with EqCol (or a raw Where):
hasComment := query.ExistsField("has_comment",
query.Select[Comment](db).Filter(
query.Col[int64]("post_id").EqCol(query.Col[int64]("id").Of("posts"))))
rows, _ := query.Into[Post, row](ctx, query.Select[Post](db),
query.Name("id"), query.Name("title"), hasComment)
The subquery validates its own columns; it is not validated against the outer model. (A feature-gated predicate inside the subquery is not feature-checked — the ordinary Filter path is — so keep dialect-specific operators on the outside.)
func Expr ¶
Expr is the raw escape hatch for a selectable/groupable expression; it is emitted verbatim and not column-validated.
func Name ¶
Name references a column by name (quoted by the dialect, validated against the model) for a clause position.
func ScalarSubquery ¶
ScalarSubquery renders a subquery as a single SELECT-list value: (sub) AS alias. The subquery must select exactly one column and yield at most one row per outer row; correlate it to the outer query with a raw Where referencing the outer table's columns. Use it as a projection field in Into — the typed answer to a per-row computed value beyond IN/EXISTS. Raw Project remains the escape hatch for anything more exotic.
type JSONPath ¶
type JSONPath struct {
// contains filtered or unexported fields
}
JSONPath is a JSON column plus a (possibly empty) object-key path.
func JSON ¶
JSON names a JSON/JSONB column for path extraction and containment. Drill into nested keys with Key, then compare the extracted text (Eq/Ne/Like/In) or test containment (Contains).
func (JSONPath) Contains ¶
Contains renders the Postgres jsonb containment operator (col @> value). The value is JSON-encoded and bound. Postgres only (FeatJSONB).
type OnConflictSpec ¶
OnConflictSpec describes an upsert conflict target and what to do on a conflict.
func OnConflict ¶
func OnConflict(cols ...string) OnConflictSpec
OnConflict names the conflict-target columns. Chain DoUpdate to pick the columns to overwrite, or DoNothing to ignore the conflicting row; with neither, all non-conflict columns are updated.
func (OnConflictSpec) DoNothing ¶ added in v0.10.0
func (o OnConflictSpec) DoNothing() OnConflictSpec
DoNothing makes the upsert ignore a conflicting row — INSERT ... ON CONFLICT DO NOTHING, the typed form of INSERT OR IGNORE — instead of updating it. On MySQL it renders a no-op ON DUPLICATE KEY UPDATE; on SQL Server, a MERGE with no WHEN MATCHED arm. A skipped insert returns no generated key.
func (OnConflictSpec) DoUpdate ¶
func (o OnConflictSpec) DoUpdate(cols ...string) OnConflictSpec
DoUpdate sets the columns to overwrite on conflict.
type OrderTerm ¶
type OrderTerm struct {
// contains filtered or unexported fields
}
OrderTerm is one ORDER BY element. Build a typed, column-validated term with Asc/Desc (the column is quoted by the dialect), or a raw fragment with OrderExpr (the escape hatch). Pass terms to SelectBuilder.Order.
type Predicate ¶
type Predicate struct {
// contains filtered or unexported fields
}
Predicate is a typed, dialect-quoted WHERE/HAVING condition built from Column operators and the And/Or/Not combinators. The columns it references are validated against the model's schema when the predicate is added to a query (an unknown column is an error, not silent). This gives compile-time *value* safety and runtime *column* validation today; codegen (liteorm gen) will later emit the same Column[V] tokens for compile-time column safety too.
func Exists ¶
func Exists[T any](sub *SelectBuilder[T]) Predicate
Exists renders an `EXISTS (subquery)` predicate (use it inside Filter). It is distinct from the SelectBuilder.Exists terminal, which executes the query and returns a bool. The subquery typically correlates to the outer query via a raw Where, e.g.
query.Select[User](db).Filter(query.Exists(
query.Select[Order](db).Project("1").Where("orders.user_id = users.id")))
func Match ¶ added in v0.10.0
Match builds a SQLite MATCH predicate — `col MATCH ?` — for full-text (FTS5), spellfix1, and sqlite-vec virtual tables, composable inside Filter / And / Or alongside ordinary column predicates. It is gated on dialect.FeatMatch: on a non-SQLite backend the query fails loudly at build time rather than emitting unsupported SQL. (Postgres and MySQL full-text use different operators; their predicates belong under their own dialects.)
hit, err := orm.NewRepo[Vocab](db).
Filter(query.Match("word", term), query.Col[int]("scope").Le(2)).
OrderBy("distance ASC").
First(ctx)
func NotExists ¶
func NotExists[T any](sub *SelectBuilder[T]) Predicate
NotExists renders `NOT EXISTS (subquery)`.
type Repo ¶
type Repo[T any] struct { // contains filtered or unexported fields }
Repo is a typed repository for CRUD over T against a liteorm.Session.
func (*Repo[T]) Delete ¶
Delete removes the row whose primary key equals the given key (one value per key column for a composite key).
func (*Repo[T]) Get ¶
Get fetches the row whose primary key equals the given key, or liteorm.ErrNoRows. For a composite key, pass one value per key column in declaration order: Get(ctx, tenantID, code).
func (*Repo[T]) Insert ¶
Insert inserts v, reading the generated primary key back via RETURNING (or a plain exec where the dialect lacks it). v is updated in place on RETURNING.
func (*Repo[T]) InsertMany ¶
InsertMany inserts vs in bulk: the backend's BulkInserter (pgx native CopyFrom) when available, else chunked multi-row VALUES. It does not read primary keys back (use Insert per row when you need the generated id).
type SelectBuilder ¶
type SelectBuilder[T any] struct { // contains filtered or unexported fields }
SelectBuilder is a typed SELECT builder. T fixes the result type at compile time.
func FromSubquery ¶
func FromSubquery[T any](sess liteorm.Session, alias string, sub inlineSelect) *SelectBuilder[T]
FromSubquery starts a SELECT whose FROM is the derived table (sub) AS alias. T is the row shape the subquery produces; its columns are qualified by alias. Derived tables are universally supported, so this is not feature-gated.
func Select ¶
func Select[T any](sess liteorm.Session) *SelectBuilder[T]
Select starts a typed SELECT over T against sess.
func (*SelectBuilder[T]) All ¶
func (b *SelectBuilder[T]) All(ctx context.Context) ([]T, error)
All runs the query and returns all rows as typed T.
func (*SelectBuilder[T]) Count ¶
func (b *SelectBuilder[T]) Count(ctx context.Context) (int64, error)
Count returns the number of matching rows (ignoring order/limit/offset).
func (*SelectBuilder[T]) CrossJoin ¶
func (b *SelectBuilder[T]) CrossJoin(table string) *SelectBuilder[T]
CrossJoin adds a CROSS JOIN of the (quoted) table.
func (*SelectBuilder[T]) Distinct ¶
func (b *SelectBuilder[T]) Distinct() *SelectBuilder[T]
Distinct adds SELECT DISTINCT.
func (*SelectBuilder[T]) DistinctOn ¶
func (b *SelectBuilder[T]) DistinctOn(cols ...Field) *SelectBuilder[T]
DistinctOn adds SELECT DISTINCT ON (cols) — keep the first row of each distinct combination of the given typed columns (validated + quoted). Postgres-only (gated by FeatDistinctOn); pair it with an Order whose leading terms match.
func (*SelectBuilder[T]) Except ¶
func (b *SelectBuilder[T]) Except(other *SelectBuilder[T]) *SelectBuilder[T]
Except appends other as an EXCEPT arm (rows in the receiver but not other). ExceptAll keeps duplicates. Gated by FeatIntersectExcept.
func (*SelectBuilder[T]) ExceptAll ¶
func (b *SelectBuilder[T]) ExceptAll(other *SelectBuilder[T]) *SelectBuilder[T]
func (*SelectBuilder[T]) Exists ¶
func (b *SelectBuilder[T]) Exists(ctx context.Context) (bool, error)
Exists reports whether any row matches.
func (*SelectBuilder[T]) Filter ¶
func (b *SelectBuilder[T]) Filter(preds ...Predicate) *SelectBuilder[T]
Filter adds typed, column-validated predicates (AND-joined with any Where).
func (*SelectBuilder[T]) First ¶
func (b *SelectBuilder[T]) First(ctx context.Context) (T, error)
First returns the first matching row, or liteorm.ErrNoRows.
func (*SelectBuilder[T]) ForShare ¶
func (b *SelectBuilder[T]) ForShare() *SelectBuilder[T]
func (*SelectBuilder[T]) ForUpdate ¶
func (b *SelectBuilder[T]) ForUpdate() *SelectBuilder[T]
ForUpdate locks the selected rows for update (FOR UPDATE). ForShare takes a weaker shared lock (FOR SHARE). Postgres and MySQL only (gated by FeatRowLocking — a clear build error on SQLite/MSSQL).
func (*SelectBuilder[T]) From ¶
func (b *SelectBuilder[T]) From(name string) *SelectBuilder[T]
From overrides the FROM source to `name` — typically a CTE defined with With/WithRecursive, but it also works as a plain table-name override. The selected columns are re-qualified to `name` (unless a raw Project is set).
func (*SelectBuilder[T]) GroupBy ¶
func (b *SelectBuilder[T]) GroupBy(cols ...string) *SelectBuilder[T]
GroupBy adds raw GROUP BY terms (emitted verbatim). For typed, validated, dialect-quoted columns use GroupByCols; both compose in call order.
func (*SelectBuilder[T]) GroupByCols ¶
func (b *SelectBuilder[T]) GroupByCols(fields ...Field) *SelectBuilder[T]
GroupByCols adds typed GROUP BY terms (validated + quoted), the typed counterpart of the raw GroupBy(...string). Both append to the same list.
func (*SelectBuilder[T]) Having ¶
func (b *SelectBuilder[T]) Having(frag string, args ...any) *SelectBuilder[T]
Having adds a raw HAVING predicate (AND-joined); frag carries "?" markers.
func (*SelectBuilder[T]) InnerJoin ¶
func (b *SelectBuilder[T]) InnerJoin(table, on string, args ...any) *SelectBuilder[T]
InnerJoin/LeftJoin/RightJoin add a typed join: the table identifier is quoted by the dialect, the ON condition is raw SQL (it spans tables) and may carry "?" markers bound by args.
func (*SelectBuilder[T]) Intersect ¶
func (b *SelectBuilder[T]) Intersect(other *SelectBuilder[T]) *SelectBuilder[T]
Intersect appends other as an INTERSECT arm (rows in both; duplicates removed). IntersectAll keeps duplicates. Like Union, other must produce the same column shape; the receiver's ORDER BY/LIMIT apply to the whole compound. INTERSECT is gated by FeatIntersectExcept (unsupported on MySQL — a clear build error there).
func (*SelectBuilder[T]) IntersectAll ¶
func (b *SelectBuilder[T]) IntersectAll(other *SelectBuilder[T]) *SelectBuilder[T]
func (*SelectBuilder[T]) Join ¶
func (b *SelectBuilder[T]) Join(clause string, args ...any) *SelectBuilder[T]
Join adds a raw join clause, e.g. "JOIN orders ON orders.user_id = users.id". The clause may carry "?" markers bound by args (rare in ON, but supported).
func (*SelectBuilder[T]) JoinLateral ¶
func (b *SelectBuilder[T]) JoinLateral(kind, alias string, sub Subquery, on string, args ...any) *SelectBuilder[T]
JoinLateral is JoinSub with the LATERAL keyword, so the subquery may reference columns of earlier FROM items. Postgres only (gated by FeatLateral).
func (*SelectBuilder[T]) JoinSub ¶
func (b *SelectBuilder[T]) JoinSub(kind, alias string, sub Subquery, on string, args ...any) *SelectBuilder[T]
JoinSub joins a subquery as a derived table: `<kind> (sub) AS alias ON <on>`, where kind is "INNER JOIN" / "LEFT JOIN" / etc. and `on` is raw SQL (it spans tables) that may carry "?" markers bound by args.
func (*SelectBuilder[T]) LeftJoin ¶
func (b *SelectBuilder[T]) LeftJoin(table, on string, args ...any) *SelectBuilder[T]
func (*SelectBuilder[T]) Limit ¶
func (b *SelectBuilder[T]) Limit(n int) *SelectBuilder[T]
Limit sets a row limit.
func (*SelectBuilder[T]) NoWait ¶
func (b *SelectBuilder[T]) NoWait() *SelectBuilder[T]
func (*SelectBuilder[T]) Offset ¶
func (b *SelectBuilder[T]) Offset(n int) *SelectBuilder[T]
Offset sets a row offset.
func (*SelectBuilder[T]) Order ¶
func (b *SelectBuilder[T]) Order(terms ...OrderTerm) *SelectBuilder[T]
Order adds typed ORDER BY terms (Asc/Desc/OrderExpr), validated and quoted. It is the typed counterpart of the raw OrderBy(...string); both append to the same ordered list, so they compose in call order.
func (*SelectBuilder[T]) OrderBy ¶
func (b *SelectBuilder[T]) OrderBy(terms ...string) *SelectBuilder[T]
OrderBy adds raw ORDER BY terms, e.g. "created_at DESC" (emitted verbatim). For typed, validated, dialect-quoted ordering use Order with Asc/Desc; both compose in call order.
func (*SelectBuilder[T]) Project ¶
func (b *SelectBuilder[T]) Project(cols ...string) *SelectBuilder[T]
Project overrides the SELECT list with raw column expressions — used to select a single column for an IN subquery, or specific columns/aggregates. With no Project the full model column set is selected.
func (*SelectBuilder[T]) RightJoin ¶
func (b *SelectBuilder[T]) RightJoin(table, on string, args ...any) *SelectBuilder[T]
func (*SelectBuilder[T]) SkipLocked ¶
func (b *SelectBuilder[T]) SkipLocked() *SelectBuilder[T]
SkipLocked makes a locking read skip rows already locked by another transaction (instead of blocking); NoWait makes it error immediately instead. Both imply a lock, defaulting to FOR UPDATE when neither ForUpdate nor ForShare was called.
func (*SelectBuilder[T]) Union ¶
func (b *SelectBuilder[T]) Union(other *SelectBuilder[T]) *SelectBuilder[T]
Union appends `other` as a UNION arm (duplicate rows removed). other must produce the same column shape as the receiver. The receiver's ORDER BY/LIMIT apply to the whole compound.
func (*SelectBuilder[T]) UnionAll ¶
func (b *SelectBuilder[T]) UnionAll(other *SelectBuilder[T]) *SelectBuilder[T]
UnionAll is Union but keeps duplicate rows.
func (*SelectBuilder[T]) Where ¶
func (b *SelectBuilder[T]) Where(frag string, args ...any) *SelectBuilder[T]
Where adds a raw AND-joined predicate; frag carries positional "?" markers. It is the escape hatch; prefer Filter with typed Column predicates.
func (*SelectBuilder[T]) With ¶
func (b *SelectBuilder[T]) With(name string, sub inlineSelect) *SelectBuilder[T]
With prepends a common table expression named `name` whose body is sub; reference it as the FROM source with From(name). Gated by FeatCTE.
func (*SelectBuilder[T]) WithRecursive ¶
func (b *SelectBuilder[T]) WithRecursive(name string, sub inlineSelect) *SelectBuilder[T]
WithRecursive prepends a recursive CTE (the body's recursive arm refers back to `name`, typically via a raw Join). It marks the whole WITH as RECURSIVE.
type Subquery ¶
type Subquery interface {
// contains filtered or unexported methods
}
Subquery is a SELECT usable inside a predicate (IN / NOT IN / EXISTS). Any *SelectBuilder[T] satisfies it; build it like a normal query and (for IN) use Project to select the single matched column. The subquery's columns are validated when it is placed in a predicate, so an error surfaces from the outer query's terminal before any SQL runs.
type UpdateBuilder ¶
type UpdateBuilder[T any] struct { // contains filtered or unexported fields }
UpdateBuilder builds a multi-row UPDATE over T's table — the WHERE-based counterpart to Repo.Update (which updates one row by primary key). Set the columns, scope it with Where/Filter, optionally correlate with another source via From, then Exec (rows affected) or Returning (the changed rows as []T).
func Update ¶
func Update[T any](sess liteorm.Session) *UpdateBuilder[T]
Update starts an UPDATE over T's table.
func (*UpdateBuilder[T]) Dec ¶ added in v0.10.0
func (u *UpdateBuilder[T]) Dec(col string, by int64) *UpdateBuilder[T]
Dec atomically decrements col by `by` (col = col - by).
func (*UpdateBuilder[T]) Exec ¶
func (u *UpdateBuilder[T]) Exec(ctx context.Context) (int64, error)
Exec runs the UPDATE and returns the number of rows affected.
func (*UpdateBuilder[T]) Filter ¶
func (u *UpdateBuilder[T]) Filter(preds ...Predicate) *UpdateBuilder[T]
Filter adds typed, column-validated predicates (AND-joined).
func (*UpdateBuilder[T]) From ¶
func (u *UpdateBuilder[T]) From(source string, args ...any) *UpdateBuilder[T]
From adds a correlated `FROM <source>` (UPDATE … FROM), so SetExpr and the WHERE may reference the source's columns. The source is raw SQL (a table, a derived table, or a VALUES list) and may carry "?" markers. Gated by FeatUpdateFrom (Postgres / SQLite / SQL Server; MySQL uses UPDATE … JOIN and raises a clear build error).
func (*UpdateBuilder[T]) Inc ¶ added in v0.10.0
func (u *UpdateBuilder[T]) Inc(col string, by int64) *UpdateBuilder[T]
Inc atomically increments col by `by` in the UPDATE (col = col + by) — the typed form of SetExpr("col", "col + 1"), with the column quoted for the dialect so the read-modify-write happens in the database. Dec decrements. The column is still validated against T at build time.
func (*UpdateBuilder[T]) Returning ¶
func (u *UpdateBuilder[T]) Returning(ctx context.Context) ([]T, error)
Returning runs the UPDATE and returns the changed rows as []T via RETURNING (Postgres/SQLite) or OUTPUT (SQL Server). It errors on a dialect with neither (MySQL).
func (*UpdateBuilder[T]) Set ¶
func (u *UpdateBuilder[T]) Set(col string, val any) *UpdateBuilder[T]
Set assigns a column to a bound value.
func (*UpdateBuilder[T]) SetExpr ¶
func (u *UpdateBuilder[T]) SetExpr(col, sqlExpr string, args ...any) *UpdateBuilder[T]
SetExpr assigns a column to a raw SQL expression (which may carry "?" markers) — e.g. SetExpr("views", "views + 1") or, with From, SetExpr("price", "src.price").
func (*UpdateBuilder[T]) Where ¶
func (u *UpdateBuilder[T]) Where(frag string, args ...any) *UpdateBuilder[T]
Where adds a raw AND-joined predicate fragment ("?" markers bound by args).
type Window ¶
type Window struct {
// contains filtered or unexported fields
}
Window is an OVER (…) specification. Build it with Over() and chain PartitionBy / OrderBy, then attach it to a window function with WindowFunc.Over.
func (Window) PartitionBy ¶
PartitionBy adds PARTITION BY columns to the window.
type WindowFunc ¶
type WindowFunc struct {
// contains filtered or unexported fields
}
WindowFunc is a window function (ROW_NUMBER, RANK, LAG, a running SUM, …) awaiting its OVER clause. Attach the window and a result alias with Over to get a projection Field for Into.
func DenseRank ¶
func DenseRank() WindowFunc
func Lag ¶
func Lag[V any](c Column[V], offset int) WindowFunc
Lag / Lead read a column from a row `offset` positions before / after the current one within the window.
func Rank ¶
func Rank() WindowFunc
func WindowAvg ¶
func WindowAvg[V any](c Column[V]) WindowFunc
func WindowCount ¶
func WindowCount[V any](c Column[V]) WindowFunc
func WindowMax ¶
func WindowMax[V any](c Column[V]) WindowFunc
func WindowMin ¶
func WindowMin[V any](c Column[V]) WindowFunc
func WindowSum ¶
func WindowSum[V any](c Column[V]) WindowFunc
Aggregate window functions (running / partitioned aggregates).