Docs
View as markdown

Rust API

The relate crate's public API at its root, with Database, Connection, OpenOptions, QueryResult, the Value mapping, error variants and codes, and features.

rust

The relate crate is the engine as a Rust library: a Database opens a store A relate database: a directory, a single .rl file, or :memory:, opened with --database. Read more in the glossary, a Connection runs statements on it, and each statement returns a QueryResult of Value rows or a relate::Error. This page lists what the crate exports at its root (every name is relate::<name>), as of relate 0.1.2. The C application binary interface (ABI) and the Python client are built on the same Database. The guide Use the Rust crate covers the same API with runnable programs.

Synopsis

use relate::{Database, OpenOptions, Value};

Database::open(uri) -> Result<Database>
Database::open_with(uri, OpenOptions) -> Result<Database>
Database::clone(source, dest, CloneOptions) -> Result<()>
db.connect() -> Result<Connection>
conn.query(cypher) -> Result<QueryResult>
conn.query_with_params(cypher, BTreeMap<String, Value>) -> Result<QueryResult>
conn.begin() -> Result<()>
conn.commit() -> Result<Option<String>>
conn.rollback() -> Result<()>
relate::error_info(&Error) -> ErrorInfo

relate::Result<T> is std::result::Result<T, relate::Error>. A uri is ":memory:", a filesystem path or a file:// URI: a path ending in .rl (or the legacy .cl) is a single-file store A store kept in one .rl file that holds the snapshot and the WAL together; the layout for a --database path ending in .rl. Read more in the glossary, any other path a directory store. An s3:// URI is refused at open.

Cargo features

The crate is relate, in the workspace at version 0.1.2, with rust-version 1.88 and edition 2021. Before crates.io publication it is a Git dependency, cargo add --git https://github.com/relatedb/relate relate.

FeatureDefaultEffect
parquetonCompiles the Parquet snapshot codec and its Arrow and Parquet dependencies. Without it, new stores use the JSON codec, and opening a Parquet store or asking for SnapshotCodecKind::Parquet fails at open with Error::Storage carrying parquet snapshot codec is not compiled into this build (enable the "parquet" feature); there is no fallback to JSON.
rkyv-codecoffCompiles the experimental rkyv snapshot codec, SnapshotCodecKind::Rkyv, on native targets, for measurement only; a store it writes opens only in a build with the feature. Without it, asking for Rkyv fails at open with Error::Storage carrying rkyv snapshot codec is not compiled into this build (enable the "rkyv-codec" feature).
researchoffResearch-only kernels; outside the public API

Database

An open store. Database is Send and Sync; dropping it stops the background checkpoint and durability threads, and a Connection still alive keeps the store open.

ConstructorOpens
open(uri)Writable; creates a missing store. Loads the snapshot, then replays the WAL.
open_read_only(uri)OpenMode::ReadOnly: an existing store, loaded once; never writes, checkpoints, or migrates it
open_ephemeral(uri)OpenMode::Ephemeral: loads an existing store into memory, then releases the source file or directory; writes and checkpoints are refused
open_with(uri, OpenOptions)With the settings in OpenOptions
open_with_wal_dir(uri, Option<PathBuf>)Writable, with a directory store's WAL in another directory
open_vfs(Arc<dyn Vfs>, OpenOptions)On a caller-supplied virtual file system, as the WebAssembly build does; OpenMode::Follow is refused
clone(source, dest, CloneOptions)Not an open: copies a store into a new one. Each side's layout follows its path (.rl or a directory). The source opens read-only and is never written; dest must not exist, and a failed clone removes it. :memory: is refused on both sides, and a writer-held .rl source fails with Error::Locked.
MethodReturns
connect()A Connection in the neo4j namespace
connect_namespace(&str)A Connection whose session namespace is neo4j, system or system_ontologies, matched case-insensitively; another name fails with Error::DatabaseNotFound
connect_typed(Namespace)The same, with a Namespace value
checkpoint()Writes a checkpoint: a snapshot, then the closed WAL segments recycled; on a read-only handle, the read-only error
checkpoint_if_writable()checkpoint(), or success without writing on a read-only or follow handle
snapshot_data_bytes()The size of the latest snapshot, WAL excluded; 0 before the first checkpoint, and on :memory: until an explicit checkpoint()
memory_usage()(logical bytes of the live graph and its indexes, the configured limit or None)
is_read_only(), is_follower(), is_safe_mode()The handle's mode
needs_reopen()true when a FollowGapPolicy::Yield follower stopped at a gap; new queries then fail with the retryable follow-gap limit
promote(), demote(), is_draining()Take or hand back the writer lease between a writer and a follower of the same directory store
register_procedure(Procedure)Registers a procedure that later statements can CALL
register_cdc_slot(&str), ack_cdc_slot(&str, u64), drop_cdc_slot(&str), cdc_slots(), cdc_records_after(u64, usize)Change data capture: a slot holds WAL recycling until its consumer acknowledges a log sequence number (LSN); cdc_records_after returns at most limit records after an LSN without blocking
set_apply_only(bool), apply_only(), apply_replicated(&WalRecord)A read replica: Cypher writes refused, records applied from another store's WAL
ontology_document(), commit_ontology_set(String), commit_ontology_drop()The store's ontology document, read, replaced, or dropped
token_pool(), on_token_ceiling(hook)The shared workspace pool's reservations, when admission is on
enable_commit_timing(), clear_commit_timing(), commit_timing_report()A histogram of commit steps; empty unless RELATE_COMMIT_TIMING=1
leak_without_checkpoint()Drops the handle without the final checkpoint, as a crash after the WAL sync would

OpenOptions

The settings of Database::open_with, a struct with public fields and Default. OpenOptions::with_mode(mode) is the default with mode set. An Option field left None reads the environment variable its Default cell names, then takes the default; wal_dir and load_csv_max_bytes read none. A set variable that does not parse fails the open.

FieldTypeDefaultMeaning
modeOpenModeWritableHow the open attaches to the store
durability_modeOption<DurabilityMode>RELATE_DURABILITY_MODE, else FullWhen a commit is acknowledged; not persisted with the store
checkpoint_intervalOption<Duration>RELATE_CHECKPOINT_INTERVAL_SECS, else 300 seconds (DEFAULT_CHECKPOINT_INTERVAL_SECS)The checkpoint timer, which runs when the WAL has work; Duration::ZERO turns it off
wal_dirOption<PathBuf><store>/walA directory store's WAL directory; ignored for :memory:
snapshot_codecOption<SnapshotCodecKind>RELATE_SNAPSHOT_FORMAT, else Parquet (JSON without the parquet feature)A new store's codec: Parquet, Json, Markdown, or the experimental Rkyv (only with the rkyv-codec feature). An existing directory store keeps its own; a different one is an error.
wide_columnsboolfalseOpts a Parquet store into the wide-column encoding: its next checkpoint writes one typed column per promoted property key beside a JSON tail, and the store stays wide from then on, whatever later opens set. On a store whose codec is not Parquet, or with markdown_body_properties set too, the open fails with Error::Semantic.
markdown_body_propertiesOption<MarkdownBodyProperties>RELATE_MARKDOWN_BODY_PROPERTIES, else the store's recorded setting, else bodyThe properties a Markdown store writes as note bodies; set on another codec, the open fails
logical_graph_size_limitOption<u64>RELATE_LOGICAL_GRAPH_SIZE_LIMIT, else unlimitedLimit: the live graph plus its indexes, in logical bytes; Some(0) is unlimited. A growing write over it fails with Error::Capacity.
expression_memory_limitOption<u64>RELATE_EXPRESSION_MEMORY_LIMIT, else 256 MiBLimit: one value an expression builds; Some(0) turns it off
concurrent_logical_workspace_limitOption<u64>RELATE_CONCURRENT_LOGICAL_WORKSPACE_LIMIT, else admission offLimit: a shared workspace pool; a positive value turns query admission on; Some(0) fails the open
max_traversal_depthOption<u32>RELATE_MAX_TRAVERSAL_DEPTH, else 500 (MAX_TRAVERSAL_DEPTH)Limit: the largest explicit hop bound a statement may ask for, 1 through 2000 (MAX_TRAVERSAL_DEPTH_CEILING)
safe_modeboolfalseRefuses a new named node without a label, and a MATCH read without LIMIT or a reducing aggregate; never switched on by detection
load_csv_dirOption<PathBuf>RELATE_LOAD_CSV_DIR, else deniedThe existing directory local LOAD CSV may read
load_csv_max_bytesOption<u64>8 MiBLimit: bytes read per CSV source, up to 64 MiB; does not grant file access by itself
follow_gapFollowGapPolicyReloadWhat a follower does when a checkpoint removes WAL records it has not applied
EnumVariants
OpenModeWritable (the default: takes the writer lease, appends and checkpoints); ReadOnly (loads once, refuses every write, never creates a store; a directory store opens beside its writer, a .rl store only while no writer holds it); Follow (read-only, then tails a directory store's WAL; refused for :memory: and .rl); Ephemeral (loads into memory and releases the source)
DurabilityModeFull (the default: the WAL is synced before each group commit is acknowledged); EverySecond (acknowledged after apply, synced about once a second, so a crash can lose about the last second); Snapshot (acknowledged after apply; a crash can lose every write since the last completed checkpoint). Parses from full, everysecond and snapshot.
FollowGapPolicyReload (the default: loads the snapshot and surviving WAL beside the live graph, then swaps); Yield (stops following and sets needs_reopen())
NamespaceNeo4j (the user graph, the only writable one); System (SHOW and administration commands); SystemOntologies (read only through the db.ontology.* procedures)

CloneOptions holds wal_dir (a directory source's WAL; refused for a .rl source), to_snapshot_format (transcode the copy to another codec; default keeps the source's) and markdown_body_properties.

Connection

One session on a Database. Connection is Send but not Sync; every method that runs a statement takes &mut self.

MethodContract
query(cypher), execute(cypher)Runs one statement with no parameters; execute is the same call
query_with_params(cypher, BTreeMap<String, Value>)Runs one statement with named parameters; a missing one fails before execution with Error::ParameterMissing
query_with_params_cancellable(cypher, params, CancelToken)The same, stoppable from another thread: a cancelled statement returns Error::Cancelled and the connection stays usable
begin()Starts an explicit transaction; one per connection, and a nested begin fails with semantic error: already in a transaction
commit()Publishes the transaction as one WAL commit; returns its bookmark relate:<n>, or None when it wrote nothing. After a failed statement in the transaction it fails with semantic error: transaction failed; rollback required.
rollback()Discards the transaction; with none open, semantic error: no transaction
in_transaction()Whether a transaction is open
explain_plan(cypher)The statement's plan as a PlanNode, without running it and without binding parameters
namespace(), set_namespace(&str)The session namespace; it changes only between transactions, and inside one the change fails with semantic error: TransactionError: Cannot change the namespace while a transaction is open.
set_principal(Option<&str>), principal()A display-only identity that dbms.showCurrentUser() reports; it grants nothing. Unset, the placeholder is relate.
pull_lookup(source, PullKind, remote_id), pull_bind(…)The identity map behind relate pull: the local id of a pulled remote element
assume_worker_stack_on_caller_thread()Runs bounded reads on the calling thread instead of the query worker; the caller guarantees a stack of QUERY_WORKER_STACK_BYTES
query_staged(…), commit_with_heartbeat(Heartbeat)The staged entry points

QueryResult

QueryResult.header is a ResultHeader, the metadata every statement announces; a staged run's ExecutionFailure carries the same struct. Its public fields are columns, column_types, query_type, namespace and elapsed; its phase timings and plan-cache outcome are read through the QueryResult methods.

Field or methodHolds
rowsVec<Vec<Value>>, each row in RETURN order
header.columnsThe column names
header.column_typesOne type name per column, from the first row: STRING, INTEGER, FLOAT, BOOLEAN, NODE, RELATIONSHIP, PATH, LIST, MAP, POINT, DATETIME, DATE, TIME, DURATION, VECTOR, BINARY or ANY; ANY for a first value that is null and for every column of an empty result. UUID is a reserved name that is never stamped: a UUID column reports STRING.
header.query_typeQueryType::Read, Write, ReadWrite or Schema, from the plan before execution; as_str() gives r, w, rw or s. EXPLAIN and PROFILE report the statement they wrap.
header.namespaceThe namespace the statement ran in: its USE target, else the session namespace
header.elapsed, elapsed_ms()The engine's wall-clock time for parse, plan and run, excluding row handling
parse_ms(), plan_ms(), execute_ms()Three disjoint parts of the elapsed time; their sum never exceeds it
lex_parse_ms(), rewrite_ms(), lower_ms()Three disjoint parts of parse_ms(): lexing and building the syntax tree, the rewrite pass, and validation with lowering; each 0.0 when a cached plan served the statement
result_generation_ms()The part of execute_ms() that builds the QueryResult; 0.0 under EXPLAIN
plan_cache()A PlanCacheOutcome: Miss, HitRawFastPath (the statement text matched a cached plan), HitTemplate (its parameterized form matched), ReplanGenerationMismatch (a cached plan, re-planned after the statistics changed) or Bypassed (the cache was not consulted); as_str() gives miss, hit-raw-fastpath, hit-template, replan-generation-mismatch or bypassed
statsQueryStats, each counter an i64: nodes_created, nodes_deleted, relationships_created, relationships_deleted, properties_set, properties_removed, labels_added, labels_removed, indexes_added, indexes_removed, constraints_added, constraints_removed, node_labels_added, node_labels_removed, properties_written
bookmarkAn auto-commit write's bookmark, relate:<n>; None for a read, an EXPLAIN, a write whose counters are all zero (it changed nothing), and any statement inside an explicit transaction
effectStatementEffect: whether a write ran (attempted()), changed something (applied()), or changed nothing (changed_nothing())
plan, plan_root()The plan tree after EXPLAIN or PROFILE; None on a plain run
notifications()The notifications derived with the plan; empty on a plain run
receiptThe peak logical workspace, when admission is on

Value

A parameter or a result cell. Value is Send, Sync and Clone; strings, lists, maps, vectors and byte arrays share their payload behind an Arc, so a clone never copies it.

VariantCypher typeColumn type
NullnullANY
Bool(bool)BOOLEANBOOLEAN
Int(i64)INTEGERINTEGER
Float(f64)FLOATFLOAT
String(Arc<str>)STRINGSTRING
List(Arc<Vec<Value>>)LISTLIST
Map(Arc<BTreeMap<String, Value>>)MAPMAP
Node(Arc<Node>)NODE: id, labels, propertiesNODE
Relationship(Arc<Relationship>)RELATIONSHIP: id, start, end, rel_type, propertiesRELATIONSHIP
Path(Arc<Path>)PATH: nodes, relsPATH
Temporal(Temporal::Date)DATEDATE
Temporal(Temporal::Time { time, offset }), Temporal(Temporal::LocalTime)ZONED TIME, LOCAL TIMETIME
Temporal(Temporal::DateTime { utc, offset, zone }), Temporal(Temporal::LocalDateTime)ZONED DATETIME, LOCAL DATETIMEDATETIME
Temporal(Temporal::Duration { months, days, nanos })DURATIONDURATION
Point(PointValue)POINT: srid, x, y, zPOINT
Vector { coord, values }VECTORVECTOR
Uuid(u128)A UUID; column_types reports it as STRINGSTRING
Bytes(Arc<[u8]>)A byte array; it enters only as a parameter, and storing it as a property fails with a type errorBINARY

Temporal::CivilDate and Temporal::CivilDateTime hold dates outside the range of the standard date types. node_element_id, rel_element_id, parse_node_element_id and parse_rel_element_id convert between numeric ids and element id The string elementId() returns for a node or relationship, such as 4:relate-neo4j:n0; it stays the same when the store is closed and opened again. Read more in the glossary, the strings elementId() returns.

Errors

relate::Error is an enum; its Display is the message every surface prints. error_info(&e) returns ErrorInfo { neo4j_code, gql_status, stage, retryable }, the one classification that the CLI, Python, the C ABI, Bolt, and HTTP all derive from. stage is an ErrorStage: Compile (rejected before any work), Runtime (found while producing rows) or Internal (not the statement's fault).

VariantDisplay beginsneo4j_codegql_statusstageretryable
Syntax(String)syntax error: Neo.ClientError.Statement.SyntaxError42N06Compilefalse
ProcedureNotFound { name }syntax error: ProcedureNotFound: Neo.ClientError.Procedure.ProcedureNotFound42N06Compilefalse
ParameterMissing(String)semantic error: ParameterMissing: Neo.ClientError.Statement.ParameterMissing42N02Compilefalse
DatabaseNotFound { name }semantic error: DatabaseNotFound: Graph not found: Neo.ClientError.Database.DatabaseNotFound42N00Compilefalse
ArgumentError(String)semantic error: Neo.ClientError.General.InvalidArguments42000Compilefalse
Semantic(String)semantic error: Neo.ClientError.Statement.SemanticError42000Runtimefalse
Execution(String)the messageNeo.ClientError.Statement.SemanticError42000Runtimefalse
UniquenessViolation { name }semantic error: ConstraintValidationFailed: `<name>` uniquenessNeo.ClientError.Schema.ConstraintValidationFailed42000Runtimefalse
Type(String), TypeError(String), InvalidArgumentType(String)type error: Neo.ClientError.Statement.TypeError22G03Runtimefalse
Arithmetic(DivisionByZero), Arithmetic(ModuloByZero)type error: / by zero, type error: % by zeroNeo.ClientError.Statement.ArithmeticError22G03Runtimefalse
Arithmetic(RoundingNecessary)ArithmeticError: rounding necessaryNeo.ClientError.Statement.ArithmeticError42000Runtimefalse
Cancelledquery cancelledNeo.ClientError.Transaction.TransactionTimedOut42000Runtimefalse
Conflictwrite-write conflictNeo.TransientError.Transaction.Outdated42000Runtimetrue
Capacity { used, limit, kind }capacity exceeded: (CapacityKind::Graph), or a sentence naming the limit (Expression, WalPayload)Neo.ClientError.General.TransactionOutOfMemoryError42000Runtimefalse
ResourceLimit { name, limit, retryable: true, .. }resource limit exceeded: Neo.TransientError.General.MemoryPoolOutOfMemoryError42000Runtimetrue
ResourceLimit { retryable: false, .. }resource limit exceeded: Neo.ClientError.General.TransactionOutOfMemoryError42000Runtimefalse
Storage(String)storage error: Neo.DatabaseError.General.UnknownError42000Internalfalse
Locked(String)storage locked: Neo.DatabaseError.General.UnknownError42000Internalfalse
Io(String)io error: Neo.DatabaseError.General.UnknownError42000Internalfalse
Internal(String)internal error: Neo.DatabaseError.General.UnknownError50N42Internalfalse

The gql_status shown for Syntax, Semantic and Execution is the default: a payload naming a more specific class carries that class's code, such as 42N18 for semantic error: WriteOnReadOnlyAccessDatabase: …. Error::WAL_PAYLOAD_CAP_BYTES is 64 MiB, the largest single commit record. ResourceLimit names are the constants Error::CONCURRENT_LOGICAL_WORKSPACE_LIMIT, Error::WRITER_DRAINING and Error::FOLLOW_GAP. A write-write conflict is never retried by the engine. The errors reference lists the messages with their causes and remedies.

Plans and notifications

TypeHolds
PlanNodeoperator, details, identifiers, children, estimated_rows, id, warnings, metrics under PROFILE, statement_echo (the wrapped statement without its EXPLAIN or PROFILE keyword), token_estimate (the plan's peak logical workspace, None unless admission is on), and pattern_engine (on a MATCH operator, the PatternEngine mode RELATE_PATTERN_ENGINE sets at open: Auto, Nfa or Walk; None elsewhere); to_value() gives the tree as a Value
ClauseMetricsOne operator's PROFILE figures: rows, db_hits, memory_bytes, expression_built_bytes, time_ns, reads, start, kernel (the KernelRung that served the clause's MATCH walk: Chain { hops }, HubStar, FrontierNfa or Walker; None without a MATCH walk), phases, batched (whether the clause ran as batch operators), zone_skips (batch filter evaluations skipped by chunk min/max metadata), frontier (the breadth-first frontier's counts of relationships visited, levels completed and endpoints accepted) and frontier_decline (why a frontier run fell back, when it did)
PlanWarningA typed warning on one operator, such as a Cartesian product, or a row count 10 or more times its estimate under PROFILE
PlanArtifactsA result's plan tree with the notifications derived from it
Notificationkind(), code() (Neo.ClientNotification.* for a kind with a Neo4j counterpart, Relate.Notification.* for an engine-own kind), gql_status(), severity(), category(), title(), description(), remedy(), operator_id(); NotificationKind, NotificationSeverity and NotificationCategory are its vocabularies

notification_to_wire_json, notifications_to_wire_json and notification_to_neo4j_json serialize notifications as the other surfaces send them. The notifications reference lists the codes.

Staged runs

Upstream documents these entry points for network transports, which report planning failures and execution failures at different points; relate's Bolt server is their in-tree user.

ItemContract
Connection::query_staged(cypher, params, CancelToken, Option<Heartbeat>)Err for a failure before execution (parse, planning, a missing parameter); Ok(Executed::Rows(QueryResult)) for a finished result; Ok(Executed::Failed(ExecutionFailure)) for a failure while executing, with the planned header and the error. Executed::into_result() gives the query shape.
Connection::commit_with_heartbeat(Heartbeat)commit(), ticking the heartbeat on the calling thread while the flush runs
Heartbeat::every(interval, tick)A callback run once per elapsed interval while a statement or commit runs on the query worker; a zero interval fails with semantic error: heartbeat interval must be non-zero

Other root exports

GroupNames
CancellationCancelToken (new(), cancel(), is_cancelled(); clones share one flag)
Graph valuesNode, Relationship, Path, PropertyMap, Temporal
Error partsErrorInfo, ErrorStage, ArithmeticFailure, CapacityKind, client_message, log_internal_original, INTERNAL_ERROR_INFO, INTERNAL_MESSAGE (internal error, the text the trust boundaries substitute for an internal error)
StorageSnapshotCodecKind, MarkdownBodyProperties, WalRecord, CdcSlot, cypher_to_value, value_to_cypher
LimitsMAX_TRAVERSAL_DEPTH (500), MAX_TRAVERSAL_DEPTH_CEILING (2000), MAX_VALUE_DEPTH, DEFAULT_CHECKPOINT_INTERVAL_SECS (300), QUERY_WORKER_STACK_BYTES, parse_memory_limit, parse_expression_memory_limit, parse_positive_memory_limit, require_positive_memory_limit, require_traversal_depth, traversal_depth_exceeded_message, value_depth_exceeded, next_depth
Settingsdurability_mode_from_setting, expression_limit_from_setting, workspace_limit_from_setting, reject_cypherlite_env (fails when a retired CYPHERLITE_* variable is set, naming its RELATE_* replacement)
Surface helpersexecute_wire, run_script_wire, query_result_to_wire, query_result_to_cypher_rows, query_stats_to_wire, plan_wire_json, timing_stamp_ms, params_from_json, params_from_value, params_from_map, binding_error_metadata: the shared conversions the other surfaces build their envelopes and parameters with
AdmissionExecutionReceipt, TokenEstimate, TokenOutcome, TokenPoolSnapshot
Executor factsQueryStats, StatementEffect, StoreReads, PhaseTimes, FrontierCounters, FrontierRunDecline, WalkStart, StartReason, KernelRung, PatternEngine, PullKind, Procedure, QueryType, PlanCacheOutcome
UUIDsuuid_hyphenated, uuid_parse

Limits

The limits come from the engine and are the same on every surface: a statement's text is at most 4194304 bytes (syntax error: query text of <n> bytes exceeds the maximum query size of 4194304 bytes), one value a statement builds is bounded by the expression memory cap, and a file-backed store has one writing open across every process. Limits and sizing lists each limit with its default and the setting that changes it.

Capabilities

FeatureRust
In-memory storeA store that lives only in the process.yesDatabase::open(":memory:")
Directory storeA store in a directory on disk.yesDatabase::open(path)
Single-file .rl storeA store in one .rl file.yesDatabase::open("graph.rl")
Read-only openAn open that loads the store once and refuses every write.yesOpenMode::ReadOnly
Explicit transactionsSeveral statements committed or rolled back together.yesbegin(), commit(), rollback()
Parameters$name values passed beside the statement.yesquery_with_params
Column types, counters and timingsMetadata returned with each result.yesQueryResult: header.column_types, header.query_type, stats, elapsed_ms() and its phase split, plan_cache()
NotificationsThe engine's query notifications (for example a Cartesian product), each with a remedy.yeswith the plan, on EXPLAIN and PROFILE
Arrow outputResults as Apache Arrow.yesthe relate-arrow crate
Change data captureReading committed changes from a slot.yesregister_cdc_slot, cdc_records_after, ack_cdc_slot
Full-text searchFull-text indexes and their queries.yesCREATE FULLTEXT INDEX and full-text SEARCH; the engine crate the other surfaces build on
LOAD CSV from local filesLocal LOAD CSV under a configured directory (denied unless one is set).yesOpenOptions.load_csv_dir
Load a store from a URLOpening a .rl store fetched over https.noDatabase::open takes :memory:, a path or file://
Agent modeThe CLI's agent defaults: the 100-row cap and the piped toon output.noA CLI setting

Each cell is yes, no, partial or unknown, with the call, flag or reason. Checked on 2026-11-09 against relate 0.1.2: runs of the CLI binary and relate serve (Bolt, HTTP and MCP), the WebAssembly build this site ships, and the Python, Node.js, C, Java, Go, Swift and Rust clients, and each surface's upstream reference. The C, Java, Go and Swift clients load the same C ABI library as the Node.js client.

Example

This program writes the team graph to an in-memory store, reads it back with a parameter, and classifies an error:

use std::collections::BTreeMap;

use relate::{error_info, Database, Error, Value};

const TEAM: &str = "
CREATE (ada:Person {name: 'Ada', role: 'engineer'}),
       (grace:Person {name: 'Grace', role: 'engineer'}),
       (noor:Person {name: 'Noor', role: 'maintainer'}),
       (relate:Project {name: 'relate', language: 'Rust'}),
       (tck:Project {name: 'opencypher-tck', language: 'Gherkin'}),
       (ada)-[:WORKS_ON {since: 2024}]->(relate),
       (grace)-[:WORKS_ON {since: 2023}]->(relate),
       (grace)-[:WORKS_ON {since: 2022}]->(tck),
       (noor)-[:MAINTAINS]->(relate),
       (ada)-[:KNOWS]->(grace)";

fn main() -> relate::Result<()> {
    let db = Database::open(":memory:")?;
    let mut conn = db.connect()?;
    conn.query(TEAM)?;

    let params = BTreeMap::from([("name".to_string(), Value::String("Grace".into()))]);
    let result = conn.query_with_params(
        "MATCH (p:Person {name: $name})-[w:WORKS_ON]->(proj:Project) \
         RETURN proj.name AS project, w.since AS since ORDER BY since",
        params,
    )?;
    println!("{:?} {:?} {}", result.header.columns, result.header.column_types,
        result.header.query_type.as_str());
    for row in &result.rows {
        println!("{row:?}");
    }

    let err = conn.query("RETURN 1 / 0 AS x").unwrap_err();
    let info = error_info(&err);
    println!("{err:?}: {err}");
    println!("{} {} {:?} {}", info.neo4j_code, info.gql_status, info.stage, info.retryable);
    println!("conflict retryable: {}", error_info(&Error::Conflict).retryable);
    Ok(())
}
["project", "since"] ["STRING", "INTEGER"] r
[String("opencypher-tck"), Int(2022)]
[String("relate"), Int(2023)]
Arithmetic(DivisionByZero): type error: / by zero
Neo.ClientError.Statement.ArithmeticError 22G03 Runtime false
conflict retryable: true

See also