- Refer to the following code:
// mod.rs
pub mod order;
pub trait ExecutorEx: Send {
type Database: sqlx::Database;
type Executor<'a>: sqlx::Executor<'a, Database = Self::Database>
where
Self: 'a;
fn get_executor(&mut self) -> Self::Executor<'_>;
}
impl<T, D> ExecutorEx for &T
where
D: sqlx::Database,
Self: for<'a> sqlx::Executor<'a, Database = D> + Send,
{
type Database = D;
type Executor<'a> = Self
where
Self: 'a;
fn get_executor(&mut self) -> Self::Executor<'_> {
*self
}
}
impl<T, D> ExecutorEx for &mut T
where
for<'a> &'a mut T: sqlx::Executor<'a, Database = D> + Send,
D: sqlx::Database,
T: std::marker::Send,
{
type Database = D;
type Executor<'a> = &'a mut T
where
Self: 'a;
fn get_executor(&mut self) -> Self::Executor<'_> {
*self
}
}
// order.rs
#[allow(unused)]
use sqlx::{Database, QueryBuilder, Result as SqlxResult};
use sqlx::prelude::*;
use super::ExecutorEx;
#[derive(Debug, serde::Serialize, serde::Deserialize, FromRow)]
pub struct Order {
pub order_id: i64,
}
pub trait SqlxOrderExt: ExecutorEx {
fn query_by_ids(
self,
order_ids: &[i64],
) -> impl std::future::Future<Output = SqlxResult<Vec<Order>>> + Send;
}
impl<T, D> SqlxOrderExt for T
where
D: sqlx::Database,
T: ExecutorEx<Database = D>,
Order: for<'r> FromRow<'r, D::Row>,
usize: sqlx::ColumnIndex<D::Row>,
i64: for<'r> sqlx::Decode<'r, D> + sqlx::Type<D>,
for<'q1, 'q2> <D as sqlx::Database>::Arguments<'q1>: sqlx::IntoArguments<'q2, D>,
{
async fn query_by_ids(mut self, order_ids: &[i64]) -> SqlxResult<Vec<Order>> {
let mut query_builder =
QueryBuilder::new("SELECT COUNT(1) FROM order_list WHERE order_id IN (");
let mut separated = query_builder.separated(",");
order_ids.iter().for_each(|item| {
separated.push(item);
});
query_builder.push(")");
let query = query_builder.build_query_scalar::<i64>();
// let r = query.fetch_one(self.get_executor()).await?;
let r: D::Row = self.get_executor().fetch_one(query).await?;
let r = <(i64,)>::from_row(&r);
println!("{r:?}");
let mut query_builder =
QueryBuilder::new("SELECT order_id FROM order_list WHERE order_id IN (");
let mut separated = query_builder.separated(",");
order_ids.iter().for_each(|item| {
separated.push(item);
});
query_builder.push(")");
let query = query_builder.build_query_as::<Order>();
let r = self.get_executor().fetch_all(query).await?;
let r = r
.into_iter()
.filter_map(|item| Order::from_row(&item).ok())
.collect();
Ok(r)
}
}
When I use self.get_executor().fetch_one(query)
, there are no compilation issues. However, when I switch to query.fetch_one(self.get_executor())
, a lifetime exception occurs during compilation:
29 | async fn query_by_ids(mut self, order_ids: &[i64]) -> SqlxResult<Vec<Order>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the parameter type `T` must be valid for lifetime `'_`...
| ...so that the type `T` will meet its required lifetime bounds...
What is the issue here, and how can it be resolved while retaining Send?
[dependencies]
sqlx = { version = "0.8", features = [
"all-databases",
"runtime-tokio-rustls",
] }