Paginate prompts that implementation of Send
is not general enough when table.into_boxed()
#141
Answered
by
weiznich
tingfeng-key
asked this question in
Q&A
-
Paginate.rs code: use crate::connect::DbConnect as Connect;
use diesel::{
pg::Pg,
query_builder::{AstPass, Query, QueryFragment, QueryId},
sql_types::BigInt,
QueryResult,
};
use diesel_async::{methods::LoadQuery, RunQueryDsl};
pub trait Paginate: Sized {
fn paginate(self, page: i64) -> Paginated<Self>;
}
impl<T> Paginate for T {
fn paginate(self, page: i64) -> Paginated<Self> {
Paginated {
query: self,
per_page: DEFAULT_PER_PAGE,
page,
offset: (page - 1) * DEFAULT_PER_PAGE,
}
}
}
const DEFAULT_PER_PAGE: i64 = 10;
#[derive(Debug, Clone, Copy, QueryId)]
pub struct Paginated<T> {
query: T,
page: i64,
per_page: i64,
offset: i64,
}
impl<T> Paginated<T> {
pub fn per_page(self, per_page: i64) -> Self {
Paginated {
per_page,
offset: (self.page - 1) * per_page,
..self
}
}
}
impl<T> Paginated<T> {
pub async fn load_and_count_pages<'a, U>(self, conn: &mut Connect) -> QueryResult<(Vec<U>, i64)>
where
Self: LoadQuery<'a, Connect, (U, i64)> + 'a,
U: std::marker::Send,
{
let per_page = self.per_page;
let results = self.load::<(U, i64)>(conn).await?;
let total = results.get(0).map(|x| x.1).unwrap_or(0);
let records = results.into_iter().map(|x| x.0).collect();
let total_pages = (total as f64 / per_page as f64).ceil() as i64;
Ok((records, total_pages))
}
}
impl<T: Query> Query for Paginated<T> {
type SqlType = (T::SqlType, BigInt);
}
impl<T> QueryFragment<Pg> for Paginated<T>
where
T: QueryFragment<Pg>,
{
fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> {
out.push_sql("SELECT *, COUNT(*) OVER () FROM (");
self.query.walk_ast(out.reborrow())?;
out.push_sql(") as paged_query_with LIMIT ");
out.push_bind_param::<BigInt, _>(&self.per_page)?;
out.push_sql(" OFFSET ");
out.push_bind_param::<BigInt, _>(&self.offset)?;
Ok(())
}
} use code: use diesel_async::{
pooled_connection::{
deadpool::{Object, Pool},
AsyncDieselConnectionManager,
},
AsyncPgConnection,
};
pub async fn paginate(
conn: &mut Object<AsyncPgConnection>,
page: i64,
limit: i64,
) -> Result<(Vec<Self>, i64)> {
let mut table = system_dicts::table.into_boxed();
let (data, count) = table
.select(UserEntity::as_select())
.paginate(page)
.per_page(limit)
.load_and_count_pages::<UserEntity>(conn)
.await?;
Ok((data, count))
} use axum Compiling error tip: |
19 | axum::Router::new().route("/user_list", get(index));
| ^^^^^^^^^^ implementation of `Send` is not general enough
|
= note: `Send` would have to be implemented for the type `&'0 deadpool::managed::Pool<diesel_async::pooled_connection::AsyncDieselConnectionManager<diesel_async::pg::AsyncPgConnection>>`, for any lifetime `'0`...
= note: ...but `Send` is actually implemented for the type `&'1 deadpool::managed::Pool<diesel_async::pooled_connection::AsyncDieselConnectionManager<diesel_async::pg::AsyncPgConnection>>`, for some specific lifetime `'1` |
Beta Was this translation helpful? Give feedback.
Answered by
weiznich
Mar 8, 2024
Replies: 1 comment 4 replies
-
You might want to clarify your question instead of just posting code + an error message. |
Beta Was this translation helpful? Give feedback.
4 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://stackoverflow.com/questions/78065581/implementation-of-dieselquery-builderquery-is-not-general-enough-error
As for the error message: Please open an issue in the rustc repo for that.