Expand description
§wasm-dbms
Runtime-agnostic DBMS engine for WASM environments.
wasm-dbms is the core engine of the wasm-dbms framework. It turns a
schema described with Rust structs into a fully featured embedded
relational database that can be hosted on any WASM runtime
(Wasmtime, Wasmer, WasmEdge, Internet Computer, …).
Schemas are declared with the Table and DatabaseSchema derive
macros from wasm-dbms-macros and consumed through this crate via
the DbmsContext / WasmDbmsDatabase pair.
§Crate architecture
wasm-dbms-macros <── wasm-dbms-api <── wasm-dbms-memory <── wasm-dbms| Crate | Role |
|---|---|
wasm-dbms-api | Shared types, traits, validators, sanitizers, error variants |
wasm-dbms-memory | MemoryProvider abstraction, page management, schema/ACL/table storage |
wasm-dbms-macros | Encode, Table, CustomDataType, DatabaseSchema derive macros |
wasm-dbms | DBMS engine: CRUD, joins, aggregations, integrity, transactions |
Use this crate together with wasm-dbms-api (types) and
wasm-dbms-macros (derives). For IC canisters, prefer the
ic-dbms-canister adapter, which is built on top of this crate.
§Layout
Each engine concern lives in its own module:
DbmsContext— owns all database state (schema registry, ACL, memory manager, active transactions). Wraps mutable state inRefCellso a single shared reference is enough to drive operations.WasmDbmsDatabase— short-lived session bound to aDbmsContext. Provides the typed CRUD surface (insert,select,update,delete,aggregate) and the transaction lifecycle (commit/rollback).schema::DatabaseSchema— dispatch trait generated by the#[derive(DatabaseSchema)]macro; routes name-based operations (“users”, “posts”, …) to the matching typed table.join::JoinEngine— nested-loop cross-table join executor used byQuery::join.integrity— insert and update validators (primary key, uniqueness, foreign key, nullability, custom validators).transaction— overlay-based MVCC-like read-your-writes layer plus journaling for commit/rollback.referenced_tables— foreign-key reverse lookups used duringdeleteto honourRestrict/Cascadesemantics.
§Quick start
Add the crate to Cargo.toml:
[dependencies]
wasm-dbms = "0.9"
wasm-dbms-api = "0.9"§Define tables
use wasm_dbms_api::prelude::*;
#[derive(Debug, Table, Clone, PartialEq, Eq)]
#[table = "users"]
pub struct User {
#[primary_key]
pub id: Uint32,
#[sanitizer(TrimSanitizer)]
#[validate(MaxStrlenValidator(100))]
pub name: Text,
#[validate(EmailValidator)]
pub email: Text,
}
#[derive(Debug, Table, Clone, PartialEq, Eq)]
#[table = "posts"]
pub struct Post {
#[primary_key]
pub id: Uint32,
pub title: Text,
pub content: Text,
#[foreign_key(entity = "User", table = "users", column = "id")]
pub author_id: Uint32,
}§Wire the schema
use wasm_dbms::prelude::*;
#[derive(DatabaseSchema)]
#[tables(User = "users", Post = "posts")]
pub struct MySchema;§Open a database session
use wasm_dbms::prelude::*;
use wasm_dbms_api::prelude::*;
use wasm_dbms_memory::HeapMemoryProvider;
let ctx = DbmsContext::new(HeapMemoryProvider::default());
MySchema::register_tables(&ctx)?;
let db = WasmDbmsDatabase::oneshot(&ctx, MySchema);
db.insert::<User>(UserInsertRequest {
id: 1.into(),
name: "Alice".into(),
email: "alice@example.com".into(),
})?;
let query = Query::builder()
.filter(Filter::eq("name", Value::Text("Alice".into())))
.build();
let users = db.select::<User>(query)?;§Transactions
let tx_id = ctx.begin_transaction(caller_id);
let mut db = WasmDbmsDatabase::from_transaction(&ctx, MySchema, tx_id);
db.insert::<User>(insert_req)?;
db.update::<User>(update_req)?;
db.commit()?; // or db.rollback()?;Transactions are per-caller. The overlay records uncommitted writes
so reads inside the session observe read-your-writes semantics
without leaking changes to other sessions until commit.
§Memory backends
wasm-dbms is parametric on the MemoryProvider from
wasm_dbms_memory. The framework ships:
HeapMemoryProvider— in-memory backend for tests and embedded use cases.WasiMemoryProvider(viawasi-dbms-memory) — file-backed provider for WASI runtimes.- IC stable memory provider (via
ic-dbms-canister) — production backend for Internet Computer canisters.
Custom backends just need to implement MemoryProvider.
§Access control
DbmsContext is generic over an AccessControl provider.
Use AccessControlList for identity-based per-table permissions
or NoAccessControl for runtimes that do not need it. The IC
adapter wires AccessControlList to canister principals.
§Threading
DbmsContext is !Send and !Sync. WASM runtimes are
single-threaded, so the engine relies on RefCell rather than
synchronization primitives. Embedders that need multi-threaded
access must wrap the context in their own synchronization layer.
Modules§
- integrity
- Integrity validators for insert and update operations.
- join
- Join execution engine for cross-table queries.
- prelude
- Prelude re-exports for convenient use.
- referenced_
tables - Foreign key reference tracking.
- schema
- transaction
- Transaction management for the DBMS engine.
Structs§
- Dbms
Context - Owns all mutable DBMS state behind interior-mutable wrappers.
- Wasm
Dbms Database - The main DBMS database struct, generic over
MemoryProviderandAccessControl.