Rindle

API index and search · Build metadata

@rindle/query-compiler

0.0.0 · Public export map; development manifest version (0.0.0).

Source revision 05d0bf2c2e56 · build details
Source revision: 05d0bf2c2e56.
TypeScript input SHA-256: aabe6cfcc4172b870d5e272142958e9ea8d8784c2aa23133156e5a7ee633318e
Generated 2026-09-04T23:58:25.590Z with TypeScript 6.0.3. Public TypeScript checks and declaration emit passed. Package runtime tests are separate.

Entry point source

Aggregate

TypeAliasDeclaration · Source: packages/client/src/ast.ts:67 · Supporting declarations

An aggregate over a (correlated) subquery's rows (REDUCE-DESIGN.md). v1: count(*). Set on a related subquery (Ast.aggregate), it marks that relationship a count aggregate the builder lowers to a scalar-projected singular relationship (§9).

export type Aggregate = "count";

Ast

InterfaceDeclaration · Source: packages/client/src/ast.ts:71 · Supporting declarations

The query AST. table is the only required field; the builder omits empty/false fields (matching the Rust skip_serializing_if), which the deserializer treats as absent.

export interface Ast {
    table: string;
    alias?: string;
    /** Projection (PROJECTION-SUPPORT-DESIGN.md §6). Absent ⇒ select all columns; present ⇒
     *  project to just these (drives what syncs + what the view reports). Serializes only when
     *  set, matching the Rust `Ast.select`'s `skip_serializing_if`. */
    select?: string[];
    where?: Condition;
    related?: CorrelatedSubquery[];
    start?: Bound;
    limit?: number;
    one?: boolean;
    /** Aggregate this (sub)query's rows instead of materializing them (`REDUCE-DESIGN.md`
     *  §9). `count` on a `related` subquery surfaces a scalar `commentCount` field; the
     *  builder lowers it to a scalar-projected singular relationship. Absent ⇒ ordinary rows. */
    aggregate?: Aggregate;
    /** The {@link Ast.aggregate} value is **precomputed** — supplied as rows of a (synthetic)
     *  source table rather than reduced from child rows. Set by the normalized client's AST
     *  rewrite (`AGGREGATE-SYNC-DESIGN.md` §3.3) so the local engine reads the server's count
     *  with a plain singular join + the same projection instead of a `reduce`. Only meaningful
     *  with `aggregate`; absent ⇒ `false`. */
    aggregatePrecomputed?: boolean;
    /** Top-level `GROUP BY` columns (names), meaningful only alongside a root {@link Ast.aggregate}
     *  (`REDUCE-DESIGN.md` §8). Empty + `aggregate` set ⇒ a **global** aggregate (one `[count]` row);
     *  non-empty ⇒ one `[group…, count]` row per distinct value-tuple. Distinct from a relationship
     *  aggregate's implicit grouping (the correlation child key). Absent on the wire ⇒ empty. */
    groupBy?: string[];
    /** `HAVING` — a filter over the **post-aggregation** rows of a root {@link Ast.aggregate}
     *  (`REDUCE-DESIGN.md` §4: a filter directly above the `reduce`). Its condition addresses the
     *  aggregate's *output* columns — the {@link Ast.groupBy} columns and the synthetic `count`
     *  column — not base-table columns (those go in {@link Ast.where}, which filters rows *below* the
     *  reduce). Absent ⇒ no post-aggregation filter. */
    having?: Condition;
    orderBy?: OrderPart[];
}

Bound

InterfaceDeclaration · Source: packages/client/src/ast.ts:53 · Supporting declarations

A paging lower bound (Bound, src/ast.rs). row is a partial wire row — the bound columns by name (only the sort columns are read by the engine's Skip comparator). exclusive ⇒ start after the bound row (Basis::After); else at it (Basis::At).

export interface Bound {
    row: Record<string, LitValue>;
    exclusive: boolean;
}

Cardinality

TypeAliasDeclaration · Source: packages/query-compiler/src/catalog.ts:8 · Supporting declarations

Whether a relationship yields a single child object (one) or an array (many).

export type Cardinality = "one" | "many";

Catalog

InterfaceDeclaration · Source: packages/query-compiler/src/catalog.ts:57 · Supporting declarations

The catalog: every table the compiler may reference, keyed by table name. Produced statically by rindle pg prepare from an ephemeral migration-built Postgres (§7, Phase B); hand-authored for tests. A pure input — the compiler never touches a database to obtain it.

export interface Catalog {
    tables: Record<string, TableSchema>;
}

ColumnType

InterfaceDeclaration · Source: packages/query-compiler/src/catalog.ts:25 · Supporting declarations

Per-column type detail the Postgres compiler needs for value-model↔native-type reconciliation (§6.2). Mirrors z2s's ServerColumnSchema: the raw Postgres type name plus the two flags the cast switch branches on. The extension over what rindle-pg-source derives today (§7, review decision 2): enums and arrays are carried distinctly instead of collapsing into a text fallback.

  • type — the native Postgres type name: "int4", "text", "bool", "float8", "numeric", "timestamptz", "timestamp", "date", "timetz", "time", "uuid", "json"/"jsonb", or an enum type name (paired with isEnum: true).
  • isEnumtype names a Postgres enum ⇒ cast via $N::text::"<type>".
  • isArray — the column is an array ⇒ unnest via jsonb_array_elements_text.

The SQLite oracle dialect ignores this entirely: it binds native values (no casts).

export interface ColumnType {
    type: string;
    isEnum: boolean;
    isArray: boolean;
}

compile

FunctionDeclaration · Source: packages/query-compiler/src/index.ts:66 · Supporting declarations

Compile ast against catalog into { sql, params } (§4). A pure function of its inputs — no database access (Invariant 2). The root is singular when ast.one is set (a single JSON object or null), else plural (a JSON array).

export declare function compile(ast: Ast, catalog: Catalog, opts: CompileOptions): CompiledQuery;

CompiledQuery

InterfaceDeclaration · Source: packages/query-compiler/src/index.ts:55 · Supporting declarations

A compiled query: one SQL SELECT plus its positional bound parameters. sql returns a single row with a single column "rindle_result" — the whole nested result as JSON (jsonb on Postgres, json text on SQLite). No runtime value is ever interpolated into sql; every filter/paging value is a bound parameter (Invariant 4).

export interface CompiledQuery {
    sql: string;
    /** In order: `$1..$n` for Postgres, `?` for SQLite. */
    params: unknown[];
}

CompileOptions

InterfaceDeclaration · Source: packages/query-compiler/src/index.ts:45 · Supporting declarations

export interface CompileOptions {
    dialect: DialectName;
}

Condition

TypeAliasDeclaration · Source: packages/client/src/ast.ts:39 · Supporting declarations

The filter tree — type-tagged; recursive. There is no generic NOT node (negation is via the negated operators and NOT EXISTS, matching src/ast.rs Condition).

export type Condition = {
    type: "simple";
    op: SimpleOp;
    left: ValuePosition;
    right: ValuePosition;
} | {
    type: "and";
    conditions: Condition[];
} | {
    type: "or";
    conditions: Condition[];
} | {
    type: "correlatedSubquery";
    related: CorrelatedSubquery;
    op: ExistsOp;
    flip?: boolean;
    scalar?: boolean;
};

CorrelatedSubquery

InterfaceDeclaration · Source: packages/client/src/ast.ts:58 · Supporting declarations

export interface CorrelatedSubquery {
    correlation: Correlation;
    subquery: Ast;
    system?: "client" | "permissions" | "test";
}

Correlation

InterfaceDeclaration · Source: packages/client/src/ast.ts:45 · Supporting declarations

export interface Correlation {
    parentField: string[];
    childField: string[];
}

Dialect

InterfaceDeclaration · Source: packages/query-compiler/src/dialect.ts:12 · Supporting declarations

export interface Dialect {
    readonly name: "postgres" | "sqlite";
    /** `json_object('k', v, …)` | `jsonb_build_object('k', v, …)`. `parts` are the flat
     *  `'key', valueExpr` fragments, in order. */
    objectBuild(parts: string[]): string;
    /** The array aggregate over `elem` with `orderSql` (e.g. ` ORDER BY __o0 ASC`) inside:
     *  `json_group_array(elem ORDER BY …)` | `jsonb_agg(elem ORDER BY …)`. */
    groupArray(elem: string, orderSql: string): string;
    /** The empty-array default for the `COALESCE` wrapper: `'[]'` | `'[]'::jsonb`. */
    readonly emptyArray: string;
    /** Re-assert the JSON subtype on a value round-tripped through a subquery's `AS` column
     *  (`json(x)` in SQLite; identity in Postgres, where `jsonb` is a real type). */
    reassertJson(x: string): string;
    /** The truthy/falsy constants for empty `AND`/`OR` folding and boolean keyword positions:
     *  `1`/`0` | `TRUE`/`FALSE`. */
    readonly trueLit: string;
    readonly falseLit: string;
    /** An `ORDER BY` direction with the engine's null-low ordering made explicit where the
     *  dialect default differs (§8): SQLite is null-low by default (`ASC`/`DESC`); Postgres's
     *  default is the opposite, so it must emit `ASC NULLS FIRST` / `DESC NULLS LAST`. */
    orderDir(dir: Dir): string;
    /** Project a stored column into the value model's representation for the result JSON.
     *  Identity in SQLite; the outbound half of §6.2 in Postgres (e.g. timestamptz → epoch-ms). */
    projectColumn(colRef: string, col: ColumnType | null): string;
    /** Bind a scalar filter/paging value as a parameter: push onto `params`, return the
     *  placeholder SQL. `col` is the compared column's type when known (drives the Postgres
     *  `::text::<type>` casts, §6.2); `null` ⇒ infer from the JS type. SQLite ignores `col`
     *  and `isComparison` — it binds natives. */
    bindValue(params: unknown[], value: LitScalar, col: ColumnType | null, isComparison: boolean): string;
    /** Double-quote an identifier, doubling embedded `"`. Identical across dialects (kept on
     *  the seam for uniformity). */
    quoteIdent(name: string): string;
}

DialectName

TypeAliasDeclaration · Source: packages/query-compiler/src/index.ts:43 · Supporting declarations

Which SQL dialect to emit. Both are product targets: postgres for the BYO-PG backend, sqlite for the daemon backend's session reads (and the offline oracle, §9).

export type DialectName = "postgres" | "sqlite";

Dir

TypeAliasDeclaration · Source: packages/client/src/ast.ts:5 · Supporting declarations

export type Dir = "asc" | "desc";

ExistsOp

TypeAliasDeclaration · Source: packages/client/src/ast.ts:35 · Supporting declarations

export type ExistsOp = "EXISTS" | "NOT EXISTS";

LitValue

TypeAliasDeclaration · Source: packages/client/src/ast.ts:11 · Supporting declarations

An untagged literal (null | bool | number | string | array). Numbers are one f64.

export type LitValue = null | boolean | number | string | LitValue[];

OrderPart

TypeAliasDeclaration · Source: packages/client/src/ast.ts:8 · Supporting declarations

One (field, direction) ordering — serializes as the 2-tuple ["id", "asc"].

export type OrderPart = [
    field: string,
    dir: Dir
];

postgresDialect

VariableDeclaration · Source: packages/query-compiler/src/postgres.ts:140 · Supporting declarations

The Postgres dialect — the BYO-Postgres server-mutator read target. Emits (sql, params) with $N::text::<type> parameters and never imports a driver (Invariant 7).

export declare const postgresDialect: Dialect;

SimpleOp

TypeAliasDeclaration · Source: packages/client/src/ast.ts:19 · Supporting declarations

The wire comparison operators (exact strings, src/ast.rs Op).

export type SimpleOp = "=" | "!=" | "<" | "<=" | ">" | ">=" | "IS" | "IS NOT" | "LIKE" | "NOT LIKE" | "ILIKE" | "NOT ILIKE" | "IN" | "NOT IN";

sqliteDialect

VariableDeclaration · Source: packages/query-compiler/src/dialect.ts:69 · Supporting declarations

The SQLite dialect — the daemon backend's session-read target (DAEMON-INTERACTIVE-TXN §5.4) and the offline differential oracle (§9). It binds native values as parameters (no ::text::<type> casts — SQLite is the canonical store, so there is no driver seam to pin and no second representation to reconcile), relies on SQLite's null-low default ordering (which matches the engine's null < everything), and re-asserts the json() subtype where objects round-trip through a subquery column. Matches rindle-d2s's raw SQL shapes so the two agree modulo parameterization; the executing connection must run PRAGMA case_sensitive_like = ON (every daemon cluster connection does — open_wal2).

export declare const sqliteDialect: Dialect;

TableSchema

InterfaceDeclaration · Source: packages/query-compiler/src/catalog.ts:44 · Supporting declarations

Per-table metadata the compiler needs beyond the Ast:

  • columns — the projected column list, in projection order (the order json_object/jsonb_build_object enumerates), matching the View's Schema.
  • primaryKey — the PK columns, for ordering-completion (§8): the compiler appends the full PK to every orderBy at every level for a total order, exactly as the engine's builder does (rindle::complete_ordering).
  • columnTypes — per-column native type detail, keyed by column name (§6.2; Postgres dialect only).
  • relationships — declared relationships → cardinality. This is the one structural fact not carried by the Ast (the relationship shape — correlation keys, nesting, where/order/limit — lives in the Ast's related subqueries).
export interface TableSchema {
    columns: string[];
    primaryKey: string[];
    columnTypes: Record<string, ColumnType>;
    relationships: Record<string, Cardinality>;
}

ValuePosition

TypeAliasDeclaration · Source: packages/client/src/ast.ts:14 · Supporting declarations

A column reference or a literal — type-tagged.

export type ValuePosition = {
    type: "column";
    name: string;
} | {
    type: "literal";
    value: LitValue;
};