An embedded SQL database written in Rust. Single-writer, page-based storage with a B-tree primary index, write-ahead log for crash safety, and an interactive REPL.
cargo run --releaseVelociDB v0.1.0
Database: veloci.db
Type '.help' for help, '.exit' to quit. Statements end with ';'.
velocidb> CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER);
OK
velocidb> INSERT INTO users VALUES (1, 'Alice', 30);
OK
velocidb> SELECT * FROM users WHERE age > 25 ORDER BY name LIMIT 10;
id | name | age
-----------+-----------+-----------
1 | Alice | 30
1 row(s) returned
velocidb> .schema users
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER);
REPL niceties: arrow-key history, persistent history file
(~/.velocidb_history, or $VELOCIDB_HISTORY), multi-line statements
terminated by ;, and .help, .tables, .schema [name], .exit.
use velocidb::Database;
fn main() -> anyhow::Result<()> {
let db = Database::open("my_database.db")?;
db.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")?;
db.execute("INSERT INTO users VALUES (1, 'Alice')")?;
let results = db.query("SELECT * FROM users ORDER BY id")?;
println!("Found {} users", results.rows.len());
Ok(())
}Storage and durability
- 4 KB page-based storage on a single data file.
- Write-ahead log (
<db>-wal) with CRC32-checked records. Each write statement runs as one atomic group: the WAL is fsynced on commit, then the modified pages are applied to the data file, fsynced, and the WAL truncated. - Crash recovery on open: committed groups in the WAL are replayed; partial / torn / uncommitted records are discarded.
- DashMap-backed read cache with bounded capacity.
Indexing
- B-tree primary key index with full split + merge + redistribute paths for both leaf and internal nodes (proptest covers random insert/delete sequences).
SQL surface
CREATE TABLE(INTEGER / REAL / TEXT / BLOB columns;PRIMARY KEY,NOT NULL,UNIQUEconstraints)DROP TABLEINSERT INTO ... VALUES (...)with optional explicit column listSELECT [* | cols | COUNT(*)] FROM t [WHERE ...] [ORDER BY col [ASC|DESC]] [LIMIT n]UPDATE t SET col = val [, ...] [WHERE ...]DELETE FROM t [WHERE ...]WHEREsupports=,!=,<>,>,<,>=,<=,LIKE, withANDBEGIN/COMMIT/ROLLBACK(see limitations below)
Concurrency
- Writers serialized at the
Databaselevel so the pager only ever has one active WAL group. Readers run concurrently with each other. - Lock-manager-based per-table shared/exclusive locking for in-flight transactions.
- Single-writer. All write statements take a global writer mutex. Reads can be concurrent with each other but a single in-flight write blocks other writes for its duration.
- Multi-statement transaction rollback is incomplete.
BEGINandCOMMITrelease/acquire locks correctly, butROLLBACKdoes not undo storage mutations made by earlier statements in the transaction. (Each statement is its own WAL group; a future change can fold an explicit transaction into a single WAL group.) - No
JOIN,GROUP BY, sub-queries, no indexes other than the primary key, noALTER TABLE. - Single primary key column. Composite primary keys are not supported.
- No async or networked access. The library is embedded only.
The crate exports several modules that explore advanced storage and concurrency techniques. They are not used by the SQL engine today and are exported only so the experimentation is visible:
mvcc— Multi-version concurrency controlasync_io— Tokio /io_uringpage I/Olockfree— Lock-free page cache and queuessimd— Vectorized filter / aggregation kernelsbtree_optimized— Cache-conscious B-tree node layoutcrdt— CRDT synchronization primitivescloud_vfs— S3 / Azure / GCS-backed VFShybrid_storage— Row/columnar hybrid table layoutpmem— Persistent-memory / DAX VFS
git clone https://github.com/niklabh/velocidb.git
cd velocidb
cargo build --releaseMIT — see LICENSE.