Reference

AST nodes

The canonical intermediate language Vadyl compiles to provider-specific execution. Read, write, DDL, document, key-value, graph, capabilities.

Every database operation in Vadyl is expressed as a typed AST. Providers compile the AST to their native dialect (T-SQL, PL/pgSQL, MongoDB aggregation pipeline, Cypher, CQL, …). There is no raw SQL string-building outside provider implementations — the AST is the canonical contract every plane consumes.

AST families

  • ASTCore — primitives (literals, references, columns, scalar expressions).
  • ASTRead — query plans (project, filter, sort, page, group, join, union).
  • ASTWrite — mutation plans (insert, update, delete, upsert, returning).
  • ASTDDL — schema operations (create table, alter column, create index, RLS policy, …).
  • ASTRelational — relational-specific (CTEs, window functions, lateral joins).
  • ASTDocument — document operations (collection scan, aggregation pipeline, doc filter, doc project).
  • ASTKeyValue — KV operations (get, put, delete, scan, batch, expire).
  • ASTGraph — graph operations (vertex scan, edge scan, traverse, shortest path, neighbors).
  • ASTMigrations — typed migration ops (add field, rename, drop, change type, copy, backfill).
  • ASTCapabilities — capability declarations and constraints.

BoolExpr

Predicates use a typed BoolExpr tree:

type BoolExpr =
  | { kind: "BoolLiteral"; value: boolean }
  | { kind: "And";  left: BoolExpr; right: BoolExpr }
  | { kind: "Or";   left: BoolExpr; right: BoolExpr }
  | { kind: "Not";  inner: BoolExpr }
  | { kind: "Cmp";  op: CmpOp; left: ScalarExpr; right: ScalarExpr }
  | { kind: "IsNull"; expr: ScalarExpr }
  | { kind: "InList"; expr: ScalarExpr; values: ScalarExpr[] }
  | { kind: "Between"; expr: ScalarExpr; low: ScalarExpr; high: ScalarExpr }
  | { kind: "Like"; expr: ScalarExpr; pattern: ScalarExpr; caseInsensitive?: boolean }
  | { kind: "Exists"; sub: QueryPlan }
  | { kind: "InSubquery"; expr: ScalarExpr; sub: QueryPlan }
  | { kind: "QuantifiedCmp"; op: CmpOp; expr: ScalarExpr; sub: QueryPlan; quantifier: "Any" | "All" }
  // Access predicates — resolved before reaching renderers
  | { kind: "HasRole"; role: string }
  | { kind: "HasClaim"; name: string; value: ScalarExpr }
  | { kind: "InContextSet"; setName: string }
  | { kind: "AuthStrengthAtLeast"; level: AuthStrength }
  | { kind: "AuthenticatedVia"; connector: string }
  | { kind: "SubjectTypeIs"; subject: SubjectType }
  | { kind: "SessionAgeLt"; duration: Duration };

ScalarExpr

type ScalarExpr =
  | { kind: "Literal"; value: unknown; type: ScalarTypeRef }
  | { kind: "ColRef"; columnName: string }
  | { kind: "ContextValue"; key: string }
  | { kind: "Func"; name: string; args: ScalarExpr[] }
  | { kind: "Cast"; expr: ScalarExpr; targetType: ScalarTypeRef }
  | { kind: "Case"; whens: CaseWhen[]; else?: ScalarExpr }
  | { kind: "Coalesce"; exprs: ScalarExpr[] };

Semantic lowering

AstSemanticLowering normalizes ASTs at plan consumption boundaries before any renderer sees them. The canonical example: Cmp(Eq, x, Literal(null)) rewrites to IsNull(x); Cmp(Ne, x, Literal(null)) rewrites to Not(IsNull(x)). Renderers can assume Cmp operands are non-null after lowering.

Provider compilation

Each provider implements the canonical render contracts:

  • SharedQueryRendering.RenderPredicateCore — SQL-standard BoolExpr to dialect SQL.
  • SharedMutationRendering.RenderBoolExprCore — same for mutation paths with parameterized bindings.
  • IDialectAdapter — provider-specific hooks (case-insensitive LIKE, regex, IS DISTINCT FROM, security predicates, collation, IN-list limits).

Adding a new BoolExpr / ScalarExpr node type requires updating both shared cores plus dialect implementations on every relational provider. Document / KV / graph providers handle their own AST families.

Why an AST

An AST gives Vadyl one canonical place to apply security predicates, cache decisions, audit annotations, query optimization, and cross-provider plan rewriting — without depending on string-level SQL parsing. It's how the same canonical operation works across seven storage families.