diff --git a/src/connector/select.rs b/src/connector/select.rs index e3ea6fb3..3aa50359 100644 --- a/src/connector/select.rs +++ b/src/connector/select.rs @@ -1,22 +1,79 @@ -use crate::{Connection, Database, EntityTrait, ModelTrait, QueryErr, Select}; +use crate::{Connection, Database, EntityTrait, FromQueryResult, QueryErr, Select, Statement}; +use sea_query::{QueryBuilder, SelectStatement}; +use std::marker::PhantomData; + +#[derive(Clone, Debug)] +pub struct ModelSelect +where + M: FromQueryResult, +{ + query: SelectStatement, + model: PhantomData, +} impl Select where E: EntityTrait, { - pub async fn one(mut self, db: &Database) -> Result { - let builder = db.get_query_builder_backend(); - self.query().limit(1); - let row = db.get_connection().query_one(self.build(builder)).await?; - Ok(::Model::from_query_result(row)?) + pub fn into_model(self) -> ModelSelect + where + M: FromQueryResult, + { + ModelSelect { + query: self.query, + model: PhantomData, + } + } + + pub async fn one(self, db: &Database) -> Result { + self.into_model::().one(db).await } pub async fn all(self, db: &Database) -> Result, QueryErr> { + self.into_model::().all(db).await + } +} + +impl ModelSelect +where + M: FromQueryResult, +{ + /// Get a mutable ref to the query builder + pub fn query(&mut self) -> &mut SelectStatement { + &mut self.query + } + + /// Get an immutable ref to the query builder + pub fn as_query(&self) -> &SelectStatement { + &self.query + } + + /// Take ownership of the query builder + pub fn into_query(self) -> SelectStatement { + self.query + } + + /// Build the query as [`Statement`] + pub fn build(&self, builder: B) -> Statement + where + B: QueryBuilder, + { + self.as_query().build(builder).into() + } + + pub async fn one(mut self, db: &Database) -> Result { + let builder = db.get_query_builder_backend(); + self.query().limit(1); + let row = db.get_connection().query_one(self.build(builder)).await?; + Ok(M::from_query_result(row)?) + } + + pub async fn all(self, db: &Database) -> Result, QueryErr> { let builder = db.get_query_builder_backend(); let rows = db.get_connection().query_all(self.build(builder)).await?; let mut models = Vec::new(); for row in rows.into_iter() { - models.push(::Model::from_query_result(row)?); + models.push(M::from_query_result(row)?); } Ok(models) } diff --git a/src/entity/model.rs b/src/entity/model.rs index f86a63d8..328385c2 100644 --- a/src/entity/model.rs +++ b/src/entity/model.rs @@ -11,5 +11,20 @@ pub trait ModelTrait: Clone + Debug + Default { fn from_query_result(row: QueryResult) -> Result where - Self: std::marker::Sized; + Self: Sized; +} + +pub trait FromQueryResult { + fn from_query_result(row: QueryResult) -> Result + where + Self: Sized; +} + +impl FromQueryResult for M +where + M: ModelTrait + Sized, +{ + fn from_query_result(row: QueryResult) -> Result { + ::from_query_result(row) + } } diff --git a/src/query/select.rs b/src/query/select.rs index 039df62b..4dd0439b 100644 --- a/src/query/select.rs +++ b/src/query/select.rs @@ -13,8 +13,8 @@ pub struct Select where E: EntityTrait, { - query: SelectStatement, - entity: PhantomData, + pub(crate) query: SelectStatement, + pub(crate) entity: PhantomData, } impl Select @@ -162,7 +162,7 @@ where &mut self.query } - /// Get a immutable ref to the query builder + /// Get an immutable ref to the query builder pub fn as_query(&self) -> &SelectStatement { &self.query }