Decouple as ModelSelect

This commit is contained in:
Chris Tsang 2021-05-09 23:32:54 +08:00
parent e1504c6743
commit e2c7722d84
3 changed files with 83 additions and 11 deletions

View File

@ -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<M>
where
M: FromQueryResult,
{
query: SelectStatement,
model: PhantomData<M>,
}
impl<E: 'static> Select<E>
where
E: EntityTrait,
{
pub async fn one(mut self, db: &Database) -> Result<E::Model, QueryErr> {
let builder = db.get_query_builder_backend();
self.query().limit(1);
let row = db.get_connection().query_one(self.build(builder)).await?;
Ok(<E as EntityTrait>::Model::from_query_result(row)?)
pub fn into_model<M>(self) -> ModelSelect<M>
where
M: FromQueryResult,
{
ModelSelect {
query: self.query,
model: PhantomData,
}
}
pub async fn one(self, db: &Database) -> Result<E::Model, QueryErr> {
self.into_model::<E::Model>().one(db).await
}
pub async fn all(self, db: &Database) -> Result<Vec<E::Model>, QueryErr> {
self.into_model::<E::Model>().all(db).await
}
}
impl<M> ModelSelect<M>
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<B>(&self, builder: B) -> Statement
where
B: QueryBuilder,
{
self.as_query().build(builder).into()
}
pub async fn one(mut self, db: &Database) -> Result<M, QueryErr> {
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<Vec<M>, 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(<E as EntityTrait>::Model::from_query_result(row)?);
models.push(M::from_query_result(row)?);
}
Ok(models)
}

View File

@ -11,5 +11,20 @@ pub trait ModelTrait: Clone + Debug + Default {
fn from_query_result(row: QueryResult) -> Result<Self, TypeErr>
where
Self: std::marker::Sized;
Self: Sized;
}
pub trait FromQueryResult {
fn from_query_result(row: QueryResult) -> Result<Self, TypeErr>
where
Self: Sized;
}
impl<M> FromQueryResult for M
where
M: ModelTrait + Sized,
{
fn from_query_result(row: QueryResult) -> Result<M, TypeErr> {
<Self as ModelTrait>::from_query_result(row)
}
}

View File

@ -13,8 +13,8 @@ pub struct Select<E: 'static>
where
E: EntityTrait,
{
query: SelectStatement,
entity: PhantomData<E>,
pub(crate) query: SelectStatement,
pub(crate) entity: PhantomData<E>,
}
impl<E: 'static> Select<E>
@ -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
}