SQL frontend over the catalog engine
1(*---------------------------------------------------------------------------
2 Copyright (c) 2026 Thomas Gazagnaire. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** A SQL statement engine that runs over a {!Catalog.Spi.t} -- the storage
7 contract -- rather than any one backend. Parse, lower, and execute happen
8 here in [sql]; the store underneath is any {!Catalog.Spi} (a B-tree, the
9 in-memory reference, an Irmin tree). This is the boundary that moves
10 statement execution off the sqlite backend onto the engine.
11
12 [SELECT] runs the complete read dialect -- joins, aggregates / [GROUP BY] /
13 [HAVING], window functions, compounds ([UNION] etc.), [WITH] (including
14 recursive), correlated and FROM-subqueries, [VALUES] and table-function
15 sources -- entirely on the register VM ({!run_select}), with no tree-walker.
16 For writes it models [CREATE TABLE], [DROP TABLE], [INSERT] (VALUES and
17 SELECT sources), [UPDATE], and [DELETE], the [WHERE] / [SET] expressions on
18 the VM. Constraints, triggers, foreign keys, [DEFAULT] enforcement, upsert,
19 and [RETURNING] move over this boundary incrementally. *)
20
21type result =
22 | Rows of Catalog.Value.t list list (** a [SELECT]'s rows *)
23 | Done (** a statement with no result *)
24
25val exec : Catalog.Spi.t -> string -> result
26(** [exec cat sql] runs [sql]'s statements in order over [cat] and returns the
27 last statement's result.
28 @raise Failure on a parse error or a statement shape not yet supported. *)
29
30val run_select :
31 ?scope:Query.binding list ->
32 Query.catalog ->
33 Ast.select ->
34 Ast.value array ->
35 Ast.value list list
36(** [run_select cat s params] runs SELECT [s] over the catalog [cat] on the
37 register VM and returns its rows, the complete-dialect replacement for the
38 tree-walker. A backend builds a {!Query.catalog} over its {!Catalog.Spi.t}
39 (via {!Query.of_catalog}) and calls this for every SELECT. [?scope] is an
40 enclosing row (a correlated subquery, a trigger's OLD/NEW), substituted in
41 before the query runs.
42 @raise Failure on a non-substitutable correlated subquery. *)