postgresql/query.rs
1//! The query builder surface used by the `query!` / `query_as!` macros, and
2//! the [`Executor`] marker implemented by connections, pools and transactions.
3
4use std::{future::Future, marker::PhantomData};
5
6use futures_util::StreamExt;
7
8use crate::{connection::RowStream, encode::ToSql, error::Error, row::FromRow};
9
10pub(crate) mod sealed {
11 pub trait Sealed {}
12}
13
14/// Internal execution capability. Not part of the public API.
15///
16/// Sealed: only this crate implements it. Query execution is reached through
17/// the `query!` / `query_as!` macros, never by calling these methods directly.
18#[doc(hidden)]
19pub trait Capable: sealed::Sealed + Send + Sync {
20 /// Runs a statement without collecting rows and returns the number of
21 /// affected rows.
22 fn execute<'a>(
23 &'a self,
24 sql: &'a str,
25 params: &'a [&'a dyn ToSql],
26 ) -> impl Future<Output = Result<u64, Error>> + Send + 'a;
27
28 /// Runs a statement and returns a stream of rows.
29 ///
30 /// `max_rows` limits the number of rows the server sends (`0` means no
31 /// limit).
32 fn fetch_rows<'a>(
33 &'a self,
34 sql: &'a str,
35 params: &'a [&'a dyn ToSql],
36 max_rows: i32,
37 ) -> impl Future<Output = Result<RowStream, Error>> + Send + 'a;
38}
39
40/// Anything a query can run against: a connection, a pooled connection, a
41/// pool, or a transaction.
42///
43/// This is a sealed marker trait, so generic helpers can accept
44/// `E: Executor`, but queries themselves are only run through the `query!` /
45/// `query_as!` macros.
46pub trait Executor: Capable {}
47
48impl<T: Capable + ?Sized> Executor for T {}
49
50/// Runs multi-statement SQL scripts via the simple query protocol.
51///
52/// This is the unchecked, parameterless path (for migrations, `SET` scripts and
53/// statements the extended protocol cannot express, such as `VACUUM`). Use
54/// `query!` / `query_as!` for anything parameterized or typed.
55pub trait ScriptExecutor: sealed::Sealed {
56 /// Runs one or more statements and returns the affected-row count of the
57 /// last command.
58 ///
59 /// # Errors
60 ///
61 /// Returns an error if the connection is closed or the server rejects a
62 /// statement.
63 fn execute_script<'a>(&'a self, sql: &'a str) -> impl Future<Output = Result<u64, Error>> + Send + 'a;
64}
65
66/// A prepared query returning untyped [`crate::Row`]s.
67pub struct Query<'a> {
68 sql: &'a str,
69 params: &'a [&'a dyn ToSql],
70}
71
72impl<'a> Query<'a> {
73 /// Builds a query from SQL and already-built parameters.
74 pub fn new(sql: &'a str, params: &'a [&'a dyn ToSql]) -> Self {
75 Query {
76 sql,
77 params,
78 }
79 }
80
81 /// Runs the statement and returns the number of affected rows.
82 ///
83 /// Use this for statements that change data (`INSERT`, `UPDATE`, `DELETE`,
84 /// DDL). Any rows the statement produces are read and **discarded**; the
85 /// returned count is the command tag's affected-row count (for example the
86 /// number of inserted or updated rows).
87 ///
88 /// # Errors
89 ///
90 /// Returns a server error if the statement fails, or [`Error::Closed`] if
91 /// the connection is gone.
92 pub async fn execute<E: Executor>(&self, executor: &E) -> Result<u64, Error> {
93 executor.execute(self.sql, self.params).await
94 }
95
96 /// Runs the statement and returns a stream of rows.
97 pub async fn fetch_rows<E: Executor>(&self, executor: &E) -> Result<RowStream, Error> {
98 executor.fetch_rows(self.sql, self.params, 0).await
99 }
100
101 /// Collects all rows into a `Vec<T>`.
102 ///
103 /// The result is unbounded: use [`Query::fetch_rows`] to process a large
104 /// result without holding it all in memory.
105 pub async fn fetch_all<E: Executor, T: FromRow>(&self, executor: &E) -> Result<Vec<T>, Error> {
106 let mut rows = executor.fetch_rows(self.sql, self.params, 0).await?;
107 let mut out = Vec::new();
108 while let Some(row) = rows.next().await {
109 out.push(T::from_row(&row?)?);
110 }
111 Ok(out)
112 }
113
114 /// Returns exactly one row, or [`Error::RowNotFound`].
115 pub async fn fetch_one<E: Executor, T: FromRow>(&self, executor: &E) -> Result<T, Error> {
116 let mut rows = executor.fetch_rows(self.sql, self.params, 1).await?;
117 match rows.next().await {
118 Some(row) => T::from_row(&row?),
119 None => Err(Error::RowNotFound),
120 }
121 }
122
123 /// Returns the first row, if any.
124 pub async fn fetch_optional<E: Executor, T: FromRow>(&self, executor: &E) -> Result<Option<T>, Error> {
125 let mut rows = executor.fetch_rows(self.sql, self.params, 1).await?;
126 match rows.next().await {
127 Some(row) => Ok(Some(T::from_row(&row?)?)),
128 None => Ok(None),
129 }
130 }
131}
132
133/// A prepared query decoded into `T`.
134pub struct QueryAs<'a, T> {
135 query: Query<'a>,
136 _marker: PhantomData<fn() -> T>,
137}
138
139impl<'a, T: FromRow> QueryAs<'a, T> {
140 /// Builds a typed query from SQL and already-built parameters.
141 pub fn new(sql: &'a str, params: &'a [&'a dyn ToSql]) -> Self {
142 QueryAs {
143 query: Query::new(sql, params),
144 _marker: PhantomData,
145 }
146 }
147
148 /// Runs the statement and returns the number of affected rows.
149 ///
150 /// See [`Query::execute`]: rows produced by the statement are discarded.
151 pub async fn execute<E: Executor>(&self, executor: &E) -> Result<u64, Error> {
152 self.query.execute(executor).await
153 }
154
155 /// Runs the statement and returns a stream of rows.
156 pub async fn fetch_rows<E: Executor>(&self, executor: &E) -> Result<RowStream, Error> {
157 self.query.fetch_rows(executor).await
158 }
159
160 /// Collects all rows into a `Vec<T>`.
161 pub async fn fetch_all<E: Executor>(&self, executor: &E) -> Result<Vec<T>, Error> {
162 self.query.fetch_all::<E, T>(executor).await
163 }
164
165 /// Returns exactly one row, or [`Error::RowNotFound`].
166 pub async fn fetch_one<E: Executor>(&self, executor: &E) -> Result<T, Error> {
167 self.query.fetch_one::<E, T>(executor).await
168 }
169
170 /// Returns the first row, if any.
171 pub async fn fetch_optional<E: Executor>(&self, executor: &E) -> Result<Option<T>, Error> {
172 self.query.fetch_optional::<E, T>(executor).await
173 }
174}