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.