nautilus-core
The foundational query AST and type system for the Nautilus ORM. Every other crate in the workspace depends on this one — it defines the language that queries, dialects, connectors, and the code generator all speak.
Purpose
nautilus-core provides:
- A query AST — immutable value types representing SELECT, INSERT, UPDATE, and DELETE statements along with the expressions that can appear inside them.
- A type system — the
Valueenum that bridges Rust scalar types and database column values, along with theFromValue/SelectColumnstraits that drive row decoding. - A column API — typed
Column<T>/ColumnMarkerstructs that carry table and column metadata and can build filter expressions in a type-safe way. - Query builders — ergonomic
*Builderfacades (SelectBuilder,InsertBuilder, etc.) that produce validated AST nodes. - A cursor helper —
build_cursor_predicatefor stable keyset pagination over composite primary keys. - Structured query arguments —
FindUniqueArgsandFindManyArgs, the entry points used by the engine and codegen layers. - Core error types —
ErrorandResultfor query-construction failures (missing table, type mismatch, etc.); runtime execution errors live innautilus-connector.
Public API Overview
| Item | Description |
|---|---|
Value |
Unified column value enum (Null, Bool, I32, I64, F64, Text, Bytes, Uuid, DateTime, Decimal, Json, Array, Array2D) |
Expr |
Expression AST: comparisons, boolean logic, IN, IS NULL, EXISTS, json_build_object, raw Literal |
Column<T> |
Typed column reference; carries table name, column name, and a PhantomData<T> for builder methods like .eq(), .gt(), .contains() |
ColumnMarker |
Lightweight marker used by the codegen layer for reflection without a type parameter |
FromValue |
Trait implemented for every Rust type that can be decoded from a Value |
SelectColumns |
Trait for tuple-based multi-column decoding (1–8 elements); drives SELECT projection in connectors |
RowAccess |
Trait for looking up a column by alias in an abstract row |
Select / SelectBuilder |
SELECT AST + builder (columns, joins, filters, order, take/skip) |
Insert / InsertBuilder |
INSERT AST + builder (single and batch) |
Update / UpdateBuilder |
UPDATE AST + builder |
Delete / DeleteBuilder |
DELETE AST + builder |
FindUniqueArgs |
Query argument for a single-row lookup by a required Expr filter |
FindManyArgs |
Query argument for a multi-row query with optional filter, order, take, skip, and cursor |
build_cursor_predicate |
Builds a keyset-pagination Expr from a composite PK cursor token |
Error / Result |
Query-construction error enum and std::result::Result<T, Error> alias |
Usage Within the Project
graph LR
core[nautilus-core]
dialect[nautilus-dialect]
connector[nautilus-connector]
codegen[nautilus-codegen]
engine[nautilus-engine]
lsp[nautilus-lsp]
dialect -->|renders AST → SQL| core
connector -->|executes queries| core
codegen -->|inspects ColumnMarker / SelectColumns| core
engine -->|composes FindUniqueArgs / FindManyArgs| core
lsp -->|reads schema metadata| core
The dependency is strictly one-way: nautilus-core has no knowledge of SQL dialects, database drivers, or network transports.
Design Notes
Query builders are fallible at build time, not at execution time
All *Builder::build() methods validate the query (required fields present, column/value counts match, etc.) and return Result<Ast> eagerly. This means invalid queries are caught before they reach the connector or the dialect renderer.
Value deserialization is JSON-only
impl Deserialize for Value routes through serde_json::Value. Binary serde formats (bincode, postcard, MessagePack) are not supported because the intermediate JSON representation loses type fidelity (e.g. all integers become f64). If binary serialization is needed, implement a custom visitor.
Array2D is a connector-level concern
json_to_value_ref (the canonical JSON→Value converter) does not auto-promote Array(Array(_)) to Array2D. Promotion happens in the connector stream decoders where the column schema is known, preventing silent misclassification of heterogeneous or empty nested arrays.
SelectColumns arity is bounded at 8
Tuple SelectColumns impls are generated for arities 1–8. This is a deliberate limit; projections with more columns should use a named struct with a hand-written FromRow impl (generated by nautilus-codegen).