query

package
v0.11.0 Latest Latest
Warning

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

Go to latest
Published: Jun 19, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func Avg

func Avg[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (float64, error)

func CountCol

func CountCol[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (int64, error)

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

func Into[T any, R any](ctx context.Context, b *SelectBuilder[T], fields ...Field) ([]R, error)

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 Max

func Max[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (V, error)

func Min

func Min[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (V, error)

func Pluck

func Pluck[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) ([]V, error)

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)").

func Raw

func Raw[T any](ctx context.Context, sess liteorm.Session, query string, args ...any) ([]T, error)

Raw runs a raw SQL query and maps the rows into typed T (the escape hatch).

func Sum

func Sum[T any, V any](ctx context.Context, b *SelectBuilder[T], col Column[V]) (V, error)

Sum/Avg/Min/Max/CountCol are whole-set aggregate terminals: each builds SELECT AGG(col) over b's filters/joins (ignoring order/limit) and returns the scalar. NULL (e.g. an aggregate over no rows) returns R's zero value. For grouped aggregates use Into with the AggAs helpers.

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 Col

func Col[V any](name string) Column[V]

Col names a typed column, e.g. Col[string]("email").Eq("a@b.c").

func (Column[V]) Contains added in v0.10.0

func (c Column[V]) Contains(sub string) Predicate

func (Column[V]) Eq

func (c Column[V]) Eq(v V) Predicate

Eq/Ne/Gt/Ge/Lt/Le compare the column against a value of its type.

func (Column[V]) EqCol added in v0.10.0

func (c Column[V]) EqCol(other Column[V]) Predicate

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

func (c Column[V]) Field() 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]) Ge

func (c Column[V]) Ge(v V) Predicate

func (Column[V]) Gt

func (c Column[V]) Gt(v V) Predicate

func (Column[V]) HasPrefix added in v0.10.0

func (c Column[V]) HasPrefix(prefix string) Predicate

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]) HasSuffix added in v0.10.0

func (c Column[V]) HasSuffix(suffix string) Predicate

func (Column[V]) In

func (c Column[V]) In(vs ...V) Predicate

In / NotIn match membership in a set of values.

func (Column[V]) InQuery

func (c Column[V]) InQuery(sub Subquery) Predicate

InQuery renders `col IN (subquery)`; the subquery must Project one column.

func (Column[V]) IsNotNull

func (c Column[V]) IsNotNull() Predicate

func (Column[V]) IsNull

func (c Column[V]) IsNull() Predicate

IsNull / IsNotNull test for SQL NULL.

func (Column[V]) Le

func (c Column[V]) Le(v V) Predicate

func (Column[V]) Like

func (c Column[V]) Like(pattern string) Predicate

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]) Lt

func (c Column[V]) Lt(v V) Predicate

func (Column[V]) Ne

func (c Column[V]) Ne(v V) Predicate

func (Column[V]) NotIn

func (c Column[V]) NotIn(vs ...V) Predicate

func (Column[V]) NotInQuery

func (c Column[V]) NotInQuery(sub Subquery) Predicate

NotInQuery renders `col NOT IN (subquery)`.

func (Column[V]) Of added in v0.10.0

func (c Column[V]) Of(table string) Column[V]

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

func (c Column[V]) Unvalidated() Column[V]

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 AvgAs

func AvgAs[V any](c Column[V], alias string) Field

func CountAs

func CountAs[V any](c Column[V], alias string) Field

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

func Expr(raw string) Field

Expr is the raw escape hatch for a selectable/groupable expression; it is emitted verbatim and not column-validated.

func MaxAs

func MaxAs[V any](c Column[V], alias string) Field

func MinAs

func MinAs[V any](c Column[V], alias string) Field

func Name

func Name(col string) Field

Name references a column by name (quoted by the dialect, validated against the model) for a clause position.

func ScalarSubquery

func ScalarSubquery(alias string, sub Subquery) Field

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.

func SumAs

func SumAs[V any](c Column[V], alias string) Field

SumAs/AvgAs/MinAs/MaxAs/CountAs are aggregate projection items (e.g. for a grouped query): each renders AGG(col) AS alias and validates col. Use them in Into alongside the grouped columns.

type JSONPath

type JSONPath struct {
	// contains filtered or unexported fields
}

JSONPath is a JSON column plus a (possibly empty) object-key path.

func JSON

func JSON(name string) JSONPath

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

func (p JSONPath) Contains(value any) Predicate

Contains renders the Postgres jsonb containment operator (col @> value). The value is JSON-encoded and bound. Postgres only (FeatJSONB).

func (JSONPath) Eq

func (p JSONPath) Eq(v any) Predicate

Eq/Ne/Like compare the text value at the path. In matches any of several.

func (JSONPath) In

func (p JSONPath) In(vs ...any) Predicate

In matches the path's text value against a set.

func (JSONPath) Key

func (p JSONPath) Key(k string) JSONPath

Key drills one level into an object. Chain Key calls to walk nested objects: JSON("data").Key("address").Key("city").Eq("Paris").

func (JSONPath) Like

func (p JSONPath) Like(pat string) Predicate

func (JSONPath) Ne

func (p JSONPath) Ne(v any) Predicate

type OnConflictSpec

type OnConflictSpec struct {
	Columns []string
	Update  []string
	Nothing bool
}

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.

func Asc

func Asc[V any](c Column[V]) OrderTerm

Asc orders by a typed column ascending; the column is validated against the model (unless it is Unvalidated) and quoted by the dialect.

func Desc

func Desc[V any](c Column[V]) OrderTerm

Desc orders by a typed column descending.

func OrderExpr

func OrderExpr(raw string) OrderTerm

OrderExpr is the raw escape hatch for an ORDER BY term the typed helpers can't express (a function, a collation, NULLS FIRST). It is emitted verbatim.

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 And

func And(ps ...Predicate) Predicate

And / Or combine predicates; Not negates one.

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

func Match(col, q string) Predicate

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 Not

func Not(p Predicate) Predicate

func NotExists

func NotExists[T any](sub *SelectBuilder[T]) Predicate

NotExists renders `NOT EXISTS (subquery)`.

func Or

func Or(ps ...Predicate) Predicate

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 NewRepo

func NewRepo[T any](sess liteorm.Session) *Repo[T]

NewRepo constructs a Repo[T] bound to sess (a *DB or a transaction).

func (*Repo[T]) Delete

func (r *Repo[T]) Delete(ctx context.Context, keys ...any) error

Delete removes the row whose primary key equals the given key (one value per key column for a composite key).

func (*Repo[T]) Find

func (r *Repo[T]) Find(ctx context.Context, preds ...Predicate) ([]T, error)

Find returns all rows matching the typed predicates.

func (*Repo[T]) Get

func (r *Repo[T]) Get(ctx context.Context, keys ...any) (T, error)

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

func (r *Repo[T]) Insert(ctx context.Context, v *T) error

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

func (r *Repo[T]) InsertMany(ctx context.Context, vs []T) error

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

func (*Repo[T]) Update

func (r *Repo[T]) Update(ctx context.Context, v *T) error

Update writes v's non-key columns to the row identified by its primary key.

func (*Repo[T]) Upsert

func (r *Repo[T]) Upsert(ctx context.Context, v *T, oc OnConflictSpec) error

Upsert inserts v or, on conflict with oc.Columns, updates oc.Update (defaulting to all non-conflict insert columns).

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]) Iter

func (b *SelectBuilder[T]) Iter(ctx context.Context) iter.Seq2[T, error]

Iter runs the query and streams rows lazily as iter.Seq2[T, error].

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 Over

func Over() Window

Over starts an empty window specification.

func (Window) OrderBy

func (w Window) OrderBy(terms ...OrderTerm) Window

OrderBy adds ORDER BY terms to the window (use Asc/Desc).

func (Window) PartitionBy

func (w Window) PartitionBy(cols ...Field) Window

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 Lead

func Lead[V any](c Column[V], offset int) WindowFunc

func Rank

func Rank() WindowFunc

func RowNumber

func RowNumber() WindowFunc

Ranking window functions.

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

func (WindowFunc) Over

func (wf WindowFunc) Over(w Window, alias string) Field

Over attaches the OVER clause and the result alias, yielding a projection field: <func> OVER (<window>) AS <alias>.

Jump to

Keyboard shortcuts

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