Skip to content

Projections

Project checked SQL row shapes instead of complete models.

Updated View as Markdown

SELECT { ... } chooses result columns and creates a typed projection row.

summaries := FROM Booking
    SELECT {
        id
        reference
        total: passengers * price_per_passenger
    }?

Bare fields keep their names. Use name: expression for a computed value or a renamed column.

Every projected field name must be unique in the result shape. Rename same-named joined columns explicitly rather than relying on database-generated labels.

Inferred rows

The compiler assigns every projected field a type from SQL expression rules. FROM produces a list of that row shape; ONE FROM and single GET produce an optional row.

info := GET Booking(id)
    SELECT { reference, passengers }?

A batch GET preserves its key-to-row map shape with projection rows as values.

Projection rows contain only selected values. They are not partially initialized models and cannot be passed where the complete model type is required.

Projection identity

Compiler-generated projections can be named through a function binding projection:

fn load_summaries(): []{
    id: int,
    reference: string,
    total: float,
} ! QueryError {
    summaries := FROM Booking
        SELECT {
            id
            reference
            total: passengers * price_per_passenger
        }?
    return summaries
}

Where another declaration must reference the compiler-minted nominal row, use the supported function::binding projection form described in Projections. Prefer an explicit record or struct at public boundaries.

An explicit public result type stabilizes field order, naming, and optionality even if the internal query later changes:

record BookingSummary {
    id: int
    reference: string
}

fn summaries(): []BookingSummary ! QueryError {
    return FROM Booking
        SELECT { id, reference }?
}

The checked context requires projected names and types to match.

Distinct rows

SELECT DISTINCT { ... } removes duplicate projected rows:

statuses := FROM Booking
    SELECT DISTINCT { status }?

Distinctness applies to the selected shape, not the full source model.

Ordering occurs independently of distinctness and must still be explicit when the caller needs deterministic presentation.

Computed values

Projection expressions can combine columns, literals, bound locals, scalar functions, aggregates, and supported subqueries. Nullability propagates through optional operands. Division follows the query engine’s checked SQL typing and may widen numeric results.

Aggregate-only projections can collapse to a single checked struct when the context requests that shape. Grouped or mixed projections retain their row-collection behavior; see Aggregates.

Runtime carriers

Some joined or advanced query shapes cannot materialize a full model carrier without an explicit projection. If lowering reports that a row shape cannot be carried, add SELECT with the exact fields the caller needs.

Frames also use the projection row as their compile-time schema. A later collect() decodes host-resident columns into the same named Atoll fields.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close