Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions sea-orm-sync/src/executor/paginator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,7 @@ where
Some(res) => res,
None => return Ok(0),
};
#[allow(clippy::match_single_binding)]
let num_items = match self.db.get_database_backend() {
_ => result.try_get::<i64>("", "num_items")? as u64,
};
Ok(num_items)
Ok(result.try_get::<i64>("", "num_items")? as u64)
}

/// Get the total number of pages
Expand Down Expand Up @@ -272,12 +268,30 @@ where
/// Paginate the result of a select operation.
fn paginate(self, db: &'db C, page_size: u64) -> Paginator<'db, C, Self::Selector>;

/// Perform a count on the paginated results
/// Count the number of rows this query selects, honoring any `limit` and
/// `offset` set on it.
///
/// This differs from [`Paginator::num_items`], which resets `limit`/`offset`
/// to report the grand total for pagination. `count` wraps the query as-is in
/// a `SELECT COUNT(*) FROM (..)` subquery, so a query with a `limit` counts at
/// most that many rows.
fn count(self, db: &'db C) -> Result<u64, DbErr>
where
Self: Sized,
{
self.paginate(db, 1).num_items()
let paginator = self.paginate(db, 1);
let query = SelectStatement::new()
.expr(Expr::cust("COUNT(*) AS num_items"))
.from_subquery(
paginator.query.clone().clear_order_by().to_owned(),
"sub_query",
)
.to_owned();
let result = match db.query_one(&query)? {
Some(res) => res,
None => return Ok(0),
};
Ok(result.try_get::<i64>("", "num_items")? as u64)
}
}

Expand Down
1 change: 0 additions & 1 deletion sea-orm-sync/src/executor/select_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::{
};
use sea_query::{Expr, SelectStatement};

// TODO: Move count here
/// Helper trait for selectors with convenient methods
pub trait SelectExt {
/// This method is unstable and is only used for internal testing.
Expand Down
7 changes: 6 additions & 1 deletion sea-orm-sync/tests/paginator_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod common;

pub use common::{TestContext, features::*, setup::*};
use pretty_assertions::assert_eq;
use sea_orm::{PaginatorTrait, QueryOrder, Set, entity::prelude::*};
use sea_orm::{PaginatorTrait, QueryOrder, QuerySelect, Set, entity::prelude::*};

#[sea_orm_macros::test]
fn paginator_tests() -> Result<(), DbErr> {
Expand Down Expand Up @@ -145,5 +145,10 @@ pub fn paginator_count(db: &DatabaseConnection) -> Result<(), DbErr> {

assert_eq!(Entity::find().filter(Column::Id.gt(100)).count(db)?, 0);

// `count` honors `limit`/`offset` set on the query, unlike `num_items`.
assert_eq!(Entity::find().limit(3).count(db)?, 3);

assert_eq!(Entity::find().limit(4).offset(8).count(db)?, 2);

Ok(())
}
28 changes: 21 additions & 7 deletions src/executor/paginator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,7 @@ where
Some(res) => res,
None => return Ok(0),
};
#[allow(clippy::match_single_binding)]
let num_items = match self.db.get_database_backend() {
_ => result.try_get::<i64>("", "num_items")? as u64,
};
Ok(num_items)
Ok(result.try_get::<i64>("", "num_items")? as u64)
}

/// Get the total number of pages
Expand Down Expand Up @@ -279,12 +275,30 @@ where
/// Paginate the result of a select operation.
fn paginate(self, db: &'db C, page_size: u64) -> Paginator<'db, C, Self::Selector>;

/// Perform a count on the paginated results
/// Count the number of rows this query selects, honoring any `limit` and
/// `offset` set on it.
///
/// This differs from [`Paginator::num_items`], which resets `limit`/`offset`
/// to report the grand total for pagination. `count` wraps the query as-is in
/// a `SELECT COUNT(*) FROM (..)` subquery, so a query with a `limit` counts at
/// most that many rows.
async fn count(self, db: &'db C) -> Result<u64, DbErr>
where
Self: Send + Sized,
{
self.paginate(db, 1).num_items().await
let paginator = self.paginate(db, 1);
let query = SelectStatement::new()
.expr(Expr::cust("COUNT(*) AS num_items"))
.from_subquery(
paginator.query.clone().clear_order_by().to_owned(),
"sub_query",
)
.to_owned();
let result = match db.query_one(&query).await? {
Some(res) => res,
None => return Ok(0),
};
Ok(result.try_get::<i64>("", "num_items")? as u64)
}
}

Expand Down
1 change: 0 additions & 1 deletion src/executor/select_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::{
};
use sea_query::{Expr, SelectStatement};

// TODO: Move count here
#[async_trait::async_trait]
/// Helper trait for selectors with convenient methods
pub trait SelectExt {
Expand Down
7 changes: 6 additions & 1 deletion tests/paginator_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod common;

pub use common::{TestContext, features::*, setup::*};
use pretty_assertions::assert_eq;
use sea_orm::{PaginatorTrait, QueryOrder, Set, entity::prelude::*};
use sea_orm::{PaginatorTrait, QueryOrder, QuerySelect, Set, entity::prelude::*};

#[sea_orm_macros::test]
async fn paginator_tests() -> Result<(), DbErr> {
Expand Down Expand Up @@ -149,5 +149,10 @@ pub async fn paginator_count(db: &DatabaseConnection) -> Result<(), DbErr> {
0
);

// `count` honors `limit`/`offset` set on the query, unlike `num_items`.
assert_eq!(Entity::find().limit(3).count(db).await?, 3);

assert_eq!(Entity::find().limit(4).offset(8).count(db).await?, 2);

Ok(())
}
Loading