diff --git a/src/executor/select.rs b/src/executor/select.rs index d4d5830f..b15c0c4b 100644 --- a/src/executor/select.rs +++ b/src/executor/select.rs @@ -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)> { + 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 ::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::().one(db).await } - pub async fn all(self, db: &DatabaseConnection) -> Result, QueryErr> { - self.into_model::().all(db).await + pub async fn all( + self, + db: &DatabaseConnection, + ) -> Result)>, QueryErr> { + let rows = self.into_model::().all(db).await?; + Ok(Self::parse_query_result(rows)) } } diff --git a/src/query/combine.rs b/src/query/combine.rs index 2cde583f..50f000d4 100644 --- a/src/query/combine.rs +++ b/src/query/combine.rs @@ -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 ::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(" ") ); }