Join APIs
This commit is contained in:
parent
634b5aca7a
commit
1bec83ff64
@ -105,7 +105,7 @@ async fn count_fruits_by_cake(db: &Database) -> Result<(), QueryErr> {
|
||||
print!("count fruits by cake: ");
|
||||
|
||||
let select = cake::Entity::find()
|
||||
.left_join(cake::Relation::Fruit)
|
||||
.left_join(fruit::Entity)
|
||||
.select_only()
|
||||
.column(cake::Column::Name)
|
||||
.column_as(fruit::Column::Id.count(), "num_of_fruits")
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{EntityTrait, Identity, IntoIdentity, Select};
|
||||
use sea_query::{Iden, IntoIden};
|
||||
use sea_query::{Iden, IntoIden, JoinType};
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -24,7 +24,7 @@ where
|
||||
}
|
||||
|
||||
fn find_related() -> Select<R> {
|
||||
Select::<R>::new().prepare_reverse_join(Self::to())
|
||||
Select::<R>::new().join_rev(JoinType::InnerJoin, Self::to())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
ColumnTrait, EntityTrait, Identity, Iterable, ModelTrait, PrimaryKeyOfModel, Related,
|
||||
RelationDef, RelationTrait, Statement,
|
||||
RelationDef, Statement,
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
use core::marker::PhantomData;
|
||||
@ -67,35 +67,6 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
fn prepare_join(mut self, join: JoinType, rel: RelationDef) -> Self {
|
||||
let own_tbl = E::default().into_iden();
|
||||
let to_tbl = rel.to_tbl.clone();
|
||||
let owner_keys = rel.from_col;
|
||||
let foreign_keys = rel.to_col;
|
||||
let condition = match (owner_keys, foreign_keys) {
|
||||
(Identity::Unary(o1), Identity::Unary(f1)) => {
|
||||
Expr::tbl(Rc::clone(&own_tbl), o1).equals(Rc::clone(&to_tbl), f1)
|
||||
} // _ => panic!("Owner key and foreign key mismatch"),
|
||||
};
|
||||
self.query.join(join, Rc::clone(&to_tbl), condition);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_reverse_join(mut self, rel: RelationDef) -> Self {
|
||||
let from_tbl = rel.from_tbl.clone();
|
||||
let to_tbl = rel.to_tbl.clone();
|
||||
let owner_keys = rel.from_col;
|
||||
let foreign_keys = rel.to_col;
|
||||
let condition = match (owner_keys, foreign_keys) {
|
||||
(Identity::Unary(o1), Identity::Unary(f1)) => {
|
||||
Expr::tbl(Rc::clone(&from_tbl), o1).equals(Rc::clone(&to_tbl), f1)
|
||||
} // _ => panic!("Owner key and foreign key mismatch"),
|
||||
};
|
||||
self.query
|
||||
.join(JoinType::InnerJoin, Rc::clone(&from_tbl), condition);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn select_only(mut self) -> Self {
|
||||
self.query.clear_selects();
|
||||
self
|
||||
@ -243,23 +214,71 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn left_join(self, rel: E::Relation) -> Self {
|
||||
self.prepare_join(JoinType::LeftJoin, E::Relation::def(&rel))
|
||||
/// Join via [`RelationDef`].
|
||||
pub fn join(mut self, join: JoinType, rel: RelationDef) -> Self {
|
||||
let own_tbl = E::default().into_iden();
|
||||
let to_tbl = rel.to_tbl.clone();
|
||||
let owner_keys = rel.from_col;
|
||||
let foreign_keys = rel.to_col;
|
||||
let condition = match (owner_keys, foreign_keys) {
|
||||
(Identity::Unary(o1), Identity::Unary(f1)) => {
|
||||
Expr::tbl(Rc::clone(&own_tbl), o1).equals(Rc::clone(&to_tbl), f1)
|
||||
} // _ => panic!("Owner key and foreign key mismatch"),
|
||||
};
|
||||
self.query.join(join, Rc::clone(&to_tbl), condition);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn right_join(self, rel: E::Relation) -> Self {
|
||||
self.prepare_join(JoinType::RightJoin, E::Relation::def(&rel))
|
||||
/// Join via [`RelationDef`] but in reverse direction.
|
||||
/// Assume when there exist a relation A -> B.
|
||||
/// You can reverse join B <- A.
|
||||
pub fn join_rev(mut self, join: JoinType, rel: RelationDef) -> Self {
|
||||
let from_tbl = rel.from_tbl.clone();
|
||||
let to_tbl = rel.to_tbl.clone();
|
||||
let owner_keys = rel.from_col;
|
||||
let foreign_keys = rel.to_col;
|
||||
let condition = match (owner_keys, foreign_keys) {
|
||||
(Identity::Unary(o1), Identity::Unary(f1)) => {
|
||||
Expr::tbl(Rc::clone(&from_tbl), o1).equals(Rc::clone(&to_tbl), f1)
|
||||
} // _ => panic!("Owner key and foreign key mismatch"),
|
||||
};
|
||||
self.query.join(join, Rc::clone(&from_tbl), condition);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn inner_join(self, rel: E::Relation) -> Self {
|
||||
self.prepare_join(JoinType::InnerJoin, E::Relation::def(&rel))
|
||||
/// Left Join with a Related Entity.
|
||||
pub fn left_join<R>(self, _: R) -> Self
|
||||
where
|
||||
R: EntityTrait,
|
||||
E: Related<R>,
|
||||
{
|
||||
self.join(JoinType::LeftJoin, E::to())
|
||||
}
|
||||
|
||||
pub fn reverse_join<R>(self) -> Self
|
||||
/// Right Join with a Related Entity.
|
||||
pub fn right_join<R>(self, _: R) -> Self
|
||||
where
|
||||
R: EntityTrait,
|
||||
E: Related<R>,
|
||||
{
|
||||
self.join(JoinType::RightJoin, E::to())
|
||||
}
|
||||
|
||||
/// Inner Join with a Related Entity.
|
||||
pub fn inner_join<R>(self, _: R) -> Self
|
||||
where
|
||||
R: EntityTrait,
|
||||
E: Related<R>,
|
||||
{
|
||||
self.join(JoinType::InnerJoin, E::to())
|
||||
}
|
||||
|
||||
/// Join with an Entity Related to me.
|
||||
pub fn reverse_join<R>(self, _: R) -> Self
|
||||
where
|
||||
R: EntityTrait + Related<E>,
|
||||
{
|
||||
self.prepare_reverse_join(R::to())
|
||||
self.join_rev(JoinType::InnerJoin, R::to())
|
||||
}
|
||||
|
||||
/// Get a mutable ref to the query builder
|
||||
@ -296,7 +315,7 @@ mod tests {
|
||||
fn join_1() {
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.left_join(cake::Relation::Fruit)
|
||||
.left_join(fruit::Entity)
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
[
|
||||
@ -311,7 +330,7 @@ mod tests {
|
||||
fn join_2() {
|
||||
assert_eq!(
|
||||
cake::Entity::find()
|
||||
.inner_join(cake::Relation::Fruit)
|
||||
.inner_join(fruit::Entity)
|
||||
.filter(fruit::Column::Name.contains("cherry"))
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
@ -328,7 +347,7 @@ mod tests {
|
||||
fn join_3() {
|
||||
assert_eq!(
|
||||
fruit::Entity::find()
|
||||
.reverse_join::<cake::Entity>()
|
||||
.reverse_join(cake::Entity)
|
||||
.build(MysqlQueryBuilder)
|
||||
.to_string(),
|
||||
[
|
||||
|
Loading…
x
Reference in New Issue
Block a user