ExSQL. Codegen
(exsql v0.1.13)
Copy Markdown
Runtime query codegen — the JIT path.
Two shapes compile today:
- single-table scan / filter / project / sort, and
- two-table
LEFT JOINon an equi-key — hash-joined, with NULL-filled non-matches, residualONfilters pushed into the index build, and 2-argCOALESCE(col, literal)projections.
For either, this compiles a parsed %ExSQL.AST.Select{} into a native BEAM
function (via Module.create/3, which the compiler/JIT turns into machine
code) rather than walking the AST per row. Columns are read positionally from
the stored row tuple (:erlang.element/2), and SQL semantics are preserved by
delegating comparisons/booleans/affinity to ExSQL.Value — the exact functions
the tree walker uses.
Literals are lifted to a params tuple so a query shape compiles once and is
reused for any literal values (WHERE x > 30 and WHERE x > 40 share a module;
the value is a runtime argument). Compilation costs a few ms and only pays off
for repeated/prepared queries, so the caller gates on that and falls back to the
tree walker for anything compilable?/2 rejects.
The generated function takes the table's positional rows ([{rowid, tuple}],
scan order) plus a params tuple and returns [[value, ...]] — the same shape
as a tree-walked result's rows. The scan form is run(rows, params); the join
form is run(left_rows, right_rows, params), which indexes the right side by
the (affinity-canonicalized) join key and probes it once per left row, then
re-verifies each candidate with an exact comparison before emitting.
Summary
Functions
Compiles a spec (from compilable?/2) into a native module. Returns {:ok, %{module, params, columns}}.
Returns {:ok, spec} if stmt is a supported single-table scan shape, else
:no. The spec carries column positions, a param-lifted WHERE/ORDER/LIMIT IR,
and the lifted literal values.
Runs stmt via a compiled native function when enabled, the shape is supported,
and it's been seen enough times to compile. Returns {:ok, %ExSQL.Result{}} or
:fallback (use the tree walker). Enabled by EXSQL_CODEGEN=1.
Functions
Compiles a spec (from compilable?/2) into a native module. Returns {:ok, %{module, params, columns}}.
@spec compilable?(ExSQL.AST.Select.t(), ExSQL.Database.t()) :: {:ok, map()} | :no
Returns {:ok, spec} if stmt is a supported single-table scan shape, else
:no. The spec carries column positions, a param-lifted WHERE/ORDER/LIMIT IR,
and the lifted literal values.
@spec run_select(ExSQL.Database.t(), ExSQL.AST.Select.t()) :: {:ok, ExSQL.Result.t()} | :fallback
Runs stmt via a compiled native function when enabled, the shape is supported,
and it's been seen enough times to compile. Returns {:ok, %ExSQL.Result{}} or
:fallback (use the tree walker). Enabled by EXSQL_CODEGEN=1.