count() on Select
This commit is contained in:
parent
c018e45c3c
commit
56763a8718
@ -18,6 +18,8 @@ where
|
|||||||
pub(crate) selector: PhantomData<S>,
|
pub(crate) selector: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LINT: warn if paginator is used without an order by clause
|
||||||
|
|
||||||
impl<'db, S> Paginator<'db, S>
|
impl<'db, S> Paginator<'db, S>
|
||||||
where
|
where
|
||||||
S: SelectorTrait + 'db,
|
S: SelectorTrait + 'db,
|
||||||
@ -46,12 +48,12 @@ where
|
|||||||
self.fetch_page(self.page).await
|
self.fetch_page(self.page).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the total number of pages
|
/// Get the total number of items
|
||||||
pub async fn num_pages(&self) -> Result<usize, DbErr> {
|
pub async fn num_items(&self) -> Result<usize, DbErr> {
|
||||||
let builder = self.db.get_database_backend();
|
let builder = self.db.get_database_backend();
|
||||||
let stmt = builder.build(
|
let stmt = builder.build(
|
||||||
SelectStatement::new()
|
SelectStatement::new()
|
||||||
.expr(Expr::cust("COUNT(*) AS num_rows"))
|
.expr(Expr::cust("COUNT(*) AS num_items"))
|
||||||
.from_subquery(
|
.from_subquery(
|
||||||
self.query.clone().reset_limit().reset_offset().to_owned(),
|
self.query.clone().reset_limit().reset_offset().to_owned(),
|
||||||
Alias::new("sub_query"),
|
Alias::new("sub_query"),
|
||||||
@ -61,8 +63,14 @@ where
|
|||||||
Some(res) => res,
|
Some(res) => res,
|
||||||
None => return Ok(0),
|
None => return Ok(0),
|
||||||
};
|
};
|
||||||
let num_rows = result.try_get::<i32>("", "num_rows")? as usize;
|
let num_items = result.try_get::<i32>("", "num_items")? as usize;
|
||||||
let num_pages = (num_rows / self.page_size) + (num_rows % self.page_size > 0) as usize;
|
Ok(num_items)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the total number of pages
|
||||||
|
pub async fn num_pages(&self) -> Result<usize, DbErr> {
|
||||||
|
let num_items = self.num_items().await?;
|
||||||
|
let num_pages = (num_items / self.page_size) + (num_items % self.page_size > 0) as usize;
|
||||||
Ok(num_pages)
|
Ok(num_pages)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,15 +144,15 @@ mod tests {
|
|||||||
(db, vec![page1, page2, page3])
|
(db, vec![page1, page2, page3])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_num_rows() -> (DatabaseConnection, i32) {
|
fn setup_num_items() -> (DatabaseConnection, i32) {
|
||||||
let num_rows = 3;
|
let num_items = 3;
|
||||||
let db = MockDatabase::new(DatabaseBackend::Postgres)
|
let db = MockDatabase::new(DatabaseBackend::Postgres)
|
||||||
.append_query_results(vec![vec![maplit::btreemap! {
|
.append_query_results(vec![vec![maplit::btreemap! {
|
||||||
"num_rows" => Into::<Value>::into(num_rows),
|
"num_items" => Into::<Value>::into(num_items),
|
||||||
}]])
|
}]])
|
||||||
.into_connection();
|
.into_connection();
|
||||||
|
|
||||||
(db, num_rows)
|
(db, num_items)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
@ -213,11 +221,11 @@ mod tests {
|
|||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
async fn num_pages() -> Result<(), DbErr> {
|
async fn num_pages() -> Result<(), DbErr> {
|
||||||
let (db, num_rows) = setup_num_rows();
|
let (db, num_items) = setup_num_items();
|
||||||
|
|
||||||
let num_rows = num_rows as usize;
|
let num_items = num_items as usize;
|
||||||
let page_size = 2_usize;
|
let page_size = 2_usize;
|
||||||
let num_pages = (num_rows / page_size) + (num_rows % page_size > 0) as usize;
|
let num_pages = (num_items / page_size) + (num_items % page_size > 0) as usize;
|
||||||
let paginator = fruit::Entity::find().paginate(&db, page_size);
|
let paginator = fruit::Entity::find().paginate(&db, page_size);
|
||||||
|
|
||||||
assert_eq!(paginator.num_pages().await?, num_pages);
|
assert_eq!(paginator.num_pages().await?, num_pages);
|
||||||
@ -232,7 +240,7 @@ mod tests {
|
|||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let select = SelectStatement::new()
|
let select = SelectStatement::new()
|
||||||
.expr(Expr::cust("COUNT(*) AS num_rows"))
|
.expr(Expr::cust("COUNT(*) AS num_items"))
|
||||||
.from_subquery(sub_query, Alias::new("sub_query"))
|
.from_subquery(sub_query, Alias::new("sub_query"))
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
|
@ -116,6 +116,10 @@ where
|
|||||||
) -> Paginator<'_, SelectModel<E::Model>> {
|
) -> Paginator<'_, SelectModel<E::Model>> {
|
||||||
self.into_model().paginate(db, page_size)
|
self.into_model().paginate(db, page_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn count(self, db: &DatabaseConnection) -> Result<usize, DbErr> {
|
||||||
|
self.paginate(db, 1).num_items().await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, F> SelectTwo<E, F>
|
impl<E, F> SelectTwo<E, F>
|
||||||
@ -155,6 +159,18 @@ where
|
|||||||
) -> Result<Vec<(E::Model, Option<F::Model>)>, DbErr> {
|
) -> Result<Vec<(E::Model, Option<F::Model>)>, DbErr> {
|
||||||
self.into_model().all(db).await
|
self.into_model().all(db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn paginate(
|
||||||
|
self,
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
page_size: usize,
|
||||||
|
) -> Paginator<'_, SelectTwoModel<E::Model, F::Model>> {
|
||||||
|
self.into_model().paginate(db, page_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn count(self, db: &DatabaseConnection) -> Result<usize, DbErr> {
|
||||||
|
self.paginate(db, 1).num_items().await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, F> SelectTwoMany<E, F>
|
impl<E, F> SelectTwoMany<E, F>
|
||||||
@ -195,6 +211,15 @@ where
|
|||||||
let rows = self.into_model().all(db).await?;
|
let rows = self.into_model().all(db).await?;
|
||||||
Ok(consolidate_query_result::<E, F>(rows))
|
Ok(consolidate_query_result::<E, F>(rows))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pub fn paginate()
|
||||||
|
// we could not implement paginate easily, if the number of children for a
|
||||||
|
// parent is larger than one page, then we will end up splitting it in two pages
|
||||||
|
// so the correct way is actually perform query in two stages
|
||||||
|
// paginate the parent model and then populate the children
|
||||||
|
|
||||||
|
// pub fn count()
|
||||||
|
// we should only count the number of items of the parent model
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Selector<S>
|
impl<S> Selector<S>
|
||||||
|
@ -59,6 +59,12 @@ async fn crud_cake(db: &DbConn) -> Result<(), DbErr> {
|
|||||||
println!();
|
println!();
|
||||||
println!("Updated: {:?}", apple);
|
println!("Updated: {:?}", apple);
|
||||||
|
|
||||||
|
let count = cake::Entity::find().count(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Count: {:?}", count);
|
||||||
|
assert_eq!(count, 1);
|
||||||
|
|
||||||
let apple = cake::Entity::find_by_id(1).one(db).await?;
|
let apple = cake::Entity::find_by_id(1).one(db).await?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -80,5 +86,11 @@ async fn crud_cake(db: &DbConn) -> Result<(), DbErr> {
|
|||||||
|
|
||||||
assert_eq!(None, apple);
|
assert_eq!(None, apple);
|
||||||
|
|
||||||
|
let count = cake::Entity::find().count(db).await?;
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("Count: {:?}", count);
|
||||||
|
assert_eq!(count, 0);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user