Velr
Velr is an embedded property-graph database from Velr.ai, written in Rust, built on top of SQLite3 (persisting to a standard SQLite database file) and queried using the openCypher language.
This crate provides the Rust binding for Velr. It links against a bundled native runtime with a C ABI, implemented in Rust.
For the main Velr public entry point, see velr-ai/velr.
For the Velr website, see velr.ai.
Community
- Community and questions: GitHub Discussions
- Bug reports and feature requests: GitHub Issues
- Rust examples: velr-rust-examples
We’d love to have you join the Velr community.
Release status
This release is alpha.
- The API and query support are still evolving.
- openCypher coverage is already substantial, but some features are still missing.
- During the
0.2.xseries, we do not guarantee database migration or on-disk database compatibility between releases. - Velr 0.2.14 includes a breaking on-disk storage change; existing databases from earlier releases must be recreated by re-importing the source data.
- Starting with the
0.3.xseries, we intend to guarantee internal database compatibility within the branch.
Schema version 5 compatibility
This release's current on-disk schema is version 5. Supported older databases
can be opened with Velr::open or Velr::open_readonly without changing the
file. Reads continue to work on those databases, but writes (CREATE, MERGE,
SET, DELETE, DETACH DELETE, and other mutating queries) are only available
after migrating to schema version 5. This is intentional: migration is an
explicit maintenance operation, not a side effect of opening a database.
Velr is already usable for real workflows and representative use cases, but rough edges remain and the API is not yet stable.
Velr 1.0 is focused on strong openCypher compatibility.
Vector search, time-series, and federation are planned as post-1.0 capabilities.
Installation
Add to Cargo.toml:
[]
= "0.2"
Enable Arrow IPC support (binding Arrow arrays + exporting result tables as Arrow IPC):
[]
= { = "0.2", = ["arrow-ipc"] }
Quick start
use ;
Opening an existing database read-only
Use Velr::open_readonly(path) for viewers, agents, and other read paths that
should not initialize or migrate the database:
use Velr;
open_readonly requires an existing file-backed database at a supported Velr
schema version. It does not create files, run schema DDL, or migrate older
databases. Older supported databases, such as schema version 3 or 4 databases
opened by a schema version 5 runtime, remain available for reads. Writes and
features that require schema version 5 fail with a normal query error until the
database is explicitly migrated.
Schema migration
Velr does not migrate supported older databases automatically on open. Use the
driver migration API, or run MIGRATE DATABASE, from maintenance code when you
intend to update the on-disk schema. See the release-status note above for the
schema version 5 read/write compatibility behavior.
use ;
The equivalent Cypher command is useful for scripts and tools that already work through query execution:
let db = open?;
let mut report = db.exec_one?;
println!;
Introspection
Use SHOW CURRENT GRAPH SHAPE to inspect the observed schema of the graph. It
reports the shape present in stored data: node labels, relationship types,
properties, observed value types, and counts. It is an observed shape surface,
not a declared GQL graph type.
SHOW CURRENT GRAPH SHAPE is available on schema version 5 databases. Older
supported databases can still be opened for reads, but must be migrated
explicitly before this command is valid. Schema version 5 maintains this
inventory through the write planner instead of persistent graph-shape triggers.
The default projection returns element_kind, element_name, property_name,
observed_type, owner_count, present_count, and missing_count.
YIELD * exposes the full row shape, including surface, source_label,
target_label, required, storage_class, and tag.
let db = open?;
let mut shape = db.exec_one?;
shape.for_each_row?;
Use YIELD to compose the command with WHERE and RETURN. Plain
SHOW CURRENT GRAPH SHAPE returns the default projection; YIELD * exposes the
full current row shape.
Query language support
Velr supports most of openCypher, but some features are not yet implemented.
Notable current limitations:
- Driver-level query parameters (for example
$name) - The query planner does not yet use indexes in all cases where expected.
Streaming multiple result tables
A single exec() can yield multiple result tables (e.g. multiple statements):
let db = open?;
let mut stream = db.exec?;
while let Some = stream.next_table?
Bounded result previews
Use QueryOptions::max_result_rows when a host needs projected column names and
a small row sample without rewriting the Cypher text:
use ;
max_result_rows = 0 preserves the returned column metadata and opens row
cursors at EOF. The cap is enforced by Velr during result emission, not by
appending or injecting Cypher LIMIT, and applies independently to each result
table produced by exec_with_options. Existing Cypher LIMIT clauses still
apply, so a query with LIMIT 3 and max_result_rows = 5 emits at most three
rows, while LIMIT 10 with max_result_rows = 5 emits at most five rows. It is
not a timeout or cancellation
mechanism; hosts that need read-only validation or execution deadlines should
keep those checks separate.
Query parameter binding
Use params!, QueryParams, or QueryOptions::with_param to bind openCypher parameters
out of band. Query text uses $name; API parameter names omit the leading $.
Values are passed as Cypher values, not interpolated into query text, so a Rust
String is always a Cypher string value.
use ;
Supported parameter values are null, booleans, signed 64-bit integers, finite
floats, strings, lists, and maps. Lists and maps can be supplied as
QueryValue::List / QueryValue::Map, Rust Vecs, BTreeMap<String, _>,
HashMap<String, _>, or serde_json::Value.
Use string-literal keys in params! for parameter names that are not Rust
identifiers, such as $1: velr::params! { name: "Alice", "1" => 42_i64 }?.
Transactions and savepoints
Velr supports transactions together with two kinds of savepoints:
- Scoped savepoints via
savepoint(), which return a guard - Named savepoints via
savepoint_named(name), which remain active in the transaction until released or the transaction ends
Calling rollback_to(name) rolls back to the named savepoint, discards any newer named savepoints, and keeps the target savepoint active.
Scoped savepoint
let db = open?;
let tx = db.begin_tx?;
tx.run?;
tx.commit?;
Named savepoints
let db = open?;
let tx = db.begin_tx?;
tx.savepoint_named?;
tx.run?;
tx.savepoint_named?;
tx.run?;
tx.rollback_to?;
tx.run?;
tx.release_savepoint?;
tx.commit?;
release_savepoint(name) currently releases the most recent active named savepoint.
Dropping an active transaction without commit() will roll it back automatically.
Explain plans
Velr can produce an explain trace for a query, which is useful when you want to inspect how a openCypher query is planned and translated internally.
Use Velr::explain to build a trace without executing the query:
use Velr;
The returned ExplainTrace can be inspected programmatically or rendered as a compact string for logging, debugging, tests, or documentation.
Arrow IPC (optional)
With features = ["arrow-ipc"] you can:
- Bind Arrow arrays as a logical table (
bind_arrow,bind_arrow_chunks) - Export a result table as an Arrow IPC file (
to_arrow_ipc_file())
Supported functions
Velr currently supports these openCypher functions and constructors:
Graph and path
id()type()labels()keys()properties()length()nodes()relationships()
Lists and predicates
size()head()last()tail()reverse()range()all()any()none()single()
Strings and conversion
coalesce()toInteger()toString()toLower()trim()substring()split()
Numeric
abs()ceil()rand()sign()sqrt()
Temporal
date()time()localtime()datetime()localdatetime()duration()datetime.fromepoch()datetime.fromepochmillis()date.realtime(),date.transaction(),date.statement()time.realtime(),time.transaction(),time.statement()localtime.realtime(),localtime.transaction(),localtime.statement()datetime.realtime(),datetime.transaction(),datetime.statement()localdatetime.realtime(),localdatetime.transaction(),localdatetime.statement()
Aggregates
count()sum()avg()min()max()collect()percentileDisc()percentileCont()
Platform support
This crate links against a bundled native runtime. Cargo selects one platform-specific
velr-runtime-* crate for the current build target, so user installation stays:
[]
= "0.2"
Currently bundled targets:
- macOS universal (arm64 + x86_64)
- Linux x86_64
- Linux aarch64
- Windows x86_64
Licensing
- The Rust binding source code in this package is licensed under MIT.
- The bundled native runtime binaries may be used and freely redistributed in unmodified form under the terms of
LICENSE.runtime.
See LICENSE and LICENSE.runtime for the full license texts.