Skip to content

The query builder

The query package is LiteORM’s explicit, generics-first query builder. You write query.Select[T](sess), chain typed predicates and clauses, and finish with a terminal that runs the SQL and scans rows straight into your struct T. If you’d rather work declaratively — models, associations, migrations — see the orm front-end; the two share one core and interoperate on a single transaction, so choosing one here never locks you out of the other. Not sure which to reach for? Start with Query or ORM?.

For exhaustive API detail, see the reference at pkg.go.dev/liteorm.org/query.

Every query runs on a liteorm.Session — a *liteorm.DB or a transaction, since both satisfy the interface. Open one with a dialect package; SQLite is the simplest, and the rest open the same way:

import (
"liteorm.org/dialect/sqlite"
"liteorm.org/query"
)
db, err := sqlite.Open("app.db")
if err != nil {
return err
}
defer db.Close()

Other backends return the same *liteorm.DB, so nothing else on these pages changes when you switch: postgres.Open(ctx, dsn), mysql.Open(ctx, dsn), mssql.Open(ctx, dsn). See connecting to a database for the full setup.

A model is a plain struct. The table name comes from a TableName() string method if you define one, otherwise it’s the snake_case of the type name — singular by default, or pluralized if you opt in with orm.UsePluralTableNames(true) (both front-ends share that one setting).

type Product struct {
ID int64
Name string
Category string
Price float64
Stock int64
Active bool
}
func (Product) TableName() string { return "products" }

query.Select[T](sess) opens a typed SELECT over T. Chain clauses, then call a terminal — .All(ctx) returns every matching row as []T:

products, err := query.Select[Product](db).All(ctx)

From there the builder splits into task areas:

I want to… See
filter, order, paginate, fetch rows Reading data
join tables, IN / EXISTS subqueries, derived tables Joins & subqueries
CTEs, window functions, set ops, DISTINCT ON, row locks Advanced SQL
insert, bulk, upsert, multi-row UPDATE/DELETE, RETURNING Writing data
stream large results, pluck, group, aggregate Streaming & aggregates
drop to hand-written SQL Raw SQL
  • Query or ORM? — the decision guide, and how the two front-ends share a Session.
  • The orm front-end — declarative models, associations, migrations.
  • Transactions — running any of these builders inside a tx.
  • Errors — the normalized errors these terminals return.