Data Types Reference (IC)

Note: This is the IC-specific data types reference. For the complete list of all data types, usage examples, and general documentation, see the generic data types reference.


Overview

All wasm-dbms data types are available in ic-dbms through ic_dbms_api::prelude::* (which re-exports wasm_dbms_api types). This document covers the IC-specific aspects: the Principal type (which is unique to the Internet Computer) and the Candid type mappings used for canister API serialization.


Principal Type

Principal is an Internet Computer-specific identifier type. It represents a canister ID, user identity, or the anonymous principal. This type is only meaningful in the IC context.

Usage

use ic_dbms_api::prelude::*;

#[derive(Debug, Table, CandidType, Deserialize, Clone, PartialEq, Eq)]
#[table = "users"]
pub struct User {
    #[primary_key]
    pub id: Uint32,
    #[custom_type]
    pub owner: Principal,  // IC principal who owns this record
}

Creating principals:

use candid::Principal;

// From text representation
let principal = Principal::from_text("aaaaa-aa").unwrap();

// Anonymous principal
let anon = Principal::anonymous();

// Caller principal (inside a canister)
let caller = ic_cdk::caller();

// Management canister
let mgmt = Principal::management_canister();

Using in insert requests:

let user = UserInsertRequest {
    id: 1.into(),
    owner: ic_cdk::caller(),  // Store the caller's principal
};

client.insert::<User>(User::table_name(), user, None).await??;

Common Patterns

Recording ownership:

#[derive(Debug, Table, CandidType, Deserialize, Clone, PartialEq, Eq)]
#[table = "documents"]
pub struct Document {
    #[primary_key]
    pub id: Uuid,
    pub title: Text,
    #[custom_type]
    pub owner: Principal,      // Who created this
    #[custom_type]
    pub last_editor: Principal, // Who last modified this
}

Filtering by principal:

// Find all documents owned by the caller
let filter = Filter::eq("owner", ic_cdk::caller().into());
let query = Query::builder().filter(filter).build();
let my_docs = client.select::<Document>(Document::table_name(), query, None).await??;

Nullable principal (optional ownership):

#[derive(Debug, Table, CandidType, Deserialize, Clone, PartialEq, Eq)]
#[table = "tasks"]
pub struct Task {
    #[primary_key]
    pub id: Uint32,
    pub title: Text,
    #[custom_type]
    pub assignee: Nullable<Principal>,  // May be unassigned
}

Candid Type Mapping

When ic-dbms generates the Candid interface (.did file) for your canister, each wasm-dbms type maps to a specific Candid type. This mapping is important for frontend integration, inter-canister calls, and using the Candid UI.

ic-dbms Type Rust Type Candid Type Notes
Uint8 u8 nat8  
Uint16 u16 nat16  
Uint32 u32 nat32  
Uint64 u64 nat64  
Int8 i8 int8  
Int16 i16 int16  
Int32 i32 int32  
Int64 i64 int64  
Decimal rust_decimal::Decimal text Serialized as string for precision
Text String text  
Boolean bool bool  
Date chrono::NaiveDate record { year; month; day } Structured record
DateTime chrono::DateTime<Utc> int64 Unix timestamp
Blob Vec<u8> blob  
Principal candid::Principal principal IC-specific
Uuid uuid::Uuid text String representation
Json serde_json::Value text Serialized JSON string
Nullable<T> Option<T> opt T Candid optional

Frontend integration example (JavaScript/TypeScript):

// Calling from a frontend using @dfinity/agent
const user = await actor.select_users({
  filter: [{ Eq: ["name", { Text: "Alice" }] }],
  order_by: [],
  limit: [10n],  // nat64 maps to bigint
  columns: [],
  with_tables: [],
}, []);  // No transaction ID

// Principal values
import { Principal } from "@dfinity/principal";
const owner = Principal.fromText("aaaaa-aa");

IC-Specific Considerations

Re-exports: ic_dbms_api::prelude::* re-exports all types from wasm_dbms_api::prelude::* plus IC-specific additions. You do not need to import wasm_dbms_api directly.

CandidType requirement: All data types used in your table schemas must implement CandidType. The built-in types already do. If you define custom data types, they must also derive CandidType.

Principal storage: The Principal type is stored in binary format in stable memory (29 bytes max). It is serialized to/from its Candid principal representation when crossing canister boundaries.

Decimal precision: The Decimal type is serialized as text in Candid to preserve arbitrary precision. Frontends should parse the string representation rather than using floating-point conversion.