Select to many

This commit is contained in:
Billy Chan 2021-06-23 15:00:20 +08:00 committed by Chris Tsang
parent 0afd226dbe
commit 19c0b0c35d
2 changed files with 49 additions and 8 deletions

View File

@ -1,6 +1,6 @@
use crate::{
query::combine, DatabaseConnection, EntityTrait, FromQueryResult, JsonValue, Paginator,
QueryErr, QueryResult, Select, SelectTwo, TypeErr,
query::combine, DatabaseConnection, EntityTrait, FromQueryResult, Iterable, JsonValue,
ModelTrait, Paginator, PrimaryKeyToColumn, QueryErr, QueryResult, Select, SelectTwo, TypeErr,
};
use sea_query::SelectStatement;
use std::marker::PhantomData;
@ -125,6 +125,33 @@ where
}
}
fn parse_query_result(rows: Vec<(E::Model, F::Model)>) -> Vec<(E::Model, Vec<F::Model>)> {
let mut acc = Vec::new();
for (l_model, r_model) in rows {
if acc.is_empty() {
acc.push((l_model, vec![r_model]));
continue;
}
let (last_l, last_r) = acc.last_mut().unwrap();
let mut l_equal = true;
for pk_col in <E::PrimaryKey as Iterable>::iter() {
let col = pk_col.into_column();
let curr_val = l_model.get(col);
let last_val = last_l.get(col);
if !curr_val.eq(&last_val) {
l_equal = false;
break;
}
}
if l_equal {
last_r.push(r_model);
} else {
acc.push((l_model, vec![r_model]));
}
}
acc
}
pub async fn one(
self,
db: &DatabaseConnection,
@ -132,8 +159,12 @@ where
self.into_model::<E::Model, F::Model>().one(db).await
}
pub async fn all(self, db: &DatabaseConnection) -> Result<Vec<(E::Model, F::Model)>, QueryErr> {
self.into_model::<E::Model, F::Model>().all(db).await
pub async fn all(
self,
db: &DatabaseConnection,
) -> Result<Vec<(E::Model, Vec<F::Model>)>, QueryErr> {
let rows = self.into_model::<E::Model, F::Model>().all(db).await?;
Ok(Self::parse_query_result(rows))
}
}

View File

@ -1,7 +1,7 @@
use crate::{EntityTrait, IntoSimpleExpr, Iterable, QueryTrait, Select, SelectTwo};
use core::marker::PhantomData;
pub use sea_query::JoinType;
use sea_query::{Alias, ColumnRef, Iden, SeaRc, SelectExpr, SelectStatement, SimpleExpr};
use sea_query::{Alias, ColumnRef, Iden, Order, SeaRc, SelectExpr, SelectStatement, SimpleExpr};
pub const SELECT_A: &str = "A_";
pub const SELECT_B: &str = "B_";
@ -48,11 +48,12 @@ where
F: EntityTrait,
{
pub(crate) fn new(query: SelectStatement) -> Self {
let myself = Self {
Self {
query,
entity: PhantomData,
};
myself.prepare_select()
}
.prepare_select()
.prepare_order_by()
}
fn prepare_select(mut self) -> Self {
@ -65,6 +66,13 @@ where
}
self
}
fn prepare_order_by(mut self) -> Self {
for col in <E::PrimaryKey as Iterable>::iter() {
self.query.order_by((E::default(), col), Order::Asc);
}
self
}
}
#[cfg(test)]
@ -97,6 +105,7 @@ mod tests {
"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,",
"`fruit`.`id` AS `B_id`, `fruit`.`name` AS `B_name`, `fruit`.`cake_id` AS `B_cake_id`",
"FROM `cake` LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`",
"ORDER BY `cake`.`id` ASC",
].join(" ")
);
}
@ -116,6 +125,7 @@ mod tests {
"`fruit`.`id` AS `B_id`, `fruit`.`name` AS `B_name`, `fruit`.`cake_id` AS `B_cake_id`",
"FROM `cake` LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`",
"WHERE `cake`.`id` = 1 AND `fruit`.`id` = 2",
"ORDER BY `cake`.`id` ASC",
].join(" ")
);
}