Skip to content

Instantly share code, notes, and snippets.

@mjf
Last active October 10, 2025 13:38
Show Gist options
  • Save mjf/042e0292f2f6e09fedd42be24a3a2fc6 to your computer and use it in GitHub Desktop.
Save mjf/042e0292f2f6e09fedd42be24a3a2fc6 to your computer and use it in GitHub Desktop.
Synopsis of Lua `rel` class

Plan pipeline

rel({ rows })
  [ :as("alias") ]
  [ :sql() | :ra() ]
  [ :select(pred_or_expr, ...) ]
  [ :extend{ name = expr, ... } ]
  [ :project("col", ..., [expr:as("name")], [{ alias = expr, ... }]) ]
  [ :order_by( "col" | "-col" | expr:asc() | expr:desc() | function, ... ) ]
  [ :distinct([ "col", ... ]) ]
  [ :union(rhs) | :union_all(rhs) | :intersection(rhs) | :difference(rhs) | :except_all(rhs) | :cartesian_product(rhs) ]
  [ :join(rhs, "using_col", ...) | :join(rhs, {"lcol","rcol"}, ...) | :join(rhs, predicate_fn, ...) ]
  [ :natural_join(rhs [, ...]) ]
  [ :left_join(rhs [, ...]) | :right_join(rhs [, ...]) | :full_join(rhs [, ...]) ]
  [ :semi_join(rhs, "using_col" | {"lcol","rcol"} | predicate_fn) ]
  [ :anti_join(rhs, "using_col" | {"lcol","rcol"} | predicate_fn) ]
  [ :theta_join(rhs, predicate_fn) ]
  [ :group_by( "key" | { alias = "col" | expr }, ..., [ { agg_name = aggregator, ... } ] ) ]
  [ :having(pred_or_expr, ...) ]
  [ :limit(n) ]
  [ :offset(n) ]
  [ :divide(rhs) ]
  [ :unqualify() ]
  [ :execute() ]
  [ :to_table( [ replacement | { replace_null = value, keep_sentinels = true|false } ] ) ]

Expressions

  • constructors, operations, ordering tokens, conditionals
e.col("name") | e.qcol("alias","name") | e.lit(value)
expr + expr | expr - expr | expr * expr | expr / expr | expr % expr | -expr | expr .. expr
expr:eq(other) | expr:ne(other) | expr:lt(other) | expr:le(other) | expr:gt(other) | expr:ge(other)
expr:and_(other) | expr:or_(other) | e.not_(expr)
e.coalesce(expr1, expr2, ...) | e.nullif(a, b) | e.if_null(a, b) | e.fill_null(a, b) | e.is_null(a)
e.length(a)
expr:asc() | expr:desc()
e.switch([subject])
  :case(cond_or_value, result)
  [ :case(cond_or_value, result) ... ]
  :otherwise(result)
expr:as("new_name")

Aggregators (for group_by)

rel.count([ "col" | expr ])
rel.sum("col" | expr )
rel.avg("col" | expr )
rel.min("col" | expr )
rel.max("col" | expr )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment