Merge remote-tracking branch 'origin/master' into last-insert-id
This commit is contained in:
commit
ba66de16b6
@ -293,7 +293,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// DbBackend::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1)"#, vec!["Apple Pie".into()]
|
/// DbBackend::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1) RETURNING "id""#, vec!["Apple Pie".into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
fn insert<A>(model: A) -> Insert<A>
|
fn insert<A>(model: A) -> Insert<A>
|
||||||
@ -346,7 +346,7 @@ pub trait EntityTrait: EntityName {
|
|||||||
/// assert_eq!(
|
/// assert_eq!(
|
||||||
/// db.into_transaction_log(),
|
/// db.into_transaction_log(),
|
||||||
/// vec![Transaction::from_sql_and_values(
|
/// vec![Transaction::from_sql_and_values(
|
||||||
/// DbBackend::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1), ($2)"#,
|
/// DbBackend::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1), ($2) RETURNING "id""#,
|
||||||
/// vec!["Apple Pie".into(), "Orange Scone".into()]
|
/// vec!["Apple Pie".into(), "Orange Scone".into()]
|
||||||
/// )]);
|
/// )]);
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::{EntityTrait, QuerySelect, RelationDef, Select};
|
use crate::{
|
||||||
use sea_query::JoinType;
|
join_tbl_on_condition, unpack_table_ref, EntityTrait, QuerySelect, RelationDef, Select,
|
||||||
|
};
|
||||||
|
use sea_query::{Alias, IntoIden, JoinType, SeaRc};
|
||||||
|
|
||||||
pub type LinkDef = RelationDef;
|
pub type LinkDef = RelationDef;
|
||||||
|
|
||||||
@ -12,8 +14,20 @@ pub trait Linked {
|
|||||||
|
|
||||||
fn find_linked(&self) -> Select<Self::ToEntity> {
|
fn find_linked(&self) -> Select<Self::ToEntity> {
|
||||||
let mut select = Select::new();
|
let mut select = Select::new();
|
||||||
for rel in self.link().into_iter().rev() {
|
for (i, rel) in self.link().into_iter().rev().enumerate() {
|
||||||
select = select.join_rev(JoinType::InnerJoin, rel);
|
let from_tbl = Alias::new(&format!("r{}", i)).into_iden();
|
||||||
|
let to_tbl = if i > 0 {
|
||||||
|
Alias::new(&format!("r{}", i - 1)).into_iden()
|
||||||
|
} else {
|
||||||
|
unpack_table_ref(&rel.to_tbl)
|
||||||
|
};
|
||||||
|
|
||||||
|
select.query().join_as(
|
||||||
|
JoinType::InnerJoin,
|
||||||
|
unpack_table_ref(&rel.from_tbl),
|
||||||
|
SeaRc::clone(&from_tbl),
|
||||||
|
join_tbl_on_condition(from_tbl, to_tbl, rel.from_col, rel.to_col),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
select
|
select
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,8 @@ pub trait ModelTrait: Clone + Send + Debug {
|
|||||||
where
|
where
|
||||||
L: Linked<FromEntity = Self::Entity>,
|
L: Linked<FromEntity = Self::Entity>,
|
||||||
{
|
{
|
||||||
l.find_linked().belongs_to(self)
|
let tbl_alias = &format!("r{}", l.link().len() - 1);
|
||||||
|
l.find_linked().belongs_to_tbl_alias(self, tbl_alias)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::*, ActiveModelTrait, DatabaseConnection, EntityTrait, Insert, PrimaryKeyTrait,
|
error::*, ActiveModelTrait, DatabaseConnection, DbBackend, EntityTrait, Insert, PrimaryKeyTrait,
|
||||||
Statement, TryFromU64,
|
Statement, TryFromU64,
|
||||||
};
|
};
|
||||||
use sea_query::InsertStatement;
|
use sea_query::InsertStatement;
|
||||||
@ -38,8 +38,7 @@ where
|
|||||||
// TODO: extract primary key's value from query
|
// TODO: extract primary key's value from query
|
||||||
// so that self is dropped before entering await
|
// so that self is dropped before entering await
|
||||||
let mut query = self.query;
|
let mut query = self.query;
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
if db.get_database_backend() == DbBackend::Postgres {
|
||||||
if let DatabaseConnection::SqlxPostgresPoolConnection(_) = db {
|
|
||||||
use crate::{sea_query::Query, Iterable};
|
use crate::{sea_query::Query, Iterable};
|
||||||
if <A::Entity as EntityTrait>::PrimaryKey::iter().count() > 0 {
|
if <A::Entity as EntityTrait>::PrimaryKey::iter().count() > 0 {
|
||||||
query.returning(
|
query.returning(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{error::*, DatabaseConnection, SelectorTrait};
|
use crate::{error::*, DatabaseConnection, DbBackend, SelectorTrait};
|
||||||
use async_stream::stream;
|
use async_stream::stream;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use sea_query::{Alias, Expr, SelectStatement};
|
use sea_query::{Alias, Expr, SelectStatement};
|
||||||
@ -63,11 +63,8 @@ where
|
|||||||
Some(res) => res,
|
Some(res) => res,
|
||||||
None => return Ok(0),
|
None => return Ok(0),
|
||||||
};
|
};
|
||||||
let num_items = match self.db {
|
let num_items = match builder {
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
DbBackend::Postgres => result.try_get::<i64>("", "num_items")? as usize,
|
||||||
DatabaseConnection::SqlxPostgresPoolConnection(_) => {
|
|
||||||
result.try_get::<i64>("", "num_items")? as usize
|
|
||||||
}
|
|
||||||
_ => result.try_get::<i32>("", "num_items")? as usize,
|
_ => result.try_get::<i32>("", "num_items")? as usize,
|
||||||
};
|
};
|
||||||
Ok(num_items)
|
Ok(num_items)
|
||||||
@ -192,7 +189,7 @@ mod tests {
|
|||||||
(db, vec![page1, page2, page3])
|
(db, vec![page1, page2, page3])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_num_items() -> (DatabaseConnection, i32) {
|
fn setup_num_items() -> (DatabaseConnection, i64) {
|
||||||
let num_items = 3;
|
let num_items = 3;
|
||||||
let db = MockDatabase::new(DbBackend::Postgres)
|
let db = MockDatabase::new(DbBackend::Postgres)
|
||||||
.append_query_results(vec![vec![maplit::btreemap! {
|
.append_query_results(vec![vec![maplit::btreemap! {
|
||||||
|
@ -2,10 +2,11 @@ use crate::{
|
|||||||
ColumnTrait, EntityTrait, Identity, IntoIdentity, IntoSimpleExpr, Iterable, ModelTrait,
|
ColumnTrait, EntityTrait, Identity, IntoIdentity, IntoSimpleExpr, Iterable, ModelTrait,
|
||||||
PrimaryKeyToColumn, RelationDef,
|
PrimaryKeyToColumn, RelationDef,
|
||||||
};
|
};
|
||||||
pub use sea_query::{Condition, ConditionalStatement, DynIden, JoinType, Order, OrderedStatement};
|
|
||||||
use sea_query::{
|
use sea_query::{
|
||||||
Expr, IntoCondition, LockType, SeaRc, SelectExpr, SelectStatement, SimpleExpr, TableRef,
|
Alias, Expr, Iden, IntoCondition, LockType, SeaRc, SelectExpr, SelectStatement, SimpleExpr,
|
||||||
|
TableRef,
|
||||||
};
|
};
|
||||||
|
pub use sea_query::{Condition, ConditionalStatement, DynIden, JoinType, Order, OrderedStatement};
|
||||||
|
|
||||||
// LINT: when the column does not appear in tables selected from
|
// LINT: when the column does not appear in tables selected from
|
||||||
// LINT: when there is a group by clause, but some columns don't have aggregate functions
|
// LINT: when there is a group by clause, but some columns don't have aggregate functions
|
||||||
@ -287,14 +288,35 @@ pub trait QueryFilter: Sized {
|
|||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn belongs_to_tbl_alias<M>(mut self, model: &M, tbl_alias: &str) -> Self
|
||||||
|
where
|
||||||
|
M: ModelTrait,
|
||||||
|
{
|
||||||
|
for key in <M::Entity as EntityTrait>::PrimaryKey::iter() {
|
||||||
|
let col = key.into_column();
|
||||||
|
let expr = Expr::tbl(Alias::new(tbl_alias), col).eq(model.get(col));
|
||||||
|
self = self.filter(expr);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_condition(rel: RelationDef) -> SimpleExpr {
|
pub(crate) fn join_condition(rel: RelationDef) -> SimpleExpr {
|
||||||
let from_tbl = unpack_table_ref(&rel.from_tbl);
|
let from_tbl = unpack_table_ref(&rel.from_tbl);
|
||||||
let to_tbl = unpack_table_ref(&rel.to_tbl);
|
let to_tbl = unpack_table_ref(&rel.to_tbl);
|
||||||
let owner_keys = rel.from_col;
|
let owner_keys = rel.from_col;
|
||||||
let foreign_keys = rel.to_col;
|
let foreign_keys = rel.to_col;
|
||||||
|
|
||||||
|
join_tbl_on_condition(from_tbl, to_tbl, owner_keys, foreign_keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn join_tbl_on_condition(
|
||||||
|
from_tbl: SeaRc<dyn Iden>,
|
||||||
|
to_tbl: SeaRc<dyn Iden>,
|
||||||
|
owner_keys: Identity,
|
||||||
|
foreign_keys: Identity,
|
||||||
|
) -> SimpleExpr {
|
||||||
match (owner_keys, foreign_keys) {
|
match (owner_keys, foreign_keys) {
|
||||||
(Identity::Unary(o1), Identity::Unary(f1)) => {
|
(Identity::Unary(o1), Identity::Unary(f1)) => {
|
||||||
Expr::tbl(SeaRc::clone(&from_tbl), o1).equals(SeaRc::clone(&to_tbl), f1)
|
Expr::tbl(SeaRc::clone(&from_tbl), o1).equals(SeaRc::clone(&to_tbl), f1)
|
||||||
|
@ -74,8 +74,9 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::tests_cfg::{cake, cake_filling, cake_filling_price, filling, fruit};
|
use crate::tests_cfg::{cake, cake_filling, cake_filling_price, entity_linked, filling, fruit};
|
||||||
use crate::{ColumnTrait, DbBackend, EntityTrait, ModelTrait, QueryFilter, QueryTrait};
|
use crate::{ColumnTrait, DbBackend, EntityTrait, ModelTrait, QueryFilter, QueryTrait};
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn join_1() {
|
fn join_1() {
|
||||||
@ -188,7 +189,7 @@ mod tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
find_filling.build(DbBackend::MySql).to_string(),
|
find_filling.build(DbBackend::MySql).to_string(),
|
||||||
[
|
[
|
||||||
"SELECT `filling`.`id`, `filling`.`name` FROM `filling`",
|
"SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id` FROM `filling`",
|
||||||
"INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
|
"INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
|
||||||
"INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id`",
|
"INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id`",
|
||||||
]
|
]
|
||||||
@ -243,15 +244,15 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cake_model
|
cake_model
|
||||||
.find_linked(cake::CakeToFilling)
|
.find_linked(entity_linked::CakeToFilling)
|
||||||
.build(DbBackend::MySql)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
r#"SELECT `filling`.`id`, `filling`.`name`"#,
|
r#"SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id`"#,
|
||||||
r#"FROM `filling`"#,
|
r#"FROM `filling`"#,
|
||||||
r#"INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#,
|
r#"INNER JOIN `cake_filling` AS `r0` ON `r0`.`filling_id` = `filling`.`id`"#,
|
||||||
r#"INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id`"#,
|
r#"INNER JOIN `cake` AS `r1` ON `r1`.`id` = `r0`.`cake_id`"#,
|
||||||
r#"WHERE `cake`.`id` = 12"#,
|
r#"WHERE `r1`.`id` = 12"#,
|
||||||
]
|
]
|
||||||
.join(" ")
|
.join(" ")
|
||||||
);
|
);
|
||||||
@ -259,14 +260,38 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn join_11() {
|
fn join_11() {
|
||||||
|
let cake_model = cake::Model {
|
||||||
|
id: 18,
|
||||||
|
name: "".to_owned(),
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
cake_model
|
||||||
|
.find_linked(entity_linked::CakeToFillingVendor)
|
||||||
|
.build(DbBackend::MySql)
|
||||||
|
.to_string(),
|
||||||
|
[
|
||||||
|
r#"SELECT `vendor`.`id`, `vendor`.`name`"#,
|
||||||
|
r#"FROM `vendor`"#,
|
||||||
|
r#"INNER JOIN `filling` AS `r0` ON `r0`.`vendor_id` = `vendor`.`id`"#,
|
||||||
|
r#"INNER JOIN `cake_filling` AS `r1` ON `r1`.`filling_id` = `r0`.`id`"#,
|
||||||
|
r#"INNER JOIN `cake` AS `r2` ON `r2`.`id` = `r1`.`cake_id`"#,
|
||||||
|
r#"WHERE `r2`.`id` = 18"#,
|
||||||
|
]
|
||||||
|
.join(" ")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn join_12() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cake::Entity::find()
|
cake::Entity::find()
|
||||||
.find_also_linked(cake::CakeToFilling)
|
.find_also_linked(entity_linked::CakeToFilling)
|
||||||
.build(DbBackend::MySql)
|
.build(DbBackend::MySql)
|
||||||
.to_string(),
|
.to_string(),
|
||||||
[
|
[
|
||||||
r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
|
r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
|
||||||
r#"`filling`.`id` AS `B_id`, `filling`.`name` AS `B_name`"#,
|
r#"`filling`.`id` AS `B_id`, `filling`.`name` AS `B_name`, `filling`.`vendor_id` AS `B_vendor_id`"#,
|
||||||
r#"FROM `cake`"#,
|
r#"FROM `cake`"#,
|
||||||
r#"LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`"#,
|
r#"LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`"#,
|
||||||
r#"LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#,
|
r#"LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#,
|
||||||
@ -274,4 +299,23 @@ mod tests {
|
|||||||
.join(" ")
|
.join(" ")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn join_13() {
|
||||||
|
assert_eq!(
|
||||||
|
cake::Entity::find()
|
||||||
|
.find_also_linked(entity_linked::CakeToFillingVendor)
|
||||||
|
.build(DbBackend::MySql)
|
||||||
|
.to_string(),
|
||||||
|
[
|
||||||
|
r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
|
||||||
|
r#"`vendor`.`id` AS `B_id`, `vendor`.`name` AS `B_name`"#,
|
||||||
|
r#"FROM `cake`"#,
|
||||||
|
r#"LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`"#,
|
||||||
|
r#"LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`"#,
|
||||||
|
r#"LEFT JOIN `vendor` ON `filling`.`vendor_id` = `vendor`.`id`"#,
|
||||||
|
]
|
||||||
|
.join(" ")
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,20 +31,4 @@ impl Related<super::filling::Entity> for Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CakeToFilling;
|
|
||||||
|
|
||||||
impl Linked for CakeToFilling {
|
|
||||||
type FromEntity = Entity;
|
|
||||||
|
|
||||||
type ToEntity = super::filling::Entity;
|
|
||||||
|
|
||||||
fn link(&self) -> Vec<RelationDef> {
|
|
||||||
vec![
|
|
||||||
super::cake_filling::Relation::Cake.def().rev(),
|
|
||||||
super::cake_filling::Relation::Filling.def(),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
@ -75,20 +75,4 @@ impl Related<super::filling::Entity> for Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct CakeToFilling;
|
|
||||||
|
|
||||||
impl Linked for CakeToFilling {
|
|
||||||
type FromEntity = Entity;
|
|
||||||
|
|
||||||
type ToEntity = super::filling::Entity;
|
|
||||||
|
|
||||||
fn link(&self) -> Vec<RelationDef> {
|
|
||||||
vec![
|
|
||||||
super::cake_filling::Relation::Cake.def().rev(),
|
|
||||||
super::cake_filling::Relation::Filling.def(),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
34
src/tests_cfg/entity_linked.rs
Normal file
34
src/tests_cfg/entity_linked.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CakeToFilling;
|
||||||
|
|
||||||
|
impl Linked for CakeToFilling {
|
||||||
|
type FromEntity = super::cake::Entity;
|
||||||
|
|
||||||
|
type ToEntity = super::filling::Entity;
|
||||||
|
|
||||||
|
fn link(&self) -> Vec<RelationDef> {
|
||||||
|
vec![
|
||||||
|
super::cake_filling::Relation::Cake.def().rev(),
|
||||||
|
super::cake_filling::Relation::Filling.def(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CakeToFillingVendor;
|
||||||
|
|
||||||
|
impl Linked for CakeToFillingVendor {
|
||||||
|
type FromEntity = super::cake::Entity;
|
||||||
|
|
||||||
|
type ToEntity = super::vendor::Entity;
|
||||||
|
|
||||||
|
fn link(&self) -> Vec<RelationDef> {
|
||||||
|
vec![
|
||||||
|
super::cake_filling::Relation::Cake.def().rev(),
|
||||||
|
super::cake_filling::Relation::Filling.def(),
|
||||||
|
super::filling::Relation::Vendor.def(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ pub struct Entity;
|
|||||||
pub struct Model {
|
pub struct Model {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub vendor_id: Option<i32>,
|
||||||
#[sea_orm(ignore)]
|
#[sea_orm(ignore)]
|
||||||
pub ignored_attr: i32,
|
pub ignored_attr: i32,
|
||||||
}
|
}
|
||||||
@ -18,6 +19,7 @@ pub struct Model {
|
|||||||
pub enum Column {
|
pub enum Column {
|
||||||
Id,
|
Id,
|
||||||
Name,
|
Name,
|
||||||
|
VendorId,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, customize each column names here.
|
// Then, customize each column names here.
|
||||||
@ -46,7 +48,9 @@ impl PrimaryKeyTrait for PrimaryKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
pub enum Relation {}
|
pub enum Relation {
|
||||||
|
Vendor,
|
||||||
|
}
|
||||||
|
|
||||||
impl ColumnTrait for Column {
|
impl ColumnTrait for Column {
|
||||||
type EntityName = Entity;
|
type EntityName = Entity;
|
||||||
@ -55,13 +59,19 @@ impl ColumnTrait for Column {
|
|||||||
match self {
|
match self {
|
||||||
Self::Id => ColumnType::Integer.def(),
|
Self::Id => ColumnType::Integer.def(),
|
||||||
Self::Name => ColumnType::String(None).def(),
|
Self::Name => ColumnType::String(None).def(),
|
||||||
|
Self::VendorId => ColumnType::Integer.def().nullable(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RelationTrait for Relation {
|
impl RelationTrait for Relation {
|
||||||
fn def(&self) -> RelationDef {
|
fn def(&self) -> RelationDef {
|
||||||
panic!()
|
match self {
|
||||||
|
Self::Vendor => Entity::belongs_to(super::vendor::Entity)
|
||||||
|
.from(Column::VendorId)
|
||||||
|
.to(super::vendor::Column::Id)
|
||||||
|
.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,10 @@ pub mod cake;
|
|||||||
pub mod cake_expanded;
|
pub mod cake_expanded;
|
||||||
pub mod cake_filling;
|
pub mod cake_filling;
|
||||||
pub mod cake_filling_price;
|
pub mod cake_filling_price;
|
||||||
|
pub mod entity_linked;
|
||||||
pub mod filling;
|
pub mod filling;
|
||||||
pub mod fruit;
|
pub mod fruit;
|
||||||
|
pub mod vendor;
|
||||||
|
|
||||||
pub use cake::Entity as Cake;
|
pub use cake::Entity as Cake;
|
||||||
pub use cake_expanded::Entity as CakeExpanded;
|
pub use cake_expanded::Entity as CakeExpanded;
|
||||||
@ -13,3 +15,4 @@ pub use cake_filling::Entity as CakeFilling;
|
|||||||
pub use cake_filling_price::Entity as CakeFillingPrice;
|
pub use cake_filling_price::Entity as CakeFillingPrice;
|
||||||
pub use filling::Entity as Filling;
|
pub use filling::Entity as Filling;
|
||||||
pub use fruit::Entity as Fruit;
|
pub use fruit::Entity as Fruit;
|
||||||
|
pub use vendor::Entity as Vendor;
|
||||||
|
27
src/tests_cfg/vendor.rs
Normal file
27
src/tests_cfg/vendor.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use crate as sea_orm;
|
||||||
|
use crate::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "vendor")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Related<super::filling::Entity> for Entity {
|
||||||
|
fn to() -> RelationDef {
|
||||||
|
super::filling::Relation::Vendor.def()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
@ -708,6 +708,26 @@ pub async fn linked() -> Result<(), DbErr> {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let baker_bob = Baker::find()
|
||||||
|
.filter(baker::Column::Id.eq(1))
|
||||||
|
.one(&ctx.db)
|
||||||
|
.await?
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let baker_bob_customers = baker_bob
|
||||||
|
.find_linked(baker::BakedForCustomer)
|
||||||
|
.all(&ctx.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
baker_bob_customers,
|
||||||
|
vec![customer::Model {
|
||||||
|
id: 2,
|
||||||
|
name: "Kara".to_owned(),
|
||||||
|
notes: Some("Loves all cakes".to_owned()),
|
||||||
|
}]
|
||||||
|
);
|
||||||
|
|
||||||
ctx.delete().await;
|
ctx.delete().await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user