diff --git a/sqlx-core/src/executor.rs b/sqlx-core/src/executor.rs index 0f50dac3..037f30dd 100644 --- a/sqlx-core/src/executor.rs +++ b/sqlx-core/src/executor.rs @@ -6,7 +6,7 @@ use futures_util::TryStreamExt; /// Encapsulates query execution on the database. /// -/// Implemented by [Pool], [Connection], and [Transaction]. +/// Implemented primarily by [crate::Pool]. pub trait Executor { type Database: Database + ?Sized; @@ -32,14 +32,26 @@ pub trait Executor { ) -> BoxStream<'e, crate::Result<::Row>>; /// Executes the query and returns up to resulting record. - /// * `Error::FoundMoreThanOne` will be returned if the query produced more than 1 row. + /// + /// * [crate::Error::FoundMoreThanOne] will be returned if the query produced more than 1 row. fn fetch_optional<'e, 'q: 'e>( &'e mut self, query: &'q str, args: ::Arguments, ) -> BoxFuture<'e, crate::Result::Row>>> { let mut s = self.fetch(query, args); - Box::pin(async move { s.try_next().await }) + Box::pin(async move { + match s.try_next().await? { + Some(val) => { + if s.try_next().await?.is_some() { + Err(crate::Error::FoundMoreThanOne) + } else { + Ok(Some(val)) + } + }, + None => Ok(None) + } + }) } /// Execute the query and return at most one resulting record. diff --git a/sqlx-core/src/query.rs b/sqlx-core/src/query.rs index fafcda67..b14d4c94 100644 --- a/sqlx-core/src/query.rs +++ b/sqlx-core/src/query.rs @@ -9,6 +9,9 @@ use futures_util::TryStreamExt; use std::marker::PhantomData; /// Dynamic SQL query with bind parameters. Returned by [query]. +/// +/// The methods on this struct should be passed a reference to [crate::Pool] or one of +/// the connection types. pub struct Query<'q, DB, T = ::Arguments> where DB: Database, @@ -23,6 +26,9 @@ where DB: Database, P: IntoArguments + Send, { + /// Execute the query for its side-effects. + /// + /// Returns the number of rows affected, or 0 if not applicable. pub async fn execute(self, executor: &mut E) -> crate::Result where E: Executor, @@ -32,6 +38,9 @@ where .await } + /// Execute the query, returning the rows as a futures `Stream`. + /// + /// Use [fetch_all] if you want a `Vec` instead. pub fn fetch<'e, E>(self, executor: &'e mut E) -> BoxStream<'e, crate::Result> where E: Executor, @@ -40,6 +49,7 @@ where executor.fetch(self.query, self.arguments.into_arguments()) } + /// Execute the query and get all rows from the result as a `Vec`. pub async fn fetch_all(self, executor: &mut E) -> crate::Result> where E: Executor, @@ -50,6 +60,10 @@ where .await } + /// Execute a query which should return either 0 or 1 rows. + /// + /// Returns [crate::Error::FoundMoreThanOne] if more than 1 row is returned. + /// Use `.fetch().try_next()` if you just want one row. pub async fn fetch_optional(self, executor: &mut E) -> crate::Result> where E: Executor, @@ -59,6 +73,10 @@ where .await } + /// Execute a query which should return exactly 1 row. + /// + /// * Returns [crate::Error::NotFound] if 0 rows are returned. + /// * Returns [crate::Error::FoundMoreThanOne] if more than one row is returned. pub async fn fetch_one(self, executor: &mut E) -> crate::Result where E: Executor, diff --git a/sqlx-core/src/query_as.rs b/sqlx-core/src/query_as.rs index 461aa27c..9125b0e1 100644 --- a/sqlx-core/src/query_as.rs +++ b/sqlx-core/src/query_as.rs @@ -7,7 +7,12 @@ use crate::{ executor::Executor, row::FromRow, types::HasSqlType, }; -/// SQL query with bind parameters and output type. Returned by [query_as] and [query!] *et al*. +/// SQL query with bind parameters, which maps rows to an explicit output type. +/// +/// Returned by [query_as] and [query!] *et al*. +/// +/// The methods on this struct should be passed a reference to [crate::Pool] or one of +/// the connection types. pub struct QueryAs<'q, DB, R, P = ::Arguments> where DB: Database, @@ -17,12 +22,15 @@ where map_row: fn(DB::Row) -> crate::Result, } -/// The result of [query!] for SQL queries that do not return results. +/// The result of [query!] for SQL queries that does not return output. impl QueryAs<'_, DB, (), P> where DB: Database, P: IntoArguments + Send, { + /// Execute the query for its side-effects. + /// + /// Returns the number of rows affected, or 0 if not applicable. pub async fn execute(self, executor: &mut E) -> crate::Result where E: Executor, @@ -39,6 +47,9 @@ where P: IntoArguments + Send, R: Send + 'q, { + /// Execute the query, returning the rows as a futures `Stream`. + /// + /// Use [fetch_all] if you want a `Vec` instead. pub fn fetch<'e, E>(self, executor: &'e mut E) -> impl Stream> + 'e where E: Executor, @@ -55,6 +66,7 @@ where .and_then(move |row| future::ready(map_row(row))) } + /// Execute the query and get all rows from the result as a `Vec`. pub async fn fetch_all(self, executor: &mut E) -> crate::Result> where E: Executor, @@ -62,6 +74,10 @@ where self.fetch(executor).try_collect().await } + /// Execute a query which should return either 0 or 1 rows. + /// + /// Returns [crate::Error::FoundMoreThanOne] if more than 1 row is returned. + /// Use `.fetch().try_next()` if you just want one row. pub async fn fetch_optional(self, executor: &mut E) -> crate::Result> where E: Executor, @@ -73,6 +89,10 @@ where .transpose() } + /// Execute a query which should return exactly 1 row. + /// + /// * Returns [crate::Error::NotFound] if 0 rows are returned. + /// * Returns [crate::Error::FoundMoreThanOne] if more than one row is returned. pub async fn fetch_one(self, executor: &mut E) -> crate::Result where E: Executor,