#[derive(Table)]
{
// Attributes available to this derive:
#[table]
}
Expand description
Implements the Table trait for the some struct, and creates a table module
for it containing some useful items which allow performing operations on
this table.
§Example
#[derive(Table)]
#[table(unique(first_name, last_name))]
struct Person {
id: i32,
first_name: String,
last_name: String,
age: i32,
#[table(foreign_key(School))]
school_id: i32,
}
#[derive(Table)]
struct School {
id: i32,
name: String,
}The Table macro, besides implementing the Table trait for the provided
struct, will also create a module which has the same name as the struct, but
converted to snake_case. This module will contain useful items which allow
peforing operations on the table.
For example, for the Person struct, a module named person will be
created, containing the following items:
-
A struct called
new(person::new), which contains all fields of a person other than its id. Thenewstruct implements theInsertabletrait which allows inserting it to the database. The fields of this struct use the [std::borrow::Borrow] trait to allow for providing things that the actual type can be borrowed us. For example when creating a school usingschool::new, we can provide a value of type&strfor thenamefield. -
A struct called
new_with_id, same as thenewstruct but allows specifying a value for the id field. -
An empty struct called
table(person::table), which implements theTableMarkertrait. This struct allows you to perform operations on the table likecreate,drop,delete,find,inner_join. -
An empty struct called
all(person::all) which implements theSelectedValuestrait and allows selecting all fields of this table in functions which require selecting custom values. -
An empty struct for each column in the table. For example in the above example, the created structs will be
person::id,person::first_name,person::last_name,person::ageandperson::school_id. Each of these structs implement theSqlExpressiontrait. -
A module named
unique_constraintscontaining marker structs for each unique constraint on the table. For example in the above example, the created structs will beperson::unique_constraints::idandperson::unique_constraints::first_name_last_name.
§Foreign Keys
Foreign keys can be implemented as shown in the example above using the
#[table(foreign_key(...))] attribute, and specifying the table struct’s
name.
Foreign keys allow you to perform joins on the tables, and we can then perform select queries on the joined tables, for example, for the above snippet we can do the following:
let _ = person::table.inner_join(school::table)
.find()
.filter(school::name.equals("Stanford"))
.load_all::<Person>(...)
.await?;Foreign keys can also be optional, for example:
#[derive(Table)]
pub struct MaybeStudent {
id: i32,
#[table(foreign_key(School))]
school_id: Option<i32>,
}The inner join of the table MaybeStudent with the table School will then
only return the students who’s school_id is not None.
A single table can also have multiple foreign keys to the same table, for example:
#[derive(Table)]
pub struct Student {
id: i32,
#[table(foreign_key(School))]
elementary_school: i32,
#[table(foreign_key(School))]
university: i32,
}If you then want to perform an inner join from Student to School, you will have to use the
inner_join_on_column function instead of just using the inner_join function, because you
must explicitly tell the orm which column you want to perform the join on, for example:
let _ = student::table.inner_join_on_column(student::university, school::table)
.find()
.filter(school::name.equals("Stanford"))
.load_all::<Student>(...)
.await?;Please note that the type of the foreign key field must match the type of
the referenced table’s id field.
§Unique Constraints
Unique constraints can be implemented as shown in the example above using
the #[table(unique(...))] attribute, and specifying the fields on which
the unique constraint should enforce uniqueness.
If you want to add a unique constraint on a single field, you can also add a
#[table(unique)] attribute on one of the table struct’s fields, for
example: ```rust
#[derive(Table)]
pub struct Person {
#[table(unique)]
full_name: String,
}
You can create multiple unique constraints on a single table by adding
multiple `#[table(unique(...))]` attributes to the table struct.
A unique constraint for the id field is automatically created.
Unique constraints allow you to use `ON CONFLICT` clauses, and to perform
upserts, for example, for the above snippet, we can do the following:
```rust
let upserted_person = person::new {
first_name: "James",
last_name: "Brown",
age: &44,
school_id: &2,
}
.insert()
.on_conflict(person::unique_constraints::first_name_last_name)
.do_update(update_set!(person::school_id = 2))
.returning(person::all)
.load_one::<Person>(...)
.await?;