This section describes how to define your database schema when using ic-dbms-canister, focusing on user-defined entities and their relationships.
The schema is defined entirely in Rust by annotating structs with derive macros and attributes. Each struct represents a database table, and each field represents a column.
When defining your schema, you must follow these rules:
#[primary_key] attribute.#[foreign_key(entity = "...", table = "...", column = "...")].#[table = "..."], which specifies the table name in the database.The following types are supported in schema definitions:
BlobBooleanDateDateTimeDecimalInt8Int16Int32Int64Nullable<Type>PrincipalTextUint8Uint16Uint32Uint64UuidUsing unsupported types will result in a compile-time error.
#[derive(Debug, Table, CandidType, Deserialize, Clone, PartialEq, Eq)]
#[table = "users"]
pub struct User {
#[primary_key]
pub id: Uint32,
pub name: Text,
pub email: Text,
}
#[derive(Debug, Table, CandidType, Deserialize, 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 user: Uint32,
}
It is possible to specify a different memory alignment for a table using the #[alignment = "..."] attribute:
#[derive(Debug, Table, CandidType, Deserialize, Clone, PartialEq, Eq)]
#[table = "aligned_table"]
#[alignment = 48]
pub struct AlignedTable {
#[primary_key]
pub id: Uint32,
pub data: Text,
}
[!CAUTION]
Specifying a custom alignment is an advanced feature and should be used with caution. Incorrect alignment can lead to performance degradation. Ensure you understand the implications before using this attribute.
[!NOTE]
If the table has a fixed size (e.g. a table with just
Int32andBooleanfields), the alignment attribute will be ignored since fixed-size tables have the alignment equal to their size.