Skip to content

Filters

Filter, order, and page integrated SQL results.

Updated View as Markdown

Query expressions resolve bare model fields as columns and ordinary source locals as prepared-statement parameters.

fn page(minimum: int, limit: int): []Booking ! QueryError {
    return FROM Booking
        WHERE passengers >= minimum
        ORDER BY created_at DESC, id ASC
        LIMIT limit?
}

The compiler checks column names, operator types, parameter encodings, and the selected engine’s clause support.

Qualify a field with its model name when a source local has the same spelling or when a join introduces another column with that name.

Predicates

Repeat WHERE for an implicit conjunction, or use &&, ||, and !:

rows := FROM Booking
    WHERE active
    WHERE total > minimum && status != cancelled?

Arithmetic, scalar functions, IN, EXISTS, and scalar subqueries can appear inside predicates where their types fit.

rows := FROM Booking
    WHERE status in allowed_statuses
    WHERE total >= minimum?

Bound collections and subqueries use compiler-supported IN encodings. The right-hand query must project one compatible column.

Optional database values follow SQL null semantics. Use the query language’s supported null checks rather than assuming ordinary boolean equality turns a missing value into false in every dialect.

Ordering

Use ASC or DESC after each key:

rows := FROM Booking
    ORDER BY priority DESC, created_at ASC?

An expression of type SortDir or bool may choose a runtime direction for a plain key. The compiler pre-renders statement permutations rather than binding an SQL keyword. At most six runtime-direction keys are accepted.

direction: SortDir = if descending { Desc } else { Asc }
rows := FROM Booking
    ORDER BY created_at direction?

With bool, true means descending. The bounded six-key limit prevents an unbounded prepared-statement explosion.

Paging

LIMIT and OFFSET accept checked integer expressions:

rows := FROM Booking
    ORDER BY id
    LIMIT page_size
    OFFSET page * page_size?

Paging without stable ordering may return different rows between executions.

Validate untrusted page sizes and offsets in Atoll before executing the query. The compiler checks types and dialect support; application range policy remains the caller’s responsibility.

For keyset pagination, express a stable key predicate and ordering rather than increasing OFFSET indefinitely.

Guards

Selected clauses accept an if guard:

rows := FROM Booking
    WHERE status == wanted if filter_status
    ORDER BY created_at DESC if newest_first?

Guarded WHERE and HAVING use boolean parameter gates. A guarded static ORDER BY key uses a CASE gate. This remains one fixed prepared statement.

The guarded expression is still type-checked even when a particular runtime call supplies false. Guards control SQL behavior, not source reachability.

Shape-changing guards are rejected. Current unsupported combinations include:

  • conditional joins;
  • conditional update assignments;
  • guarded set-operation ordering;
  • a runtime sort direction and if guard on the same key.

Choose between two complete queries with ordinary if when a guard changes row cardinality or statement shape.

Statement stability

Column names, operators, clause order, and SQL keywords remain compile-time choices. Runtime values can affect predicates, limits, offsets, guards, and a bounded direction selector. This keeps statement registration and row decoding fixed for the compiled program.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close