Skip to main content

Crate wasm_dbms

Crate wasm_dbms 

Source
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
CrateRole
wasm-dbms-apiShared types, traits, validators, sanitizers, error variants
wasm-dbms-memoryMemoryProvider abstraction, page management, schema/ACL/table storage
wasm-dbms-macrosEncode, Table, CustomDataType, DatabaseSchema derive macros
wasm-dbmsDBMS 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 in RefCell so a single shared reference is enough to drive operations.
  • WasmDbmsDatabase — short-lived session bound to a DbmsContext. 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 by Query::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 during delete to honour Restrict / Cascade semantics.

§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 (via wasi-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§

DbmsContext
Owns all mutable DBMS state behind interior-mutable wrappers.
WasmDbmsDatabase
The main DBMS database struct, generic over MemoryProvider and AccessControl.