Documetation for the entity module
This commit is contained in:
parent
817e9bdd23
commit
db098d1a03
@ -5,6 +5,7 @@ use async_trait::async_trait;
|
||||
use sea_query::{Nullable, ValueTuple};
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Defines a value from an ActiveModel and its state
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ActiveValue<V>
|
||||
where
|
||||
@ -14,6 +15,7 @@ where
|
||||
state: ActiveValueState,
|
||||
}
|
||||
|
||||
/// Defines a set operation on an [ActiveValue]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn Set<V>(v: V) -> ActiveValue<V>
|
||||
where
|
||||
@ -22,6 +24,7 @@ where
|
||||
ActiveValue::set(v)
|
||||
}
|
||||
|
||||
/// Defines an unset operation on an [ActiveValue]
|
||||
#[allow(non_snake_case)]
|
||||
pub fn Unset<V>(_: Option<bool>) -> ActiveValue<V>
|
||||
where
|
||||
@ -30,6 +33,7 @@ where
|
||||
ActiveValue::unset()
|
||||
}
|
||||
|
||||
// Defines the state of an [ActiveValue]
|
||||
#[derive(Clone, Debug)]
|
||||
enum ActiveValueState {
|
||||
Set,
|
||||
@ -51,22 +55,31 @@ where
|
||||
ActiveValue::unchanged(value)
|
||||
}
|
||||
|
||||
/// Enforces a set of constraints on any type performing an Create, Update or Delete operation
|
||||
#[async_trait]
|
||||
pub trait ActiveModelTrait: Clone + Debug {
|
||||
/// Enforce the type to the constraints of the [EntityTrait]
|
||||
type Entity: EntityTrait;
|
||||
|
||||
/// Get a mutable [ActiveValue] from an ActiveModel
|
||||
fn take(&mut self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
|
||||
|
||||
/// Get a immutable [ActiveValue] from an ActiveModel
|
||||
fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> ActiveValue<Value>;
|
||||
|
||||
/// Set the Value into an ActiveModel
|
||||
fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
|
||||
|
||||
/// Set the state of an [ActiveValue] to the Unset state
|
||||
fn unset(&mut self, c: <Self::Entity as EntityTrait>::Column);
|
||||
|
||||
/// Check the state of a [ActiveValue]
|
||||
fn is_unset(&self, c: <Self::Entity as EntityTrait>::Column) -> bool;
|
||||
|
||||
/// The default implementation of the ActiveModel
|
||||
fn default() -> Self;
|
||||
|
||||
/// Get the primary key of the ActiveModel
|
||||
#[allow(clippy::question_mark)]
|
||||
fn get_primary_key_value(&self) -> Option<ValueTuple> {
|
||||
let mut cols = <Self::Entity as EntityTrait>::PrimaryKey::iter();
|
||||
@ -103,6 +116,7 @@ pub trait ActiveModelTrait: Clone + Debug {
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform an `INSERT` operation on the ActiveModel
|
||||
async fn insert<'a, C>(self, db: &'a C) -> Result<Self, DbErr>
|
||||
where
|
||||
<Self::Entity as EntityTrait>::Model: IntoActiveModel<Self>,
|
||||
@ -121,6 +135,7 @@ pub trait ActiveModelTrait: Clone + Debug {
|
||||
ActiveModelBehavior::after_save(am, true)
|
||||
}
|
||||
|
||||
/// Perform the `UPDATE` operation on an ActiveModel
|
||||
async fn update<'a, C>(self, db: &'a C) -> Result<Self, DbErr>
|
||||
where
|
||||
Self: ActiveModelBehavior + 'a,
|
||||
@ -170,6 +185,7 @@ pub trait ActiveModelTrait: Clone + Debug {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce a set of constraints to a override the ActiveModel behavior
|
||||
/// Behaviors for users to override
|
||||
#[allow(unused_variables)]
|
||||
pub trait ActiveModelBehavior: ActiveModelTrait {
|
||||
@ -199,10 +215,12 @@ pub trait ActiveModelBehavior: ActiveModelTrait {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enforce constraints for conversion to an ActiveModel
|
||||
pub trait IntoActiveModel<A>
|
||||
where
|
||||
A: ActiveModelTrait,
|
||||
{
|
||||
/// Method to call to perform the conversion
|
||||
fn into_active_model(self) -> A;
|
||||
}
|
||||
|
||||
@ -215,10 +233,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Constraints to perform the conversion of a type into an [ActiveValue]
|
||||
pub trait IntoActiveValue<V>
|
||||
where
|
||||
V: Into<Value>,
|
||||
{
|
||||
/// Method to perform the conversion
|
||||
fn into_active_value(self) -> ActiveValue<V>;
|
||||
}
|
||||
|
||||
@ -296,6 +316,7 @@ impl<V> ActiveValue<V>
|
||||
where
|
||||
V: Into<Value>,
|
||||
{
|
||||
/// Set the value of an [ActiveValue] and also set its state to `ActiveValueState::Set`
|
||||
pub fn set(value: V) -> Self {
|
||||
Self {
|
||||
value: Some(value),
|
||||
@ -303,6 +324,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the state of an [ActiveValue] is `ActiveValueState::Set` which returns true
|
||||
pub fn is_set(&self) -> bool {
|
||||
matches!(self.state, ActiveValueState::Set)
|
||||
}
|
||||
@ -314,10 +336,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the status of the [ActiveValue] is `ActiveValueState::Unchanged`
|
||||
/// which returns `true` if it is
|
||||
pub fn is_unchanged(&self) -> bool {
|
||||
matches!(self.state, ActiveValueState::Unchanged)
|
||||
}
|
||||
|
||||
/// Set the `value` field of the ActiveModel to [Option::None] and the
|
||||
/// `state` field to `ActiveValueState::Unset`
|
||||
pub fn unset() -> Self {
|
||||
Self {
|
||||
value: None,
|
||||
@ -325,23 +351,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if the state of an [ActiveValue] is `ActiveValueState::Unset`
|
||||
/// which returns true if it is
|
||||
pub fn is_unset(&self) -> bool {
|
||||
matches!(self.state, ActiveValueState::Unset)
|
||||
}
|
||||
|
||||
/// Get the mutable value of the `value` field of an [ActiveValue]
|
||||
/// also setting it's state to `ActiveValueState::Unset`
|
||||
pub fn take(&mut self) -> Option<V> {
|
||||
self.state = ActiveValueState::Unset;
|
||||
self.value.take()
|
||||
}
|
||||
|
||||
/// Get an owned value of the `value` field of the [ActiveValue]
|
||||
pub fn unwrap(self) -> V {
|
||||
self.value.unwrap()
|
||||
}
|
||||
|
||||
/// Check is a [Value] exists or not
|
||||
pub fn into_value(self) -> Option<Value> {
|
||||
self.value.map(Into::into)
|
||||
}
|
||||
|
||||
/// Wrap the [Value] into a `ActiveValue<Value>`
|
||||
pub fn into_wrapped_value(self) -> ActiveValue<Value> {
|
||||
match self.state {
|
||||
ActiveValueState::Set => ActiveValue::set(self.into_value().unwrap()),
|
||||
|
@ -7,21 +7,28 @@ use sea_query::{Alias, Iden, IntoIden, IntoTableRef, IntoValueTuple, TableRef};
|
||||
pub use sea_strum::IntoEnumIterator as Iterable;
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Ensure the identifier for an Entity can be converted to a static str
|
||||
pub trait IdenStatic: Iden + Copy + Debug + 'static {
|
||||
/// Method to call to get the static string identity
|
||||
fn as_str(&self) -> &str;
|
||||
}
|
||||
|
||||
/// Enforces the naming of an entity to a set of constraints
|
||||
pub trait EntityName: IdenStatic + Default {
|
||||
/// Method to get the name for the schema, defaults to [Option::None] if not set
|
||||
fn schema_name(&self) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Get the name of the table
|
||||
fn table_name(&self) -> &str;
|
||||
|
||||
/// Get the name of the module from the invoking `self.table_name()`
|
||||
fn module_name(&self) -> &str {
|
||||
self.table_name()
|
||||
}
|
||||
|
||||
/// Get the [TableRef] from invoking the `self.schema_name()`
|
||||
fn table_ref(&self) -> TableRef {
|
||||
match self.schema_name() {
|
||||
Some(schema) => (Alias::new(schema).into_iden(), self.into_iden()).into_table_ref(),
|
||||
@ -43,14 +50,19 @@ pub trait EntityName: IdenStatic + Default {
|
||||
/// - Update: `update`, `update_*`
|
||||
/// - Delete: `delete`, `delete_*`
|
||||
pub trait EntityTrait: EntityName {
|
||||
#[allow(missing_docs)]
|
||||
type Model: ModelTrait<Entity = Self> + FromQueryResult;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
type Column: ColumnTrait;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
type Relation: RelationTrait;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
type PrimaryKey: PrimaryKeyTrait + PrimaryKeyToColumn<Column = Self::Column>;
|
||||
|
||||
/// Check if the relation belongs to an Entity
|
||||
fn belongs_to<R>(related: R) -> RelationBuilder<Self, R>
|
||||
where
|
||||
R: EntityTrait,
|
||||
@ -58,6 +70,7 @@ pub trait EntityTrait: EntityName {
|
||||
RelationBuilder::new(RelationType::HasOne, Self::default(), related, false)
|
||||
}
|
||||
|
||||
/// Check if the entity has at least one relation
|
||||
fn has_one<R>(_: R) -> RelationBuilder<Self, R>
|
||||
where
|
||||
R: EntityTrait + Related<Self>,
|
||||
@ -65,6 +78,7 @@ pub trait EntityTrait: EntityName {
|
||||
RelationBuilder::from_rel(RelationType::HasOne, R::to().rev(), true)
|
||||
}
|
||||
|
||||
/// Chech if the Entity has many relations
|
||||
fn has_many<R>(_: R) -> RelationBuilder<Self, R>
|
||||
where
|
||||
R: EntityTrait + Related<Self>,
|
||||
|
@ -2,6 +2,7 @@ use crate::{EntityName, IdenStatic, Iterable};
|
||||
use sea_query::{DynIden, Expr, SeaRc, SelectStatement, SimpleExpr, Value};
|
||||
use std::str::FromStr;
|
||||
|
||||
/// Defines a Column for an Entity
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ColumnDef {
|
||||
pub(crate) col_type: ColumnType,
|
||||
@ -10,34 +11,62 @@ pub struct ColumnDef {
|
||||
pub(crate) indexed: bool,
|
||||
}
|
||||
|
||||
/// The type of column as defined in the SQL format
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ColumnType {
|
||||
/// `CHAR` type of specified fixed length
|
||||
Char(Option<u32>),
|
||||
/// `STRING` type for variable string length
|
||||
String(Option<u32>),
|
||||
/// `TEXT` type used for large pieces of string data and stored out of row in case size is too big
|
||||
Text,
|
||||
/// `TINYINT` useful for storing one byte of data (range of 0-255)
|
||||
TinyInteger,
|
||||
/// `SMALLINT` data type stores small whole numbers that range from –32,767 to 32,767
|
||||
SmallInteger,
|
||||
/// `INTEGER` data types hold numbers that are whole, or without a decimal point
|
||||
Integer,
|
||||
/// `BIGINT` is a 64-bit representation of an integer taking up 8 bytes of storage and
|
||||
/// ranging from -2^63 (-9,223,372,036,854,775,808) to 2^63 (9,223,372,036,854,775,807).
|
||||
BigInteger,
|
||||
/// `FLOAT` an approximate-number data type, where values range cannot be represented exactly.
|
||||
Float,
|
||||
/// `DOUBLE` is a normal-size floating point number where the
|
||||
/// total number of digits is specified in size.
|
||||
Double,
|
||||
/// `DECIMAL` type store numbers that have fixed precision and scale
|
||||
Decimal(Option<(u32, u32)>),
|
||||
/// `DATETIME` type is used for values that contain both date and time parts.
|
||||
DateTime,
|
||||
/// `TIMESTAMP` is a temporal data type that holds the combination of date and time.
|
||||
Timestamp,
|
||||
/// `TIMESTAMP WITH TIME ZONE` (or `TIMESTAMPTZ`) data type stores 8-byte
|
||||
/// date values that include timestamp and time zone information in UTC format.
|
||||
TimestampWithTimeZone,
|
||||
/// `TIME` data type defines a time of a day based on 24-hour clock
|
||||
Time,
|
||||
/// `DATE` data type stores the calendar date
|
||||
Date,
|
||||
/// `BINARY` data types contain byte strings—a sequence of octets or bytes.
|
||||
Binary,
|
||||
/// `BOOLEAN` is the result of a comparison operator
|
||||
Boolean,
|
||||
/// `MONEY` data type handles monetary data
|
||||
Money(Option<(u32, u32)>),
|
||||
/// `JSON` represents the JavaScript Object Notation type
|
||||
Json,
|
||||
/// JSON binary format is structured in the way that permits the server to search for
|
||||
/// values within the JSON document directly by key or array index, which is very fast.
|
||||
JsonBinary,
|
||||
/// A custom implementation of a data type
|
||||
Custom(String),
|
||||
/// A Universally Unique IDentifier that is specified in RFC 4122
|
||||
Uuid,
|
||||
}
|
||||
|
||||
macro_rules! bind_oper {
|
||||
( $op: ident ) => {
|
||||
#[allow(missing_docs)]
|
||||
fn $op<V>(&self, v: V) -> SimpleExpr
|
||||
where
|
||||
V: Into<Value>,
|
||||
@ -58,6 +87,7 @@ macro_rules! bind_func_no_params {
|
||||
|
||||
macro_rules! bind_vec_func {
|
||||
( $func: ident ) => {
|
||||
#[allow(missing_docs)]
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn $func<V, I>(&self, v: I) -> SimpleExpr
|
||||
where
|
||||
@ -72,6 +102,7 @@ macro_rules! bind_vec_func {
|
||||
macro_rules! bind_subquery_func {
|
||||
( $func: ident ) => {
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
#[allow(missing_docs)]
|
||||
fn $func(&self, s: SelectStatement) -> SimpleExpr {
|
||||
Expr::tbl(self.entity_name(), *self).$func(s)
|
||||
}
|
||||
@ -81,14 +112,18 @@ macro_rules! bind_subquery_func {
|
||||
// LINT: when the operand value does not match column type
|
||||
/// Wrapper of the identically named method in [`sea_query::Expr`]
|
||||
pub trait ColumnTrait: IdenStatic + Iterable + FromStr {
|
||||
#[allow(missing_docs)]
|
||||
type EntityName: EntityName;
|
||||
|
||||
/// Define a column for an Entity
|
||||
fn def(&self) -> ColumnDef;
|
||||
|
||||
/// Get the name of the entity the column belongs to
|
||||
fn entity_name(&self) -> DynIden {
|
||||
SeaRc::new(Self::EntityName::default()) as DynIden
|
||||
}
|
||||
|
||||
/// get the name of the entity the column belongs to
|
||||
fn as_column_ref(&self) -> (DynIden, DynIden) {
|
||||
(self.entity_name(), SeaRc::new(*self) as DynIden)
|
||||
}
|
||||
@ -221,6 +256,7 @@ pub trait ColumnTrait: IdenStatic + Iterable + FromStr {
|
||||
bind_func_no_params!(is_null);
|
||||
bind_func_no_params!(is_not_null);
|
||||
|
||||
/// Perform an operation if the column is null
|
||||
fn if_null<V>(&self, v: V) -> SimpleExpr
|
||||
where
|
||||
V: Into<Value>,
|
||||
@ -236,6 +272,7 @@ pub trait ColumnTrait: IdenStatic + Iterable + FromStr {
|
||||
}
|
||||
|
||||
impl ColumnType {
|
||||
/// instantiate a new [ColumnDef]
|
||||
pub fn def(self) -> ColumnDef {
|
||||
ColumnDef {
|
||||
col_type: self,
|
||||
@ -247,20 +284,24 @@ impl ColumnType {
|
||||
}
|
||||
|
||||
impl ColumnDef {
|
||||
/// Marks the column as `UNIQUE`
|
||||
pub fn unique(mut self) -> Self {
|
||||
self.unique = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Mark the column as nullable
|
||||
pub fn null(self) -> Self {
|
||||
self.nullable()
|
||||
}
|
||||
|
||||
/// Mark the column as nullable
|
||||
pub fn nullable(mut self) -> Self {
|
||||
self.null = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the `indexed` field to `true`
|
||||
pub fn indexed(mut self) -> Self {
|
||||
self.indexed = true;
|
||||
self
|
||||
|
@ -2,10 +2,14 @@ use crate::{ColumnTrait, EntityTrait, IdenStatic};
|
||||
use sea_query::{Alias, DynIden, Iden, IntoIden, SeaRc};
|
||||
use std::fmt;
|
||||
|
||||
/// Defines an operation for an Entity
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Identity {
|
||||
/// Performs one operation
|
||||
Unary(DynIden),
|
||||
/// Performs two operations
|
||||
Binary(DynIden, DynIden),
|
||||
/// Performs three operations
|
||||
Ternary(DynIden, DynIden, DynIden),
|
||||
}
|
||||
|
||||
@ -28,14 +32,18 @@ impl Iden for Identity {
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs a conversion into an [Identity]
|
||||
pub trait IntoIdentity {
|
||||
/// Method to perform the conversion
|
||||
fn into_identity(self) -> Identity;
|
||||
}
|
||||
|
||||
/// Check the [Identity] of an Entity
|
||||
pub trait IdentityOf<E>
|
||||
where
|
||||
E: EntityTrait,
|
||||
{
|
||||
/// Method to call to perform this check
|
||||
fn identity_of(self) -> Identity;
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,21 @@ use crate::{
|
||||
};
|
||||
use sea_query::{Alias, IntoIden, JoinType, SeaRc};
|
||||
|
||||
/// Same as [RelationDef]
|
||||
pub type LinkDef = RelationDef;
|
||||
|
||||
/// A set of constraints for links between Entities
|
||||
pub trait Linked {
|
||||
#[allow(missing_docs)]
|
||||
type FromEntity: EntityTrait;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
type ToEntity: EntityTrait;
|
||||
|
||||
/// Link for an Entity
|
||||
fn link(&self) -> Vec<LinkDef>;
|
||||
|
||||
/// Find all the Entities that are linked to the Entity
|
||||
fn find_linked(&self) -> Select<Self::ToEntity> {
|
||||
let mut select = Select::new();
|
||||
for (i, rel) in self.link().into_iter().rev().enumerate() {
|
||||
|
@ -4,6 +4,7 @@ mod column;
|
||||
mod identity;
|
||||
mod link;
|
||||
mod model;
|
||||
/// Re-export common types from the entity
|
||||
pub mod prelude;
|
||||
mod primary_key;
|
||||
mod relation;
|
||||
|
@ -5,13 +5,18 @@ use crate::{
|
||||
pub use sea_query::Value;
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// A set of constraints for a Model
|
||||
pub trait ModelTrait: Clone + Send + Debug {
|
||||
#[allow(missing_docs)]
|
||||
type Entity: EntityTrait;
|
||||
|
||||
/// Get the [Value] of a column from an Entity
|
||||
fn get(&self, c: <Self::Entity as EntityTrait>::Column) -> Value;
|
||||
|
||||
/// Set the [Value] of a column in an Entity
|
||||
fn set(&mut self, c: <Self::Entity as EntityTrait>::Column, v: Value);
|
||||
|
||||
/// Find related Models
|
||||
fn find_related<R>(&self, _: R) -> Select<R>
|
||||
where
|
||||
R: EntityTrait,
|
||||
@ -20,6 +25,7 @@ pub trait ModelTrait: Clone + Send + Debug {
|
||||
<Self::Entity as Related<R>>::find_related().belongs_to(self)
|
||||
}
|
||||
|
||||
/// Find linked Models
|
||||
fn find_linked<L>(&self, l: L) -> Select<L::ToEntity>
|
||||
where
|
||||
L: Linked<FromEntity = Self::Entity>,
|
||||
@ -29,9 +35,13 @@ pub trait ModelTrait: Clone + Send + Debug {
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of constraints for implementing a [QueryResult]
|
||||
pub trait FromQueryResult: Sized {
|
||||
/// Instantiate a Model from a [QueryResult]
|
||||
fn from_query_result(res: &QueryResult, pre: &str) -> Result<Self, DbErr>;
|
||||
|
||||
/// Transform the error from instantiating a Model from a [QueryResult]
|
||||
/// and converting it to an [Option]
|
||||
fn from_query_result_optional(res: &QueryResult, pre: &str) -> Result<Option<Self>, DbErr> {
|
||||
Ok(Self::from_query_result(res, pre).ok())
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ pub use chrono::NaiveTime as Time;
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub use chrono::NaiveDateTime as DateTime;
|
||||
|
||||
/// Handles the time and dates
|
||||
#[cfg(feature = "with-chrono")]
|
||||
pub type DateTimeWithTimeZone = chrono::DateTime<chrono::FixedOffset>;
|
||||
|
||||
|
@ -4,7 +4,9 @@ use sea_query::{FromValueTuple, IntoValueTuple};
|
||||
use std::fmt::Debug;
|
||||
|
||||
//LINT: composite primary key cannot auto increment
|
||||
/// A set of constraints to be used to define a Primary Key
|
||||
pub trait PrimaryKeyTrait: IdenStatic + Iterable {
|
||||
#[allow(missing_docs)]
|
||||
type ValueType: Sized
|
||||
+ Send
|
||||
+ Debug
|
||||
@ -14,14 +16,19 @@ pub trait PrimaryKeyTrait: IdenStatic + Iterable {
|
||||
+ TryGetableMany
|
||||
+ TryFromU64;
|
||||
|
||||
/// Method to call to perform `AUTOINCREMENT` operation on a Primary Kay
|
||||
fn auto_increment() -> bool;
|
||||
}
|
||||
|
||||
/// How to map a Primary Key to a column
|
||||
pub trait PrimaryKeyToColumn {
|
||||
#[allow(missing_docs)]
|
||||
type Column: ColumnTrait;
|
||||
|
||||
/// Method to map a primary key to a column in an Entity
|
||||
fn into_column(self) -> Self::Column;
|
||||
|
||||
/// Method to map a primary key from a column in an Entity
|
||||
fn from_column(col: Self::Column) -> Option<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -3,45 +3,68 @@ use core::marker::PhantomData;
|
||||
use sea_query::{JoinType, TableRef};
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Defines the type of relationship
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum RelationType {
|
||||
/// An Entity has one relationship
|
||||
HasOne,
|
||||
/// An Entity has many relationships
|
||||
HasMany,
|
||||
}
|
||||
|
||||
/// Action to perform on a foreign key whenever there are changes
|
||||
/// to an ActiveModel
|
||||
pub type ForeignKeyAction = sea_query::ForeignKeyAction;
|
||||
|
||||
/// Constraints a type to implement the trait to create a relationship
|
||||
pub trait RelationTrait: Iterable + Debug + 'static {
|
||||
/// The method to call
|
||||
fn def(&self) -> RelationDef;
|
||||
}
|
||||
|
||||
/// Checks if Entities are related
|
||||
pub trait Related<R>
|
||||
where
|
||||
R: EntityTrait,
|
||||
{
|
||||
/// Check if an entity is related to another entity
|
||||
fn to() -> RelationDef;
|
||||
|
||||
/// Check if an entity is related through another entity
|
||||
fn via() -> Option<RelationDef> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Find related Entities
|
||||
fn find_related() -> Select<R> {
|
||||
Select::<R>::new().join_join_rev(JoinType::InnerJoin, Self::to(), Self::via())
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines a relationship
|
||||
#[derive(Debug)]
|
||||
pub struct RelationDef {
|
||||
/// The type of relationship defined in [RelationType]
|
||||
pub rel_type: RelationType,
|
||||
/// Reference from another Entity
|
||||
pub from_tbl: TableRef,
|
||||
/// Reference to another ENtity
|
||||
pub to_tbl: TableRef,
|
||||
/// Reference to from a Column
|
||||
pub from_col: Identity,
|
||||
/// Reference to another column
|
||||
pub to_col: Identity,
|
||||
/// Defines the owner of the Relation
|
||||
pub is_owner: bool,
|
||||
/// Defines an operation to be performed on a Foreign Key when a
|
||||
/// `DELETE` Operation is performed
|
||||
pub on_delete: Option<ForeignKeyAction>,
|
||||
/// Defines an operation to be performed on a Foreign Key when a
|
||||
/// `UPDATE` Operation is performed
|
||||
pub on_update: Option<ForeignKeyAction>,
|
||||
}
|
||||
|
||||
/// Defines a helper to build a relation
|
||||
#[derive(Debug)]
|
||||
pub struct RelationBuilder<E, R>
|
||||
where
|
||||
@ -108,6 +131,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a relationship from an Entity
|
||||
pub fn from<T>(mut self, identifier: T) -> Self
|
||||
where
|
||||
T: IdentityOf<E>,
|
||||
@ -116,6 +140,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Build a relationship to an Entity
|
||||
pub fn to<T>(mut self, identifier: T) -> Self
|
||||
where
|
||||
T: IdentityOf<R>,
|
||||
@ -124,11 +149,13 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// An operation to perform on a foreign key when a delete operation occurs
|
||||
pub fn on_delete(mut self, action: ForeignKeyAction) -> Self {
|
||||
self.on_delete = Some(action);
|
||||
self
|
||||
}
|
||||
|
||||
/// An operation to perform on a foreign key when an update operation occurs
|
||||
pub fn on_update(mut self, action: ForeignKeyAction) -> Self {
|
||||
self.on_update = Some(action);
|
||||
self
|
||||
|
Loading…
x
Reference in New Issue
Block a user