IC-DBMS Canister

logo

license-mit repo-stars downloads latest-version ko-fi conventional-commits

ci coveralls docs


Documentation

Guides

Step-by-step guides for building database canisters:

Reference

API and type reference documentation:

Technical Documentation

For advanced users and contributors:


Quick Example

Define your schema:

use candid::{CandidType, Deserialize};
use ic_dbms_api::prelude::*;

#[derive(Debug, Table, CandidType, Deserialize, 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,
}

Generate the canister:

use ic_dbms_canister::prelude::DbmsCanister;

#[derive(DbmsCanister)]
#[tables(User = "users")]
pub struct MyDbmsCanister;

ic_cdk::export_candid!();

Use the client:

use ic_dbms_client::{IcDbmsCanisterClient, Client as _};

let client = IcDbmsCanisterClient::new(canister_id);

// Insert
let user = UserInsertRequest { id: 1.into(), name: "Alice".into(), email: "alice@example.com".into() };
client.insert::<User>(User::table_name(), user, None).await? ?;

// Query
let query = Query::builder()
.filter(Filter::eq("name", Value::Text("Alice".into())))
.build();
let users = client.select::<User>(User::table_name(), query, None).await? ?;

Features

  • Schema-driven: Define tables as Rust structs with derive macros
  • CRUD operations: Full insert, select, update, delete support
  • ACID transactions: Commit/rollback with isolation
  • Foreign keys: Referential integrity with cascade/restrict/break behaviors
  • Validation & Sanitization: Built-in validators and sanitizers
  • JSON support: Store and query semi-structured data
  • Access control: Principal-based ACL
  • Type-safe client: Compile-time checked operations