Abstract Paged Query
Abstract base class for PagedQuery — a stateless, thread-safe query executor designed for server-side use (REST, RPC, gRPC, any stateless request/response context). Users do not instantiate this directly; use the platform-specific PagedQuery subclass instead.
A PagedQuery holds only column definitions and fixed constraints. It does not hold per-request mutable state (no filter/sort on Facet, no cached page, no selected entity, no kotlin.collections.AbstractList surface). All dynamic state flows per request through execute via a PageSpec; the result of each call is a fresh Page.
Configure a PagedQuery once (typically at application startup, per endpoint / grid) and share the instance across arbitrarily many concurrent execute calls.
When to use PagedQuery vs PagedList
Use
PagedQuerywhen the caller is stateless (REST handler, RPC method, background job that processes spec'd queries). Facet aliases are the only identifiers that cross the boundary — no schema, no SQL, no paths.Use
PagedListwhen you're driving a stateful UI grid that keeps selection, lazy page cache, and per-column filter mutation across user interactions.
Usage
// One-time setup, ideally at application startup:
val customers = PagedQuery<Customer>().apply {
addFacet("search", "name", "email", "city").also {
it.isSortable = false // search is filter-only
}
addFacet("name", "name") // filterable + sortable
addFacet("city", "city")
}
// Per request:
val page: Page<Customer> = customers.execute(
PageSpec(
filters = mapOf("search" to "acme"),
sorts = mapOf("name" to SortDir.ASC),
page = 0, pageSize = 25,
)
)Inheritors
Properties
Functions
Adds a filter/sort column under alias with one or more field paths. The column type is auto-detected from the first path's Kotlin type. Multiple paths use OR logic during filtering (e.g., a single "search" column that matches any of several fields).
Adds a column using type-safe KSP-generated path objects.
Enum-column variant of addFacet with an explicit display→DB value map.
Enum-column typed-path variant.
Explicit-type variant of addFacet.
Explicit-type typed-path variant.
Adds a raw/custom column backed by an arbitrary SQL expression (e.g. "SUM(amount)", "COALESCE(a, b)"). The expression is emitted verbatim, so it is the configurator's responsibility to make it safe and dialect-compatible — it is never derived from user input.
Raw column with a custom Converter for filter semantics.
Registers a TableRef for the root entity table. The ref's TableRef.alias resolves to the underlying DB table name, so raw SQL in setConstraints or in an addSqlFacet expression can safely reference the root without hardcoding the table name.
Registers a TableRef for a table reached through the given dotted path (e.g. "address", "company.hq"). The final segment must be an FK reference, not a scalar field. The associated JOIN is activated in every subsequent SQL build while the ref's TableRef.isActive is true.
Registers a TableRef from a KSP-generated typed ReferencePath.
Returns one page of distinct values for alias together with their row counts — facet-picker style. Same filter semantics as filterValues: the facet's own filter is excluded.
Returns an aggregation builder bound to this query and the filters/ constraints derived from spec. Page/pageSize are ignored — aggregations always consider the entire matching set.
Sets a fixed constraint (baseline WHERE clause) that is always applied in addition to any per-request filters. Use for server-enforced narrowing that must not be overrideable by the client (e.g., "tenant_id = ?").