Add PaginatorTrait and CountTrait

This commit is contained in:
jasper 2021-11-09 21:21:42 +08:00
parent 03d90d8630
commit 23498892b0
3 changed files with 86 additions and 60 deletions

View File

@ -1,4 +1,4 @@
use crate::{error::*, ConnectionTrait, DbBackend, SelectorTrait};
use crate::{ConnectionTrait, DbBackend, EntityTrait, FromQueryResult, Select, SelectModel, SelectTwo, SelectTwoModel, Selector, SelectorTrait, error::*};
use async_stream::stream;
use futures::Stream;
use sea_query::{Alias, Expr, SelectStatement};
@ -95,7 +95,7 @@ where
///
/// ```rust
/// # #[cfg(feature = "mock")]
/// # use sea_orm::{error::*, MockDatabase, DbBackend};
/// # use sea_orm::{error::*, MockDatabase, DbBackend, PaginatorTrait};
/// # let owned_db = MockDatabase::new(DbBackend::Postgres).into_connection();
/// # let db = &owned_db;
/// # let _: Result<(), DbErr> = smol::block_on(async {
@ -123,7 +123,7 @@ where
///
/// ```rust
/// # #[cfg(feature = "mock")]
/// # use sea_orm::{error::*, MockDatabase, DbBackend};
/// # use sea_orm::{error::*, MockDatabase, DbBackend, PaginatorTrait};
/// # let owned_db = MockDatabase::new(DbBackend::Postgres).into_connection();
/// # let db = &owned_db;
/// # let _: Result<(), DbErr> = smol::block_on(async {
@ -155,12 +155,92 @@ where
}
}
/// Used to enforce constraints on any type that wants to paginate results
pub trait PaginatorTrait<'db, C>
where
C: ConnectionTrait<'db>,
{
/// Select operation
type Selector: SelectorTrait + 'db;
/// Paginate the result of a select operation.
fn paginate(self, db: &'db C, page_size: usize) -> Paginator<'db, C, Self::Selector>;
}
impl<'db, C, S> PaginatorTrait<'db, C> for Selector<S>
where
C: ConnectionTrait<'db>,
S: SelectorTrait + 'db,
{
type Selector = S;
fn paginate(self, db: &'db C, page_size: usize) -> Paginator<'db, C, S> {
Paginator {
query: self.query,
page: 0,
page_size,
db,
selector: PhantomData,
}
}
}
impl<'db, C, M, E> PaginatorTrait<'db, C> for Select<E>
where
C: ConnectionTrait<'db>,
E: EntityTrait<Model = M>,
M: FromQueryResult + Sized + 'db,
{
type Selector = SelectModel<M>;
fn paginate(self, db: &'db C, page_size: usize) -> Paginator<'db, C, Self::Selector> {
self.into_model().paginate(db, page_size)
}
}
impl<'db, C, M, N, E, F> PaginatorTrait<'db, C> for SelectTwo<E, F>
where
C: ConnectionTrait<'db>,
E: EntityTrait<Model = M>,
F: EntityTrait<Model = N>,
M: FromQueryResult + Sized + 'db,
N: FromQueryResult + Sized + 'db,
{
type Selector = SelectTwoModel<M, N>;
fn paginate(self, db: &'db C, page_size: usize) -> Paginator<'db, C, Self::Selector> {
self.into_model().paginate(db, page_size)
}
}
/// Used to enforce constraints on any type that wants to count results using pagination.
#[async_trait::async_trait]
pub trait CountTrait<'db, C>: PaginatorTrait<'db, C>
where
C: ConnectionTrait<'db>,
{
/// Perform a count on the paginated results
async fn count(self, db: &'db C) -> Result<usize, DbErr>;
}
#[async_trait::async_trait]
impl<'db, C, P, S> CountTrait<'db, C> for P
where
C: ConnectionTrait<'db>,
P: PaginatorTrait<'db, C, Selector = S> + Send,
S: SelectorTrait + Send + Sync + 'db
{
async fn count(self, db:&'db C) -> Result<usize, DbErr> {
self.paginate(db, 1).num_items().await
}
}
#[cfg(test)]
#[cfg(feature = "mock")]
mod tests {
use crate::entity::prelude::*;
use crate::{tests_cfg::*, ConnectionTrait};
use crate::{DatabaseConnection, DbBackend, MockDatabase, Transaction};
use super::*;
use futures::TryStreamExt;
use sea_query::{Alias, Expr, SelectStatement, Value};

View File

@ -1,6 +1,6 @@
use crate::{
error::*, ConnectionTrait, EntityTrait, FromQueryResult, IdenStatic, Iterable, ModelTrait,
Paginator, PrimaryKeyToColumn, QueryResult, Select, SelectA, SelectB, SelectTwo, SelectTwoMany,
PrimaryKeyToColumn, QueryResult, Select, SelectA, SelectB, SelectTwo, SelectTwoMany,
Statement, TryGetableMany,
};
use futures::{Stream, TryStreamExt};
@ -17,7 +17,7 @@ pub struct Selector<S>
where
S: SelectorTrait,
{
query: SelectStatement,
pub(crate) query: SelectStatement,
selector: S,
}
@ -276,26 +276,6 @@ where
{
self.into_model().stream(db).await
}
/// Paginate the results of a SELECT operation on a Model
pub fn paginate<'a, C>(
self,
db: &'a C,
page_size: usize,
) -> Paginator<'a, C, SelectModel<E::Model>>
where
C: ConnectionTrait<'a>,
{
self.into_model().paginate(db, page_size)
}
/// Perform a `COUNT` operation on a items on a Model using pagination
pub async fn count<'a, C>(self, db: &'a C) -> Result<usize, DbErr>
where
C: ConnectionTrait<'a>,
{
self.paginate(db, 1).num_items().await
}
}
impl<E, F> SelectTwo<E, F>
@ -350,26 +330,6 @@ where
{
self.into_model().stream(db).await
}
/// Paginate the results of a select operation on two models
pub fn paginate<'a, C>(
self,
db: &'a C,
page_size: usize,
) -> Paginator<'a, C, SelectTwoModel<E::Model, F::Model>>
where
C: ConnectionTrait<'a>,
{
self.into_model().paginate(db, page_size)
}
/// Perform a count on the paginated results
pub async fn count<'a, C>(self, db: &'a C) -> Result<usize, DbErr>
where
C: ConnectionTrait<'a>,
{
self.paginate(db, 1).num_items().await
}
}
impl<E, F> SelectTwoMany<E, F>
@ -499,20 +459,6 @@ where
futures::future::ready(S::from_raw_query_result(row))
})))
}
/// Paginate the result of a select operation on a Model
pub fn paginate<'a, C>(self, db: &'a C, page_size: usize) -> Paginator<'a, C, S>
where
C: ConnectionTrait<'a>,
{
Paginator {
query: self.query,
page: 0,
page_size,
db,
selector: PhantomData,
}
}
}
impl<S> SelectorRaw<S>

View File

@ -1,6 +1,6 @@
pub use super::*;
use rust_decimal_macros::dec;
use sea_orm::DbErr;
use sea_orm::{DbErr, CountTrait};
use uuid::Uuid;
pub async fn test_update_cake(db: &DbConn) {