我想封装一个函数,把具体的数据库类型(如Sqlite,Any)替换为泛型后就会报错生命周期不满足,求教怎么解决?
use futures_core::future::BoxFuture;
use sqlx::{Any, Database, Executor, IntoArguments, Sqlite, query_with};
struct TestQuery<'a, DB: Database> {
sql: String,
arg: DB::Arguments<'a>,
}
//正常
impl<'a> TestQuery<'a, Sqlite> {
fn execute<'e, E>(
self,
e: E,
) -> BoxFuture<'e, Result<<Sqlite as Database>::QueryResult, sqlx_core::Error>>
where
'a: 'e,
E: Executor<'e, Database = Sqlite> + 'e,
{
Box::pin(async move {
let TestQuery { sql, arg } = self;
query_with(&sql, arg).execute(e).await
})
}
}
//正常
impl<'a> TestQuery<'a, Any> {
fn execute<'e, E>(
self,
e: E,
) -> BoxFuture<'e, Result<<Any as Database>::QueryResult, sqlx_core::Error>>
where
'a: 'e,
E: Executor<'e, Database = Any> + 'e,
{
Box::pin(async move {
let TestQuery { sql, arg } = self;
query_with(&sql, arg).execute(e).await
})
}
}
//把具体的数据库类型修改为泛型后就不行
impl<'a, DB: Database> TestQuery<'a, DB> {
fn execute1<'e, E>(self, e: E) -> BoxFuture<'e, Result<DB::QueryResult, sqlx_core::Error>>
where
'a: 'e,
E: Executor<'e, Database = DB> + 'e,
DB::Arguments<'a>: IntoArguments<'e, DB>,
{
//报错: lifetime may not live long enough 。 coercion requires that `'a` must outlive `'static`
Box::pin(async move {
let TestQuery { sql, arg } = self;
query_with(&sql, arg).execute(e).await
})
}
}
}
1
共 3 条评论, 1 页
评论区
写评论那你可以把 sql 字段变成引用
gist
写
sql: String
是不行的,因为 &sql 在 execute1 函数内创建,需要一种方式表达DB::Arguments<'a>
中的 'a 与&'q sql
中的 'q 具有'q: 'a
关系。这无法被 Rust 的 trait bound 表达。谢谢大佬!execute1的可以编译过,但是在调用时候,除了pgArguments,mysqlArguments这种不带生命周期的数据库参数,其他像 AnyArguments<'q> 这种带生命周期的就没法绑定参数和调用
--
👇
苦瓜小仔: 你可以这样写(没有 BoxFuture):
gist
你可以这样写(没有 BoxFuture):
gist