Relix

Manual

Language reference

One page per keyword, operator and built-in function, with worked examples.

This is the complete reference for the Relix relational-algebra language — one page per keyword, operator and built-in function. The pages are arranged below in a learning order: start with getting started, which runs a first script end to end, then work down through the statements of a .relix file and the core operators toward joins, set algebra, aggregation, nested data and the advanced operators. The glossary defines the vocabulary the rest of the manual assumes. Every operator has both a Unicode form (e.g. σ, ⋈, ∪) and an ASCII keyword form (e.g. SELECT, JOIN, UNION); the two are interchangeable and produce identical results. Each page gives the syntax, a plain-English description, real-world examples, and "See Also" links to related pages. The harder operators include a fully worked example with sample data and the expected result.

New to relational algebra? Read the sections in order. Already fluent? Jump straight to the operator you need from the tables below.

Download this manual as a PDF

1. Getting started

New here? This is the whole language in one page: bring data in, filter and combine it, name the interesting steps, ask for a result. Everything below is detail on one of those four moves.

PageWhat it does
Getting startedYour first script — declare data, name a result, run it
GlossaryThe vocabulary: relation, tuple, bag vs set, materialisation, pushdown

2. Language & scripts

The shape of a .relix file — declaring data, naming results, and reusing code.

PageWhat it does
sourceDeclare an external data source (CSV, database, …)
http sourceRead JSON from an HTTP/REST API (headers, auth, body)
connectionShare one database connection across many sources
gedcom sourceRead a GEDCOM genealogy file as individuals and families
log sourceRead a web server access log as a typed relation
relateDeclare named, bounded relationships between relations (schema graph)
inline-tableEmbed small reference data directly in a script
assignment & queryName a view with := and mark a result query
delimited identifierBacktick a name that collides with a reserved word (`order`)
comments-- to end of line, /* … */ for a block
operator spellingsEvery operator's Unicode glyph and its ASCII equivalent
grammar (EBNF)The whole language as one EBNF grammar — every statement, operator and token
namespaceDeclare the script's namespace
importReuse symbols defined in another file
defDefine a scalar (per-value) function
def … : RELATIONDefine a table-valued (relation-returning) function
relation catalogrelix.relations — every relation the script can name, with its kind, size and whether it ends
introspection stdlibrelix.unused / relix.deps / relix.impact / relix.find / relix.schema / relix.cycles / relix.funcs — the engine's own introspection, shipped as Relix
observability feedrelix.events / relix.rules — the previous run's engine decisions, as queryable rows
component inventoryrelix.version — the engine, the facade and every discovered provider, as queryable rows
candidate keysrelix.keys — the collected candidate keys of every relation, one row per key column
reserved namespacerelix.catalog — the relix.* surface describing itself

3. Core operators

The everyday relational-algebra operators — the ones you reach for first.

OperatorUnicode / ASCIIWhat it does
Selectionσ / SELECTKeep rows that match a condition
Projectionπ / PROJECTPick, reorder, rename or compute columns
Renameρ / RENAMERename a relation or its columns
Distinctδ / DISTINCTRemove duplicate rows
Sortτ / SORT / ORDER [BY]Order rows by one or more keys
Limitλ / LIMITTake the first N rows (with optional offset)

4. Predicates

The conditions that go inside a σ (selection) or join.

PageUnicode / ASCIIWhat it does
Comparison= ≠ < ≤ > ≥Compare two values
And∧ / ANDBoth conditions hold
Or∨ / OREither condition holds
Not¬ / NOTNegate a condition
Null test⊥ / NULL / IS [NOT] NULLTest for a missing value
Set membership∈ / IN, ∉ / NOT INTest membership in a set
Pattern matchLIKE, NOT LIKEWildcard string match (% = any run, _ = any one char)

5. Joins

Combining two relations. The outer joins keep unmatched rows (with NULLs); the semi/anti joins filter the left relation by the existence of a match.

JoinUnicode / ASCIIWhat it does
Natural join⋈ / JOINMatch on shared column names
Theta join⨝ / ><Match on an explicit condition
Left outer join⟕ / |>< / LJOINKeep all left rows
Right outer join⟖ / ><| / RJOINKeep all right rows
Full outer join⟗ / |><| / FJOINKeep all rows from both sides
Semi join⋉ / SEMILeft rows that have a match
Anti join▷ / ANTILeft rows that have no match
AS-OF joinASOFMatch each row to the nearest-in-time row
Interval joinIJOINMatch intervals by an Allen relation (OVERLAPS, DURING, …)
Lateral joinLATERALInvoke a TVF per left row with correlated column arguments

6. Set operations

Treating relations as sets of rows.

OperationUnicode / ASCIIWhat it does
Union∪ / UNIONRows in either (deduplicated)
Union all⊎ / UALLRows in either (keeps duplicates)
Outer-union⊔ / OUNIONMerge different-schema relations (align common columns, NULL-pad the rest)
Intersection∩ / INTER / INTERSECTRows in both
Difference− / DIFF / MINUS / EXCEPTRows in the first but not the second
Symmetric difference∆ / SYMDIFFRows in exactly one
Cartesian product× / CROSSEvery combination of rows
Division÷ / DIVWhich X relate to all of the Y
Composition∘ / COMPOSEChain on a shared column and drop it

7. Grouping & aggregation

Collapse many rows into summary rows with γ (GROUP) and aggregate functions.

PageWhat it does
Group / Aggregationγ / GROUP [BY] — group rows and aggregate
SUMTotal of a numeric expression
AVGMean of a numeric expression
COUNTRows (COUNT(*)) or non-NULL values (COUNT(expr))
MINSmallest value
MAXLargest value
COLLECTGather a group's values into an array (NEST)
ARGMAXA value from the row with the maximum
ARGMINA value from the row with the minimum
Window / RollingROLLING … OVER … ROWS — sliding / cumulative aggregate added as a column (no row collapse)
Window / RankingWINDOW ROW_NUMBER/RANK/DENSE_RANK/PERCENT_RANK/NTILE — per-partition rank column added to every row
Window / OffsetWINDOW LAG/LEAD/FIRST_VALUE/LAST_VALUE — adjacent / boundary row value added as a column (no row collapse)

8. Nested data (NF²)

Relix relations can hold structs and arrays. These operators build and flatten nested values.

PageWhat it does
Struct constructionBuild a nested object { … } in a projection
Array constructionBuild an array [ … ] in a projection
COLLECTAggregate a group's values into an array (NEST)
Unnestμ / UNNEST — expand an array into rows (the inverse of COLLECT)
WITH ORDINALITYAdd a 1-based position column to an unnest
UnpivotUNPIVOT — fold named columns into rows (wide → long)
PivotPIVOT … BY … PER — turn distinct key values into columns (long → wide)
TreeTREE key BY parentKey [ORDER …] AS children — fold an adjacency relation into nested documents (recursive COLLECT)

9. Literals & temporal types

Writing constant values, including the first-class temporal types.

PageWhat it does
DATE literalDATE '2026-01-31'
TIME literalTIME '09:30:00'
TIMESTAMP literalTIMESTAMP '2026-01-31T09:30:00Z'
DURATION literalDURATION 'PT90M'
Truth relationsUNIT / EMPTY (aliases DEE / DUM) — the two zero-column relations

10. Built-in functions

Scalar functions usable in any expression (projection, selection, aggregate argument).

11. Advanced operators

Beyond standard SQL — recursion, per-group ranking, sampling, the declarative solver, combinatorial covering, and universal quantification. Each of these pages includes a fully worked example.

PageWhat it does
Universal quantification∀ / FORALL — groups where every row satisfies a condition
Top-K per groupTOP … PER — the N highest rows in each group
Transitive closureCLOSURE / RCLOSURE — reachability over a binary relation
Connected componentsCLUSTER … AS — label each node with its undirected component id
Bounded path reachabilityPATH … HOPS m TO n AS — pairs reachable within a hop window, with shortest distance
Optimal-path extractionTRACE … VIA … MINIMIZE|MAXIMIZE AS — cheapest/longest path with route array
General recursionFIX — least-fixpoint recursion (WITH RECURSIVE)
IterationITERATE — repeat a step until it settles: PageRank, state machines, convergence
Goal-seekSOLVE — fill the one blank in an equation, per row
Declarative optimisationOPTIMIZE — knapsack / allocation under constraints
Combinatorial coveringCOVER — minimal all-pairs (pairwise) subset
Bernoulli samplingSAMPLE p — keep each row with probability p
Reservoir samplingSAMPLE n ROWS — an exact-count uniform sample
DOWNSAMPLEDOWNSAMPLE ts BY '5m' USING AVG — time-series bucket aggregation
SessionizationSESSIONIZE ts GAP DURATION 'PT30M' PER … AS — split an ordered stream into sessions by an idle gap
Why (lineage provenance)ω / WHY — reify a tuple's lineage (which source rows produced it) as a queryable nested column
Query optimizerThe logical rewrite rules (SEL-…, LIM-…) and how to see which fired
PushdownWhat the backend computes and what the engine does — the boundary --explain draws