Skip to main content

wasm_dbms/
lib.rs

1// Rust guideline compliant 2026-04-28
2// X-WHERE-CLAUSE, M-CANONICAL-DOCS
3
4#![crate_name = "wasm_dbms"]
5#![crate_type = "lib"]
6#![cfg_attr(docsrs, feature(doc_cfg))]
7#![deny(clippy::print_stdout)]
8#![deny(clippy::print_stderr)]
9
10//! # wasm-dbms
11//!
12//! Runtime-agnostic DBMS engine for WASM environments.
13//!
14//! `wasm-dbms` is the core engine of the [wasm-dbms framework]. It turns a
15//! schema described with Rust structs into a fully featured embedded
16//! relational database that can be hosted on any WASM runtime
17//! (Wasmtime, Wasmer, WasmEdge, Internet Computer, ...).
18//!
19//! Schemas are declared with the `Table` and `DatabaseSchema` derive
20//! macros from [`wasm-dbms-macros`] and consumed through this crate via
21//! the [`DbmsContext`] / [`WasmDbmsDatabase`] pair.
22//!
23//! [`wasm-dbms-macros`]: https://crates.io/crates/wasm-dbms-macros
24//!
25//! [wasm-dbms framework]: https://wasm-dbms.cc
26//!
27//! ## Crate architecture
28//!
29//! ```text
30//! wasm-dbms-macros <── wasm-dbms-api <── wasm-dbms-memory <── wasm-dbms
31//! ```
32//!
33//! | Crate              | Role                                                                    |
34//! |--------------------|-------------------------------------------------------------------------|
35//! | `wasm-dbms-api`    | Shared types, traits, validators, sanitizers, error variants            |
36//! | `wasm-dbms-memory` | `MemoryProvider` abstraction, page management, schema/table storage     |
37//! | `wasm-dbms-macros` | `Encode`, `Table`, `CustomDataType`, `DatabaseSchema` derive macros     |
38//! | `wasm-dbms`        | DBMS engine: CRUD, joins, aggregations, integrity, transactions         |
39//!
40//! Use this crate together with `wasm-dbms-api` (types) and
41//! `wasm-dbms-macros` (derives). For IC canisters, prefer the
42//! `ic-dbms-canister` adapter, which is built on top of this crate.
43//!
44//! ## Feature flags
45//!
46//! | name  | description                                                                         | default |
47//! |-------|-------------------------------------------------------------------------------------|---------|
48//! | `sql` | Enables the `sql` feature of `wasm-dbms-api`, required by the `wasm-dbms-sql` crate. |         |
49//!
50//! ## Layout
51//!
52//! Each engine concern lives in its own module:
53//!
54//! - [`DbmsContext`] — owns all database state (schema registry, memory
55//!   manager, active transactions). Wraps mutable state in
56//!   `RefCell` so a single shared reference is enough to drive
57//!   operations.
58//! - [`WasmDbmsDatabase`] — short-lived session bound to a
59//!   [`DbmsContext`]. Provides the typed CRUD surface
60//!   (`insert`, `select`, `update`, `delete`, `aggregate`) and the
61//!   transaction lifecycle (`commit` / `rollback`).
62//! - [`schema::DatabaseSchema`] — dispatch trait generated by the
63//!   `#[derive(DatabaseSchema)]` macro; routes name-based operations
64//!   ("users", "posts", ...) to the matching typed table.
65//! - [`join::JoinEngine`] — nested-loop cross-table join executor used
66//!   by `Query::join`.
67//! - [`integrity`] — insert and update validators (primary key,
68//!   uniqueness, foreign key, nullability, custom validators).
69//! - [`transaction`] — overlay-based MVCC-like read-your-writes layer
70//!   plus journaling for commit/rollback.
71//! - [`referenced_tables`] — foreign-key reverse lookups used during
72//!   `delete` to honour `Restrict` / `Cascade` semantics.
73//!
74//! ## Quick start
75//!
76//! Add the crate to `Cargo.toml`:
77//!
78//! ```toml
79//! [dependencies]
80//! wasm-dbms = "0.9"
81//! wasm-dbms-api = "0.9"
82//! ```
83//!
84//! ### Define tables
85//!
86//! ```rust,ignore
87//! use wasm_dbms_api::prelude::*;
88//!
89//! #[derive(Debug, Table, Clone, PartialEq, Eq)]
90//! #[table = "users"]
91//! pub struct User {
92//!     #[primary_key]
93//!     pub id: Uint32,
94//!     #[sanitizer(TrimSanitizer)]
95//!     #[validate(MaxStrlenValidator(100))]
96//!     pub name: Text,
97//!     #[validate(EmailValidator)]
98//!     pub email: Text,
99//! }
100//!
101//! #[derive(Debug, Table, Clone, PartialEq, Eq)]
102//! #[table = "posts"]
103//! pub struct Post {
104//!     #[primary_key]
105//!     pub id: Uint32,
106//!     pub title: Text,
107//!     pub content: Text,
108//!     #[foreign_key(entity = "User", table = "users", column = "id")]
109//!     pub author_id: Uint32,
110//! }
111//! ```
112//!
113//! ### Wire the schema
114//!
115//! ```rust,ignore
116//! use wasm_dbms::prelude::*;
117//!
118//! #[derive(DatabaseSchema)]
119//! #[tables(User = "users", Post = "posts")]
120//! pub struct MySchema;
121//! ```
122//!
123//! ### Open a database session
124//!
125//! ```rust,ignore
126//! use wasm_dbms::prelude::*;
127//! use wasm_dbms_api::prelude::*;
128//! use wasm_dbms_memory::HeapMemoryProvider;
129//!
130//! let ctx = DbmsContext::new(HeapMemoryProvider::default());
131//! MySchema::register_tables(&ctx)?;
132//!
133//! let db = WasmDbmsDatabase::oneshot(&ctx, MySchema);
134//!
135//! db.insert::<User>(UserInsertRequest {
136//!     id: 1.into(),
137//!     name: "Alice".into(),
138//!     email: "alice@example.com".into(),
139//! })?;
140//!
141//! let query = Query::builder()
142//!     .filter(Filter::eq("name", Value::Text("Alice".into())))
143//!     .build();
144//! let users = db.select::<User>(query)?;
145//! ```
146//!
147//! ### Transactions
148//!
149//! ```rust,ignore
150//! let tx_id = ctx.begin_transaction();
151//! let mut db = WasmDbmsDatabase::from_transaction(&ctx, MySchema, tx_id);
152//!
153//! db.insert::<User>(insert_req)?;
154//! db.update::<User>(update_req)?;
155//!
156//! db.commit()?;        // or db.rollback()?;
157//! ```
158//!
159//! A transaction is identified by its ID; any code that holds the ID can use
160//! it. The overlay records uncommitted writes so reads inside the session
161//! observe read-your-writes semantics without leaking changes to other
162//! sessions until `commit`.
163//!
164//! ## Memory backends
165//!
166//! `wasm-dbms` is parametric on the [`MemoryProvider`] from
167//! [`wasm_dbms_memory`]. The framework ships:
168//!
169//! - `HeapMemoryProvider` — in-memory backend for tests and embedded
170//!   use cases.
171//! - `WasiMemoryProvider` (via `wasi-dbms-memory`) — file-backed
172//!   provider for WASI runtimes.
173//! - IC stable memory provider (via `ic-dbms-canister`) — production
174//!   backend for Internet Computer canisters.
175//!
176//! Custom backends just need to implement `MemoryProvider`.
177//!
178//! [`MemoryProvider`]: wasm_dbms_memory::MemoryProvider
179//!
180//! ## Threading
181//!
182//! [`DbmsContext`] is `!Send` and `!Sync`. WASM runtimes are
183//! single-threaded, so the engine relies on `RefCell` rather than
184//! synchronization primitives. Embedders that need multi-threaded
185//! access must wrap the context in their own synchronization layer.
186
187#![doc(html_playground_url = "https://play.rust-lang.org")]
188#![doc(
189    html_favicon_url = "https://raw.githubusercontent.com/veeso/wasm-dbms/main/assets/images/cargo/logo-128.png"
190)]
191#![doc(
192    html_logo_url = "https://raw.githubusercontent.com/veeso/wasm-dbms/main/assets/images/cargo/logo-512.png"
193)]
194
195extern crate self as wasm_dbms;
196
197mod context;
198mod database;
199pub mod integrity;
200pub mod join;
201pub mod referenced_tables;
202pub mod schema;
203pub mod transaction;
204
205pub use self::context::{ContextId, DbmsContext};
206pub use self::database::WasmDbmsDatabase;
207
208/// Prelude re-exports for convenient use.
209///
210/// Bring the most common engine items into scope with a single import:
211///
212/// ```rust,ignore
213/// use wasm_dbms::prelude::*;
214/// ```
215pub mod prelude {
216    pub use super::context::{ContextId, DbmsContext};
217    pub use super::database::WasmDbmsDatabase;
218    pub use super::integrity::{InsertIntegrityValidator, UpdateIntegrityValidator};
219    pub use super::join::JoinEngine;
220    pub use super::referenced_tables::get_referenced_tables;
221    pub use super::schema::DatabaseSchema;
222    pub use super::transaction::DatabaseOverlay;
223    pub use super::transaction::session::TransactionSession;
224}