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/ACL/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//! ## Layout
45//!
46//! Each engine concern lives in its own module:
47//!
48//! - [`DbmsContext`] — owns all database state (schema registry, ACL,
49//!   memory manager, active transactions). Wraps mutable state in
50//!   `RefCell` so a single shared reference is enough to drive
51//!   operations.
52//! - [`WasmDbmsDatabase`] — short-lived session bound to a
53//!   [`DbmsContext`]. Provides the typed CRUD surface
54//!   (`insert`, `select`, `update`, `delete`, `aggregate`) and the
55//!   transaction lifecycle (`commit` / `rollback`).
56//! - [`schema::DatabaseSchema`] — dispatch trait generated by the
57//!   `#[derive(DatabaseSchema)]` macro; routes name-based operations
58//!   ("users", "posts", ...) to the matching typed table.
59//! - [`join::JoinEngine`] — nested-loop cross-table join executor used
60//!   by `Query::join`.
61//! - [`integrity`] — insert and update validators (primary key,
62//!   uniqueness, foreign key, nullability, custom validators).
63//! - [`transaction`] — overlay-based MVCC-like read-your-writes layer
64//!   plus journaling for commit/rollback.
65//! - [`referenced_tables`] — foreign-key reverse lookups used during
66//!   `delete` to honour `Restrict` / `Cascade` semantics.
67//!
68//! ## Quick start
69//!
70//! Add the crate to `Cargo.toml`:
71//!
72//! ```toml
73//! [dependencies]
74//! wasm-dbms = "0.9"
75//! wasm-dbms-api = "0.9"
76//! ```
77//!
78//! ### Define tables
79//!
80//! ```rust,ignore
81//! use wasm_dbms_api::prelude::*;
82//!
83//! #[derive(Debug, Table, Clone, PartialEq, Eq)]
84//! #[table = "users"]
85//! pub struct User {
86//!     #[primary_key]
87//!     pub id: Uint32,
88//!     #[sanitizer(TrimSanitizer)]
89//!     #[validate(MaxStrlenValidator(100))]
90//!     pub name: Text,
91//!     #[validate(EmailValidator)]
92//!     pub email: Text,
93//! }
94//!
95//! #[derive(Debug, Table, Clone, PartialEq, Eq)]
96//! #[table = "posts"]
97//! pub struct Post {
98//!     #[primary_key]
99//!     pub id: Uint32,
100//!     pub title: Text,
101//!     pub content: Text,
102//!     #[foreign_key(entity = "User", table = "users", column = "id")]
103//!     pub author_id: Uint32,
104//! }
105//! ```
106//!
107//! ### Wire the schema
108//!
109//! ```rust,ignore
110//! use wasm_dbms::prelude::*;
111//!
112//! #[derive(DatabaseSchema)]
113//! #[tables(User = "users", Post = "posts")]
114//! pub struct MySchema;
115//! ```
116//!
117//! ### Open a database session
118//!
119//! ```rust,ignore
120//! use wasm_dbms::prelude::*;
121//! use wasm_dbms_api::prelude::*;
122//! use wasm_dbms_memory::HeapMemoryProvider;
123//!
124//! let ctx = DbmsContext::new(HeapMemoryProvider::default());
125//! MySchema::register_tables(&ctx)?;
126//!
127//! let db = WasmDbmsDatabase::oneshot(&ctx, MySchema);
128//!
129//! db.insert::<User>(UserInsertRequest {
130//!     id: 1.into(),
131//!     name: "Alice".into(),
132//!     email: "alice@example.com".into(),
133//! })?;
134//!
135//! let query = Query::builder()
136//!     .filter(Filter::eq("name", Value::Text("Alice".into())))
137//!     .build();
138//! let users = db.select::<User>(query)?;
139//! ```
140//!
141//! ### Transactions
142//!
143//! ```rust,ignore
144//! let tx_id = ctx.begin_transaction(caller_id);
145//! let mut db = WasmDbmsDatabase::from_transaction(&ctx, MySchema, tx_id);
146//!
147//! db.insert::<User>(insert_req)?;
148//! db.update::<User>(update_req)?;
149//!
150//! db.commit()?;        // or db.rollback()?;
151//! ```
152//!
153//! Transactions are per-caller. The overlay records uncommitted writes
154//! so reads inside the session observe read-your-writes semantics
155//! without leaking changes to other sessions until `commit`.
156//!
157//! ## Memory backends
158//!
159//! `wasm-dbms` is parametric on the [`MemoryProvider`] from
160//! [`wasm_dbms_memory`]. The framework ships:
161//!
162//! - `HeapMemoryProvider` — in-memory backend for tests and embedded
163//!   use cases.
164//! - `WasiMemoryProvider` (via `wasi-dbms-memory`) — file-backed
165//!   provider for WASI runtimes.
166//! - IC stable memory provider (via `ic-dbms-canister`) — production
167//!   backend for Internet Computer canisters.
168//!
169//! Custom backends just need to implement `MemoryProvider`.
170//!
171//! ## Access control
172//!
173//! [`DbmsContext`] is generic over an [`AccessControl`] provider.
174//! Use [`AccessControlList`] for identity-based per-table permissions
175//! or [`NoAccessControl`] for runtimes that do not need it. The IC
176//! adapter wires `AccessControlList` to canister principals.
177//!
178//! [`MemoryProvider`]: wasm_dbms_memory::MemoryProvider
179//! [`AccessControl`]: wasm_dbms_memory::AccessControl
180//! [`AccessControlList`]: wasm_dbms_memory::AccessControlList
181//! [`NoAccessControl`]: wasm_dbms_memory::NoAccessControl
182//!
183//! ## Threading
184//!
185//! [`DbmsContext`] is `!Send` and `!Sync`. WASM runtimes are
186//! single-threaded, so the engine relies on `RefCell` rather than
187//! synchronization primitives. Embedders that need multi-threaded
188//! access must wrap the context in their own synchronization layer.
189
190#![doc(html_playground_url = "https://play.rust-lang.org")]
191#![doc(
192    html_favicon_url = "https://raw.githubusercontent.com/veeso/wasm-dbms/main/assets/images/cargo/logo-128.png"
193)]
194#![doc(
195    html_logo_url = "https://raw.githubusercontent.com/veeso/wasm-dbms/main/assets/images/cargo/logo-512.png"
196)]
197
198extern crate self as wasm_dbms;
199
200mod context;
201mod database;
202pub mod integrity;
203pub mod join;
204pub mod referenced_tables;
205pub mod schema;
206pub mod transaction;
207
208pub use self::context::DbmsContext;
209pub use self::database::WasmDbmsDatabase;
210
211/// Prelude re-exports for convenient use.
212///
213/// Bring the most common engine items into scope with a single import:
214///
215/// ```rust,ignore
216/// use wasm_dbms::prelude::*;
217/// ```
218pub mod prelude {
219    pub use super::context::DbmsContext;
220    pub use super::database::WasmDbmsDatabase;
221    pub use super::integrity::{InsertIntegrityValidator, UpdateIntegrityValidator};
222    pub use super::join::JoinEngine;
223    pub use super::referenced_tables::get_referenced_tables;
224    pub use super::schema::DatabaseSchema;
225    pub use super::transaction::DatabaseOverlay;
226    pub use super::transaction::session::TransactionSession;
227}