7.9.18. SQL-17 — Subqueries
Four daslib/linq_boost macros lower to SQL’s IN / NOT IN /
EXISTS / NOT EXISTS forms when used inside a _where predicate
under _sql(...):
Source shape |
Emitted SQL |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
7.9.18.1. Why explicit positive/negative names
Negated forms have explicit names (_not_in, _none)
rather than !_in(...) / !_any(...). The _sql AST walker
pattern-matches on the macro’s textual name; a leading ! would
require deep AST walking that fights with daslang’s expansion order.
Expect this convention to repeat for any future predicate primitive
with a negated form.
7.9.18.2. IN / NOT IN with a single-column subquery
For IN-style subqueries, project a single column with
_select(_.Col) so the IN list shape matches.
let with_orders <- _sql(db |> select_from(type<User>)
|> _where(_.Id._in(db |> select_from(type<Order>) |> _select(_.UserId))))
// SELECT "Id", "Name", "Active" FROM "Users"
// WHERE "Id" IN (SELECT "UserId" FROM "Orders")
let no_orders <- _sql(db |> select_from(type<User>)
|> _where(_.Id._not_in(db |> select_from(type<Order>) |> _select(_.UserId))))
// ... WHERE "Id" NOT IN (...)
7.9.18.3. EXISTS / NOT EXISTS
let some_big <- _sql(db |> select_from(type<User>)
|> _where((db |> select_from(type<Order>))._any(_.Total > 200)))
// ... WHERE EXISTS (SELECT ... FROM "Orders" WHERE "Total" > ?)
let no_huge <- _sql(db |> select_from(type<User>)
|> _where((db |> select_from(type<Order>))._none(_.Total > 1000)))
// ... WHERE NOT EXISTS (SELECT ... FROM "Orders" WHERE "Total" > ?)