The binder currently supports one relation, derived table, table function, or
supported left-deep join chain in FROM; it also supports no FROM for
constant expressions.
SELECT a, b + 1 AS b1
FROM events
WHERE a > 10
ORDER BY b1
LIMIT 50;FROM-first query syntax is also accepted:
FROM events
SELECT a, b + 1 AS b1
WHERE a > 10
LIMIT 50;Use standard SELECT ... FROM ... syntax unless you are intentionally matching
DuckDB-style examples.
FROM
Supported FROM items:
- a registered table
- a non-lateral derived table
- a table function call
- one table alias; column alias lists are supported for derived tables and CTEs
Examples:
SELECT *
FROM events AS e
LIMIT 10;SELECT function_set, summary
FROM spql.meta.table_functions()
WHERE visibility = 'public';SELECT recent.id, recent.score
FROM (
SELECT id, score
FROM events
WHERE score > 0
) AS recent;Not yet supported:
- join shapes outside left-deep
INNER JOIN ... ONfield-reference equality - lateral derived tables
- lateral table functions
- nested joins
- more than one
FROMrelation
CTEs
Non-recursive CTEs are bound inline and can rename output columns:
WITH totals(category, total_score) AS (
SELECT category, sum(score)
FROM events
GROUP BY category
)
SELECT category, total_score
FROM totals
WHERE total_score > 100;Recursive CTEs are not supported.
Projection
Supported:
- Column references.
- Expression aliases with
AS. - Unqualified
*.
Projection names are preserved for simple column references and aliases.
Generated expression names use column1, column2, and so on.
Not yet supported:
- Qualified wildcards.
- Wildcard options such as
EXCLUDE,REPLACE, andRENAME. - Multi-alias projection items.
Filtering
WHERE accepts supported scalar expressions. See
Expressions.
Aggregation
Use GROUP BY with field references or scalar expressions:
SELECT category, count(*) AS rows
FROM events
GROUP BY category;Aggregate calls are supported as direct projection items:
SELECT category, sum(score) AS total_score
FROM events
GROUP BY category;Expressions in GROUP BY are materialized into generated helper fields before
aggregation when needed:
SELECT amount + 1 AS bucket, count(*) AS rows
FROM events
WHERE amount IS NOT NULL
GROUP BY amount + 1
HAVING amount + 1 > 20
ORDER BY bucket;HAVING is supported for aggregate queries:
SELECT category, count(*) AS rows
FROM events
GROUP BY category
HAVING count(*) > 10;Current limits:
GROUP BY ALLis not supported.- Aggregate calls nested inside projection expressions are not supported.
Ordering and limits
ORDER BY supports output field references and scalar expressions. If an
ordering expression is not part of the projected output, the binder materializes
a generated helper field before sorting or top-k and drops it afterward.
Without LIMIT, only ascending NULLS FIRST ordering is supported. With
LIMIT, Spiral uses the Top-K path and can plan descending order and null
ordering.
LIMIT and OFFSET must be integer literals.
Examples:
SELECT id, score
FROM events
ORDER BY score DESC NULLS LAST
LIMIT 20;SELECT id, score
FROM events
ORDER BY id
OFFSET 100
LIMIT 50;SELECT id
FROM events
WHERE amount IS NOT NULL
ORDER BY amount + 1
LIMIT 20;Not yet supported
Set operations, DISTINCT, QUALIFY, window functions, recursive CTEs, lateral
derived tables, and join shapes outside the supported inner equi-join subset are
parsed in some cases but are not yet bound by the current execution path.