Skip to main content

Table

Derive Macro Table 

Source
#[derive(Table)]
{
    // Attributes available to this derive:
    #[alignment]
    #[autoincrement]
    #[candid]
    #[custom_type]
    #[foreign_key]
    #[index]
    #[primary_key]
    #[sanitizer]
    #[table]
    #[unique]
    #[validate]
}
Expand description

Given a struct representing a database table, automatically implements the TableSchema trait with all the necessary types to work with the wasm-dbms engine. So given this struct:

#[derive(Table, Encode)]
#[table = "posts"]
struct Post {
    #[primary_key]
    id: Uint32,
    title: Text,
    content: Text,
    #[foreign_key(entity = "User", table = "users", column = "id")]
    author_id: Uint32,
}

What we expect as output is:

  • To implement the TableSchema trait for the struct as follows:

    impl TableSchema for Post {
        type Insert = PostInsertRequest;
        type Record = PostRecord;
        type Update = PostUpdateRequest;
        type ForeignFetcher = PostForeignFetcher;
    
        fn columns() -> &'static [ColumnDef] {
            &[
                ColumnDef {
                    name: "id",
                    data_type: DataTypeKind::Uint32,
                    auto_increment: false,
                    nullable: false,
                    primary_key: true,
                    unique: true,
                    foreign_key: None,
                },
                ColumnDef {
                    name: "title",
                    data_type: DataTypeKind::Text,
                    auto_increment: false,
                    nullable: false,
                    primary_key: false,
                    unique: false,
                    foreign_key: None,
                },
                ColumnDef {
                    name: "content",
                    data_type: DataTypeKind::Text,
                    auto_increment: false,
                    nullable: false,
                    primary_key: false,
                    unique: false,
                    foreign_key: None,
                },
                ColumnDef {
                    name: "user_id",
                    data_type: DataTypeKind::Uint32,
                    auto_increment: false,
                    nullable: false,
                    primary_key: false,
                    unique: false,
                    foreign_key: Some(ForeignKeyDef {
                        local_column: "user_id",
                        foreign_table: "users",
                        foreign_column: "id",
                    }),
                },
            ]
        }
    
        fn table_name() -> &'static str {
            "posts"
        }
    
        fn primary_key() -> &'static str {
            "id"
        }
    
        fn to_values(self) -> Vec<(ColumnDef, Value)> {
            vec![
                (Self::columns()[0], Value::Uint32(self.id)),
                (Self::columns()[1], Value::Text(self.title)),
                (Self::columns()[2], Value::Text(self.content)),
                (Self::columns()[3], Value::Uint32(self.user_id)),
            ]
        }
    }
  • Implement the associated Record type

  • Implement the associated InsertRecord type

  • Implement the associated UpdateRecord type

  • If has foreign keys, implement the associated ForeignFetcher

So for each struct deriving Table, we will generate the following type. Given ${StructName}, we will generate:

  • ${StructName}Record - implementing TableRecord
  • ${StructName}InsertRequest - implementing InsertRecord
  • ${StructName}UpdateRequest - implementing UpdateRecord
  • ${StructName}ForeignFetcher (only if foreign keys are present)

Also, we will implement the TableSchema trait for the struct itself and derive Encode for ${StructName}.

§Attributes

The Table derive macro supports the following attributes:

  • #[alignment = N]: (optional) Specifies the alignment for the table records. Use only if you know what you are doing.
  • #[autoincrement]: Marks a field as auto-incrementing. The macro will generate code to automatically fill in values for this field during inserts. Auto-increment fields must be non-nullable and cannot be marked as #[unique].
  • #[candid]: Marks the table as compatible with Candid serialization.
  • #[custom_type = "TypeName"]: Specifies a custom data type for the
  • #[foreign_key(entity = "EntityName", table = "table_name", column = "column_name")]: Defines a foreign key relationship.
  • #[index]: Marks a field to be indexed for faster queries.
  • #[primary_key]: Marks a field as the primary key of the table.
  • #[sanitizer(SanitizerType)]: Specifies a sanitize for the field.
  • #[table = "table_name"]: Specifies the name of the table in the database.
  • #[unique]: Marks a field to have a unique constraint.
  • #[validate(ValidatorType)]: Specifies a validator for the field.