Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

marsdb-storage   thin trait boundary over redb (file + in-memory backends)
marsdb-graph     property graph model, CRUD, KV/adjacency encoding
marsdb-query     openCypher subset: ANTLR4 grammar -> AST -> IR -> executor
marsdb           embeddable public Rust API (Database::open/in_memory/execute)
marsdb-cli       the `marsdb` binary (REPL + one-shot mode)
marsdb-python    PyO3 bindings, builds via maturin
marsdb-capi      C ABI (opaque handle + JSON results), basis for non-Rust bindings
marsdb-go        Go bindings, via cgo against marsdb-capi
marsdb-nl2cypher natural-language -> Cypher: schema introspection, prompt building, validate-and-repair

Storage

Storage runs on redb, a pure-Rust single-file MVCC embedded KV engine. Every Cypher statement runs inside one transaction — a read-only MATCH ... RETURN opens a ReadTransaction (a consistent snapshot that runs alongside other concurrent readers or a concurrent writer without contending for redb’s single-writer lock), everything else opens a WriteTransaction, committed or aborted as a whole. Database::begin_transaction lets callers explicitly extend that atomic boundary across multiple statements. MarsDB records its own table/record format version in metadata when the file is created or first opened by a version-aware build, and refuses to open a database written by a newer unsupported format.

A from-scratch storage engine (page format, B-tree, crash recovery) as an alternate marsdb-storage backend independent of redb is on the roadmap, not built yet — the trait boundary in marsdb-storage exists specifically so a second backend could slot in later without touching marsdb-graph/ marsdb-query.

Query execution

Query execution compiles Cypher to a small Gremlin-shaped logical IR (AllNodesScan, NodeByLabelScan, Seed, Expand, VarExpand, Filter, IndexSeek) so a future Gremlin frontend could target the same executor. The parser is ANTLR4-generated (marsdb-query/grammar/), replacing an earlier hand-rolled pest grammar.

The logical read plan runs as a pull-based row stream through node-ID scans, filters, and relationship expansions. A non-aggregating, non-distinct RETURN ... LIMIT k without ORDER BY stops that pipeline after k rows, so downstream limits avoid unnecessary expansions. Clause boundaries and inherently blocking operations still materialize: WITH, optional-match reconciliation, variable-length traversal results for each input row, aggregation, DISTINCT, mutations, and the public QueryResult. Use ExecutionOptions to put hard ceilings on intermediate rows, result rows, relationship expansions, and elapsed time.

There is not yet a general cost-based optimizer. Two targeted optimizations complement streaming: a direct MATCH (n[:Label]) RETURN ... LIMIT k scan pushes the limit into storage; and every ORDER BY ... LIMIT k site uses a top-k partial selection (slice::select_nth_unstable_by + a sort of just the k-sized prefix) instead of a full sort of every row. Declared property indexes (CREATE INDEX ON :Label(prop)) are used automatically when a WHERE/ inline-property equality matches one — see the index seek benchmarks.

Cypher coverage

See Cypher Language Support for the full, TCK-measured breakdown.