fix: tweak lifetimes in Executor to limit the scope for the borrow on the query to the single execution

This commit is contained in:
Ryan Leckey 2020-05-30 02:04:19 -07:00
parent cc9d443434
commit bb3b571a57
No known key found for this signature in database
GPG key ID: BBDFC5595030E7D3
9 changed files with 227 additions and 183 deletions

View file

@ -28,8 +28,9 @@ pub trait Executor<'c>: Send + Debug + Sized {
type Database: Database;
/// Execute the query and return the total number of rows affected.
fn execute<'q: 'c, E: 'c>(self, query: E) -> BoxFuture<'c, Result<u64, Error>>
fn execute<'e, 'q: 'e, E: 'q>(self, query: E) -> BoxFuture<'e, Result<u64, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.execute_many(query)
@ -38,8 +39,9 @@ pub trait Executor<'c>: Send + Debug + Sized {
}
/// Execute multiple queries and return the rows affected from each query, in a stream.
fn execute_many<'q: 'c, E: 'c>(self, query: E) -> BoxStream<'c, Result<u64, Error>>
fn execute_many<'e, 'q: 'e, E: 'q>(self, query: E) -> BoxStream<'e, Result<u64, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.fetch_many(query)
@ -53,11 +55,12 @@ pub trait Executor<'c>: Send + Debug + Sized {
}
/// Execute the query and return the generated results as a stream.
fn fetch<'q: 'c, E: 'c>(
fn fetch<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxStream<'c, Result<<Self::Database as Database>::Row, Error>>
) -> BoxStream<'e, Result<<Self::Database as Database>::Row, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.fetch_many(query)
@ -72,30 +75,33 @@ pub trait Executor<'c>: Send + Debug + Sized {
/// Execute multiple queries and return the generated results as a stream
/// from each query, in a stream.
fn fetch_many<'q: 'c, E: 'c>(
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxStream<'c, Result<Either<u64, <Self::Database as Database>::Row>, Error>>
) -> BoxStream<'e, Result<Either<u64, <Self::Database as Database>::Row>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>;
/// Execute the query and return all the generated results, collected into a [`Vec`].
fn fetch_all<'q: 'c, E: 'c>(
fn fetch_all<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'c, Result<Vec<<Self::Database as Database>::Row>, Error>>
) -> BoxFuture<'e, Result<Vec<<Self::Database as Database>::Row>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.fetch(query).try_collect().boxed()
}
/// Execute the query and returns exactly one row.
fn fetch_one<'q: 'c, E: 'c>(
fn fetch_one<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'c, Result<<Self::Database as Database>::Row, Error>>
) -> BoxFuture<'e, Result<<Self::Database as Database>::Row, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.fetch_optional(query)
@ -107,11 +113,12 @@ pub trait Executor<'c>: Send + Debug + Sized {
}
/// Execute the query and returns at most one row.
fn fetch_optional<'q: 'c, E: 'c>(
fn fetch_optional<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'c, Result<Option<<Self::Database as Database>::Row>, Error>>
) -> BoxFuture<'e, Result<Option<<Self::Database as Database>::Row>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>;
/// Prepare the SQL query and return type information about its parameters
@ -120,11 +127,12 @@ pub trait Executor<'c>: Send + Debug + Sized {
/// This is used by compile-time verification in the query macros to
/// power their type inference.
#[doc(hidden)]
fn describe<'q: 'c, E: 'c>(
fn describe<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'c, Result<Describe<Self::Database>, Error>>
) -> BoxFuture<'e, Result<Describe<Self::Database>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>;
}

View file

@ -198,11 +198,12 @@ impl MySqlConnection {
impl<'c> Executor<'c> for &'c mut MySqlConnection {
type Database = MySql;
fn fetch_many<'q: 'c, E: 'c>(
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
mut query: E,
) -> BoxStream<'c, Result<Either<u64, MySqlRow>, Error>>
) -> BoxStream<'e, Result<Either<u64, MySqlRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let s = query.query();
@ -218,11 +219,12 @@ impl<'c> Executor<'c> for &'c mut MySqlConnection {
})
}
fn fetch_optional<'q: 'c, E: 'c>(
fn fetch_optional<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'c, Result<Option<MySqlRow>, Error>>
) -> BoxFuture<'e, Result<Option<MySqlRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let mut s = self.fetch_many(query);
@ -239,8 +241,9 @@ impl<'c> Executor<'c> for &'c mut MySqlConnection {
}
#[doc(hidden)]
fn describe<'q: 'c, E: 'c>(self, query: E) -> BoxFuture<'c, Result<Describe<MySql>, Error>>
fn describe<'e, 'q: 'e, E: 'q>(self, query: E) -> BoxFuture<'e, Result<Describe<MySql>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let query = query.query();

View file

@ -11,22 +11,24 @@ use crate::error::Error;
use crate::executor::{Execute, Executor};
use crate::pool::Pool;
impl<'p, C> Executor<'p> for &'p Pool<C>
impl<'p, C> Executor<'p> for &'_ Pool<C>
where
C: Connect,
C: 'static + Connect,
for<'c> &'c mut C: Executor<'c, Database = C::Database>,
{
type Database = C::Database;
fn fetch_many<'q, E: 'p>(
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxStream<'p, Result<Either<u64, <Self::Database as Database>::Row>, Error>>
) -> BoxStream<'e, Result<Either<u64, <Self::Database as Database>::Row>, Error>>
where
E: Execute<'q, Self::Database>,
{
let pool = self.clone();
Box::pin(try_stream! {
let mut conn = self.acquire().await?;
let mut conn = pool.acquire().await?;
let mut s = conn.fetch_many(query);
for v in s.try_next().await? {
@ -35,51 +37,61 @@ where
})
}
fn fetch_optional<'q, E: 'p>(
fn fetch_optional<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'p, Result<Option<<Self::Database as Database>::Row>, Error>>
) -> BoxFuture<'e, Result<Option<<Self::Database as Database>::Row>, Error>>
where
E: Execute<'q, Self::Database>,
{
Box::pin(async move { self.acquire().await?.fetch_optional(query).await })
let pool = self.clone();
Box::pin(async move { pool.acquire().await?.fetch_optional(query).await })
}
#[doc(hidden)]
fn describe<'q, E: 'p>(self, query: E) -> BoxFuture<'p, Result<Describe<Self::Database>, Error>>
fn describe<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'e, Result<Describe<Self::Database>, Error>>
where
E: Execute<'q, Self::Database>,
{
Box::pin(async move { self.acquire().await?.describe(query).await })
let pool = self.clone();
Box::pin(async move { pool.acquire().await?.describe(query).await })
}
}
// NOTE: required due to lack of lazy normalization
#[allow(unused_macros)]
macro_rules! impl_executor_for_pool_connection {
($DB:ident, $C:ident, $R:ident) => {
impl<'c> crate::executor::Executor<'c> for &'c mut crate::pool::PoolConnection<$C> {
type Database = $DB;
#[inline]
fn fetch_many<'q: 'c, E: 'c>(
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> futures_core::stream::BoxStream<
'c,
'e,
Result<either::Either<u64, $R>, crate::error::Error>,
>
where
'c: 'e,
E: crate::executor::Execute<'q, $DB>,
{
(&mut **self).fetch_many(query)
}
#[inline]
fn fetch_optional<'q: 'c, E: 'c>(
fn fetch_optional<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> futures_core::future::BoxFuture<'c, Result<Option<$R>, crate::error::Error>>
) -> futures_core::future::BoxFuture<'e, Result<Option<$R>, crate::error::Error>>
where
'c: 'e,
E: crate::executor::Execute<'q, $DB>,
{
(&mut **self).fetch_optional(query)
@ -87,14 +99,15 @@ macro_rules! impl_executor_for_pool_connection {
#[doc(hidden)]
#[inline]
fn describe<'q: 'c, E: 'c>(
fn describe<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> futures_core::future::BoxFuture<
'c,
'e,
Result<crate::describe::Describe<$DB>, crate::error::Error>,
>
where
'c: 'e,
E: crate::executor::Execute<'q, $DB>,
{
(&mut **self).describe(query)

View file

@ -242,11 +242,12 @@ SELECT oid FROM pg_catalog.pg_type WHERE typname ILIKE $1
impl<'c> Executor<'c> for &'c mut PgConnection {
type Database = Postgres;
fn fetch_many<'q: 'c, E: 'c>(
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
mut query: E,
) -> BoxStream<'c, Result<Either<u64, PgRow>, Error>>
) -> BoxStream<'e, Result<Either<u64, PgRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let s = query.query();
@ -262,11 +263,12 @@ impl<'c> Executor<'c> for &'c mut PgConnection {
})
}
fn fetch_optional<'q: 'c, E: 'c>(
fn fetch_optional<'e, 'q: 'e, E: 'q>(
self,
mut query: E,
) -> BoxFuture<'c, Result<Option<PgRow>, Error>>
) -> BoxFuture<'e, Result<Option<PgRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let s = query.query();
@ -287,8 +289,12 @@ impl<'c> Executor<'c> for &'c mut PgConnection {
}
#[doc(hidden)]
fn describe<'q: 'c, E: 'c>(self, query: E) -> BoxFuture<'c, Result<Describe<Postgres>, Error>>
fn describe<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'e, Result<Describe<Postgres>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let s = query.query();

View file

@ -195,26 +195,35 @@ impl PgListener {
impl<'c> Executor<'c> for &'c mut PgListener {
type Database = Postgres;
fn fetch_many<'q: 'c, E: 'c>(self, query: E) -> BoxStream<'c, Result<Either<u64, PgRow>, Error>>
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxStream<'e, Result<Either<u64, PgRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.connection().fetch_many(query)
}
fn fetch_optional<'q: 'c, E: 'c>(self, query: E) -> BoxFuture<'c, Result<Option<PgRow>, Error>>
fn fetch_optional<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'e, Result<Option<PgRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.connection().fetch_optional(query)
}
#[doc(hidden)]
fn describe<'q: 'c, E: 'c>(
fn describe<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'c, Result<Describe<Self::Database>, Error>>
) -> BoxFuture<'e, Result<Describe<Self::Database>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
self.connection().describe(query)

View file

@ -2,9 +2,8 @@ use std::marker::PhantomData;
use async_stream::try_stream;
use either::Either;
use futures_core::future::BoxFuture;
use futures_core::stream::BoxStream;
use futures_util::{future, FutureExt, StreamExt, TryFutureExt, TryStreamExt};
use futures_util::{future, StreamExt, TryFutureExt, TryStreamExt};
use crate::arguments::{Arguments, IntoArguments};
use crate::database::{Database, HasArguments};
@ -71,7 +70,7 @@ impl<'q, DB: Database> Query<'q, DB, <DB as HasArguments<'q>>::Arguments> {
impl<'q, DB, A: Send> Query<'q, DB, A>
where
DB: Database,
A: IntoArguments<'q, DB>,
A: 'q + IntoArguments<'q, DB>,
{
/// Map each row in the result to another type.
///
@ -104,10 +103,10 @@ where
/// Execute the query and return the total number of rows affected.
#[inline]
pub async fn execute<'c, E>(self, executor: E) -> Result<u64, Error>
pub async fn execute<'e, 'c: 'e, E>(self, executor: E) -> Result<u64, Error>
where
'q: 'c,
A: 'c,
'q: 'e,
A: 'e,
E: Executor<'c, Database = DB>,
{
executor.execute(self).await
@ -115,10 +114,10 @@ where
/// Execute multiple queries and return the rows affected from each query, in a stream.
#[inline]
pub async fn execute_many<'c, E>(self, executor: E) -> BoxStream<'c, Result<u64, Error>>
pub async fn execute_many<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<u64, Error>>
where
'q: 'c,
A: 'c,
'q: 'e,
A: 'e,
E: Executor<'c, Database = DB>,
{
executor.execute_many(self)
@ -126,10 +125,10 @@ where
/// Execute the query and return the generated results as a stream.
#[inline]
pub fn fetch<'c, E>(self, executor: E) -> BoxStream<'c, Result<DB::Row, Error>>
pub fn fetch<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<DB::Row, Error>>
where
'q: 'c,
A: 'c,
'q: 'e,
A: 'e,
E: Executor<'c, Database = DB>,
{
executor.fetch(self)
@ -138,13 +137,13 @@ where
/// Execute multiple queries and return the generated results as a stream
/// from each query, in a stream.
#[inline]
pub fn fetch_many<'c, E>(
pub fn fetch_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'c, Result<Either<u64, DB::Row>, Error>>
) -> BoxStream<'e, Result<Either<u64, DB::Row>, Error>>
where
'q: 'c,
A: 'c,
'q: 'e,
A: 'e,
E: Executor<'c, Database = DB>,
{
executor.fetch_many(self)
@ -152,10 +151,10 @@ where
/// Execute the query and return all the generated results, collected into a [`Vec`].
#[inline]
pub async fn fetch_all<'c, E>(self, executor: E) -> Result<Vec<DB::Row>, Error>
pub async fn fetch_all<'e, 'c: 'e, E>(self, executor: E) -> Result<Vec<DB::Row>, Error>
where
'q: 'c,
A: 'c,
'q: 'e,
A: 'e,
E: Executor<'c, Database = DB>,
{
executor.fetch_all(self).await
@ -163,10 +162,10 @@ where
/// Execute the query and returns exactly one row.
#[inline]
pub async fn fetch_one<'c, E>(self, executor: E) -> Result<DB::Row, Error>
pub async fn fetch_one<'e, 'c: 'e, E>(self, executor: E) -> Result<DB::Row, Error>
where
'q: 'c,
A: 'c,
'q: 'e,
A: 'e,
E: Executor<'c, Database = DB>,
{
executor.fetch_one(self).await
@ -174,10 +173,10 @@ where
/// Execute the query and returns at most one row.
#[inline]
pub async fn fetch_optional<'c, E>(self, executor: E) -> Result<Option<DB::Row>, Error>
pub async fn fetch_optional<'e, 'c: 'e, E>(self, executor: E) -> Result<Option<DB::Row>, Error>
where
'q: 'c,
A: 'c,
'q: 'e,
A: 'e,
E: Executor<'c, Database = DB>,
{
executor.fetch_optional(self).await
@ -207,16 +206,14 @@ where
O: Send + Unpin,
A: 'q + Send + IntoArguments<'q, DB>,
{
// FIXME: This is very close 1:1 with [`Executor::fetch`]
// noinspection DuplicatedCode
/// Execute the query and return the generated results as a stream.
pub fn fetch<'c, E>(self, executor: E) -> BoxStream<'c, Result<O, Error>>
pub fn fetch<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<O, Error>>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
F: 'c,
O: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
F: 'e,
O: 'e,
{
self.fetch_many(executor)
.try_filter_map(|step| async move {
@ -230,13 +227,16 @@ where
/// Execute multiple queries and return the generated results as a stream
/// from each query, in a stream.
pub fn fetch_many<'c, E>(self, executor: E) -> BoxStream<'c, Result<Either<u64, O>, Error>>
pub fn fetch_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
F: 'c,
O: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
F: 'e,
O: 'e,
{
Box::pin(try_stream! {
let mut s = executor.fetch_many(self.inner);
@ -253,54 +253,50 @@ where
}
/// Execute the query and return all the generated results, collected into a [`Vec`].
#[inline]
pub fn fetch_all<'c, E>(self, executor: E) -> BoxFuture<'c, Result<Vec<O>, Error>>
pub async fn fetch_all<'e, 'c: 'e, E>(self, executor: E) -> Result<Vec<O>, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
F: 'c,
O: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
F: 'e,
O: 'e,
{
self.fetch(executor).try_collect().boxed()
self.fetch(executor).try_collect().await
}
// FIXME: This is very close 1:1 with [`Executor::fetch_one`]
// noinspection DuplicatedCode
/// Execute the query and returns exactly one row.
pub fn fetch_one<'c, E>(self, executor: E) -> BoxFuture<'c, Result<O, Error>>
pub async fn fetch_one<'e, 'c: 'e, E>(self, executor: E) -> Result<O, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
F: 'c,
O: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
F: 'e,
O: 'e,
{
self.fetch_optional(executor)
.and_then(|row| match row {
Some(row) => future::ok(row),
None => future::err(Error::RowNotFound),
})
.boxed()
.await
}
/// Execute the query and returns at most one row.
pub fn fetch_optional<'c, E>(self, executor: E) -> BoxFuture<'c, Result<Option<O>, Error>>
pub async fn fetch_optional<'e, 'c: 'e, E>(self, executor: E) -> Result<Option<O>, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
F: 'c,
O: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
F: 'e,
O: 'e,
{
Box::pin(async move {
let row = executor.fetch_optional(self.inner).await?;
if let Some(row) = row {
(self.mapper)(row).map(Some)
} else {
Ok(None)
}
})
let row = executor.fetch_optional(self.inner).await?;
if let Some(row) = row {
(self.mapper)(row).map(Some)
} else {
Ok(None)
}
}
}

View file

@ -24,7 +24,7 @@ pub struct QueryAs<'q, DB: Database, O, A> {
impl<'q, DB, O: Send, A: Send> Execute<'q, DB> for QueryAs<'q, DB, O, A>
where
DB: Database,
A: IntoArguments<'q, DB>,
A: 'q + IntoArguments<'q, DB>,
{
#[inline]
fn query(&self) -> &'q str {
@ -52,17 +52,17 @@ impl<'q, DB: Database, O> QueryAs<'q, DB, O, <DB as HasArguments<'q>>::Arguments
impl<'q, DB, O, A> QueryAs<'q, DB, O, A>
where
DB: Database,
A: IntoArguments<'q, DB>,
A: 'q + IntoArguments<'q, DB>,
O: Send + Unpin + for<'r> FromRow<'r, DB::Row>,
{
/// Execute the query and return the generated results as a stream.
pub fn fetch<'c, E>(self, executor: E) -> BoxStream<'c, Result<O, Error>>
pub fn fetch<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<O, Error>>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
O: 'c,
A: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
O: 'e,
A: 'e,
{
self.fetch_many(executor)
.try_filter_map(|step| async move { Ok(step.right()) })
@ -71,13 +71,16 @@ where
/// Execute multiple queries and return the generated results as a stream
/// from each query, in a stream.
pub fn fetch_many<'c, E>(self, executor: E) -> BoxStream<'c, Result<Either<u64, O>, Error>>
pub fn fetch_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
O: 'c,
A: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
O: 'e,
A: 'e,
{
Box::pin(try_stream! {
let mut s = executor.fetch_many(self.inner);
@ -95,25 +98,25 @@ where
/// Execute the query and return all the generated results, collected into a [`Vec`].
#[inline]
pub async fn fetch_all<'c, E>(self, executor: E) -> Result<Vec<O>, Error>
pub async fn fetch_all<'e, 'c: 'e, E>(self, executor: E) -> Result<Vec<O>, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
A: 'c,
O: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
O: 'e,
A: 'e,
{
self.fetch(executor).try_collect().await
}
/// Execute the query and returns exactly one row.
pub async fn fetch_one<'c, E>(self, executor: E) -> Result<O, Error>
pub async fn fetch_one<'e, 'c: 'e, E>(self, executor: E) -> Result<O, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
O: 'c,
A: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
O: 'e,
A: 'e,
{
self.fetch_optional(executor)
.await
@ -121,13 +124,13 @@ where
}
/// Execute the query and returns at most one row.
pub async fn fetch_optional<'c, E>(self, executor: E) -> Result<Option<O>, Error>
pub async fn fetch_optional<'e, 'c: 'e, E>(self, executor: E) -> Result<Option<O>, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
O: 'c,
A: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
O: 'e,
A: 'e,
{
let row = executor.fetch_optional(self.inner).await?;
if let Some(row) = row {

View file

@ -19,7 +19,7 @@ pub struct QueryScalar<'q, DB: Database, O, A> {
impl<'q, DB: Database, O: Send, A: Send> Execute<'q, DB> for QueryScalar<'q, DB, O, A>
where
A: IntoArguments<'q, DB>,
A: 'q + IntoArguments<'q, DB>,
{
#[inline]
fn query(&self) -> &'q str {
@ -48,18 +48,18 @@ impl<'q, DB, O, A> QueryScalar<'q, DB, O, A>
where
DB: Database,
O: Send + Unpin,
A: IntoArguments<'q, DB>,
A: 'q + IntoArguments<'q, DB>,
(O,): Send + Unpin + for<'r> FromRow<'r, DB::Row>,
{
/// Execute the query and return the generated results as a stream.
#[inline]
pub fn fetch<'c, E>(self, executor: E) -> BoxStream<'c, Result<O, Error>>
pub fn fetch<'e, 'c: 'e, E>(self, executor: E) -> BoxStream<'e, Result<O, Error>>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
A: 'c,
O: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
A: 'e,
O: 'e,
{
self.inner.fetch(executor).map_ok(|it| it.0).boxed()
}
@ -67,13 +67,16 @@ where
/// Execute multiple queries and return the generated results as a stream
/// from each query, in a stream.
#[inline]
pub fn fetch_many<'c, E>(self, executor: E) -> BoxStream<'c, Result<Either<u64, O>, Error>>
pub fn fetch_many<'e, 'c: 'e, E>(
self,
executor: E,
) -> BoxStream<'e, Result<Either<u64, O>, Error>>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
O: 'c,
A: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
A: 'e,
O: 'e,
{
self.inner
.fetch_many(executor)
@ -83,13 +86,13 @@ where
/// Execute the query and return all the generated results, collected into a [`Vec`].
#[inline]
pub async fn fetch_all<'c, E>(self, executor: E) -> Result<Vec<O>, Error>
pub async fn fetch_all<'e, 'c: 'e, E>(self, executor: E) -> Result<Vec<O>, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
(O,): 'c,
A: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
(O,): 'e,
A: 'e,
{
self.inner
.fetch(executor)
@ -100,26 +103,26 @@ where
/// Execute the query and returns exactly one row.
#[inline]
pub async fn fetch_one<'c, E>(self, executor: E) -> Result<O, Error>
pub async fn fetch_one<'e, 'c: 'e, E>(self, executor: E) -> Result<O, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
O: 'c,
A: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
O: 'e,
A: 'e,
{
self.inner.fetch_one(executor).map_ok(|it| it.0).await
}
/// Execute the query and returns at most one row.
#[inline]
pub async fn fetch_optional<'c, E>(self, executor: E) -> Result<Option<O>, Error>
pub async fn fetch_optional<'e, 'c: 'e, E>(self, executor: E) -> Result<Option<O>, Error>
where
'q: 'c,
E: 'c + Executor<'c, Database = DB>,
DB: 'c,
O: 'c,
A: 'c,
'q: 'e,
E: 'e + Executor<'c, Database = DB>,
DB: 'e,
O: 'e,
A: 'e,
{
Ok(self.inner.fetch_optional(executor).await?.map(|it| it.0))
}

View file

@ -74,11 +74,12 @@ fn emplace_row_metadata(
impl<'c> Executor<'c> for &'c mut SqliteConnection {
type Database = Sqlite;
fn fetch_many<'q: 'c, E: 'c>(
fn fetch_many<'e, 'q: 'e, E: 'q>(
self,
mut query: E,
) -> BoxStream<'c, Result<Either<u64, SqliteRow>, Error>>
) -> BoxStream<'e, Result<Either<u64, SqliteRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let s = query.query();
@ -148,11 +149,12 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
})
}
fn fetch_optional<'q: 'c, E: 'c>(
fn fetch_optional<'e, 'q: 'e, E: 'q>(
self,
query: E,
) -> BoxFuture<'c, Result<Option<SqliteRow>, Error>>
) -> BoxFuture<'e, Result<Option<SqliteRow>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let mut s = self.fetch_many(query);
@ -169,8 +171,9 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
}
#[doc(hidden)]
fn describe<'q: 'c, E: 'c>(self, query: E) -> BoxFuture<'c, Result<Describe<Sqlite>, Error>>
fn describe<'e, 'q: 'e, E: 'q>(self, query: E) -> BoxFuture<'e, Result<Describe<Sqlite>, Error>>
where
'c: 'e,
E: Execute<'q, Self::Database>,
{
let query = query.query();