tokio_postgres/client.rs
1use crate::codec::{BackendMessages, FrontendMessage};
2use crate::config::{SslMode, SslNegotiation};
3use crate::connection::{Request, RequestMessages};
4use crate::copy_out::CopyOutStream;
5#[cfg(feature = "runtime")]
6use crate::keepalive::KeepaliveConfig;
7use crate::query::RowStream;
8use crate::simple_query::SimpleQueryStream;
9#[cfg(feature = "runtime")]
10use crate::tls::MakeTlsConnect;
11use crate::tls::TlsConnect;
12use crate::types::{Oid, ToSql, Type};
13#[cfg(feature = "runtime")]
14use crate::Socket;
15use crate::{
16 copy_in, copy_out, prepare, query, simple_query, slice_iter, CancelToken, CopyInSink, Error,
17 Row, SimpleQueryMessage, Statement, ToStatement, Transaction, TransactionBuilder,
18};
19use bytes::{Buf, BytesMut};
20use fallible_iterator::FallibleIterator;
21use futures_channel::mpsc;
22use futures_util::{future, pin_mut, ready, StreamExt, TryStreamExt};
23use parking_lot::Mutex;
24use postgres_protocol::message::backend::Message;
25use postgres_protocol::message::frontend;
26use postgres_types::BorrowToSql;
27use std::collections::HashMap;
28use std::fmt;
29#[cfg(feature = "runtime")]
30use std::net::IpAddr;
31#[cfg(feature = "runtime")]
32use std::path::PathBuf;
33use std::sync::Arc;
34use std::task::{Context, Poll};
35#[cfg(feature = "runtime")]
36use std::time::Duration;
37use tokio::io::{AsyncRead, AsyncWrite};
38
39pub struct Responses {
40 receiver: mpsc::Receiver<BackendMessages>,
41 cur: BackendMessages,
42}
43
44impl Responses {
45 pub fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Result<Message, Error>> {
46 loop {
47 match self.cur.next().map_err(Error::parse)? {
48 Some(Message::ErrorResponse(body)) => return Poll::Ready(Err(Error::db(body))),
49 Some(message) => return Poll::Ready(Ok(message)),
50 None => {}
51 }
52
53 match ready!(self.receiver.poll_next_unpin(cx)) {
54 Some(messages) => self.cur = messages,
55 None => return Poll::Ready(Err(Error::closed())),
56 }
57 }
58 }
59
60 pub async fn next(&mut self) -> Result<Message, Error> {
61 future::poll_fn(|cx| self.poll_next(cx)).await
62 }
63}
64
65/// A cache of type info and prepared statements for fetching type info
66/// (corresponding to the queries in the [prepare](prepare) module).
67#[derive(Default)]
68struct CachedTypeInfo {
69 /// A statement for basic information for a type from its
70 /// OID. Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_QUERY) (or its
71 /// fallback).
72 typeinfo: Option<Statement>,
73 /// A statement for getting information for a composite type from its OID.
74 /// Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_COMPOSITE_QUERY).
75 typeinfo_composite: Option<Statement>,
76 /// A statement for getting information for a composite type from its OID.
77 /// Corresponds to [TYPEINFO_QUERY](prepare::TYPEINFO_COMPOSITE_QUERY) (or
78 /// its fallback).
79 typeinfo_enum: Option<Statement>,
80
81 /// Cache of types already looked up.
82 types: HashMap<Oid, Type>,
83}
84
85pub struct InnerClient {
86 sender: mpsc::UnboundedSender<Request>,
87 cached_typeinfo: Mutex<CachedTypeInfo>,
88
89 /// A buffer to use when writing out postgres commands.
90 buffer: Mutex<BytesMut>,
91}
92
93impl InnerClient {
94 pub fn send(&self, messages: RequestMessages) -> Result<Responses, Error> {
95 let (sender, receiver) = mpsc::channel(1);
96 let request = Request { messages, sender };
97 self.sender
98 .unbounded_send(request)
99 .map_err(|_| Error::closed())?;
100
101 Ok(Responses {
102 receiver,
103 cur: BackendMessages::empty(),
104 })
105 }
106
107 pub fn typeinfo(&self) -> Option<Statement> {
108 self.cached_typeinfo.lock().typeinfo.clone()
109 }
110
111 pub fn set_typeinfo(&self, statement: &Statement) {
112 self.cached_typeinfo.lock().typeinfo = Some(statement.clone());
113 }
114
115 pub fn typeinfo_composite(&self) -> Option<Statement> {
116 self.cached_typeinfo.lock().typeinfo_composite.clone()
117 }
118
119 pub fn set_typeinfo_composite(&self, statement: &Statement) {
120 self.cached_typeinfo.lock().typeinfo_composite = Some(statement.clone());
121 }
122
123 pub fn typeinfo_enum(&self) -> Option<Statement> {
124 self.cached_typeinfo.lock().typeinfo_enum.clone()
125 }
126
127 pub fn set_typeinfo_enum(&self, statement: &Statement) {
128 self.cached_typeinfo.lock().typeinfo_enum = Some(statement.clone());
129 }
130
131 pub fn type_(&self, oid: Oid) -> Option<Type> {
132 self.cached_typeinfo.lock().types.get(&oid).cloned()
133 }
134
135 pub fn set_type(&self, oid: Oid, type_: &Type) {
136 self.cached_typeinfo.lock().types.insert(oid, type_.clone());
137 }
138
139 pub fn clear_type_cache(&self) {
140 self.cached_typeinfo.lock().types.clear();
141 }
142
143 /// Call the given function with a buffer to be used when writing out
144 /// postgres commands.
145 pub fn with_buf<F, R>(&self, f: F) -> R
146 where
147 F: FnOnce(&mut BytesMut) -> R,
148 {
149 let mut buffer = self.buffer.lock();
150 let r = f(&mut buffer);
151 buffer.clear();
152 r
153 }
154}
155
156#[cfg(feature = "runtime")]
157#[derive(Clone)]
158pub(crate) struct SocketConfig {
159 pub addr: Addr,
160 pub hostname: Option<String>,
161 pub port: u16,
162 pub connect_timeout: Option<Duration>,
163 pub tcp_user_timeout: Option<Duration>,
164 pub keepalive: Option<KeepaliveConfig>,
165}
166
167#[cfg(feature = "runtime")]
168#[derive(Clone)]
169pub(crate) enum Addr {
170 Tcp(IpAddr),
171 #[cfg(unix)]
172 Unix(PathBuf),
173}
174
175/// An asynchronous PostgreSQL client.
176///
177/// The client is one half of what is returned when a connection is established. Users interact with the database
178/// through this client object.
179pub struct Client {
180 inner: Arc<InnerClient>,
181 #[cfg(feature = "runtime")]
182 socket_config: Option<SocketConfig>,
183 ssl_mode: SslMode,
184 ssl_negotiation: SslNegotiation,
185 process_id: i32,
186 secret_key: i32,
187}
188
189impl Client {
190 pub(crate) fn new(
191 sender: mpsc::UnboundedSender<Request>,
192 ssl_mode: SslMode,
193 ssl_negotiation: SslNegotiation,
194 process_id: i32,
195 secret_key: i32,
196 ) -> Client {
197 Client {
198 inner: Arc::new(InnerClient {
199 sender,
200 cached_typeinfo: Default::default(),
201 buffer: Default::default(),
202 }),
203 #[cfg(feature = "runtime")]
204 socket_config: None,
205 ssl_mode,
206 ssl_negotiation,
207 process_id,
208 secret_key,
209 }
210 }
211
212 pub(crate) fn inner(&self) -> &Arc<InnerClient> {
213 &self.inner
214 }
215
216 #[cfg(feature = "runtime")]
217 pub(crate) fn set_socket_config(&mut self, socket_config: SocketConfig) {
218 self.socket_config = Some(socket_config);
219 }
220
221 /// Creates a new prepared statement.
222 ///
223 /// Prepared statements can be executed repeatedly, and may contain query parameters (indicated by `$1`, `$2`, etc),
224 /// which are set when executed. Prepared statements can only be used with the connection that created them.
225 pub async fn prepare(&self, query: &str) -> Result<Statement, Error> {
226 self.prepare_typed(query, &[]).await
227 }
228
229 /// Like `prepare`, but allows the types of query parameters to be explicitly specified.
230 ///
231 /// The list of types may be smaller than the number of parameters - the types of the remaining parameters will be
232 /// inferred. For example, `client.prepare_typed(query, &[])` is equivalent to `client.prepare(query)`.
233 pub async fn prepare_typed(
234 &self,
235 query: &str,
236 parameter_types: &[Type],
237 ) -> Result<Statement, Error> {
238 prepare::prepare(&self.inner, query, parameter_types).await
239 }
240
241 /// Executes a statement, returning a vector of the resulting rows.
242 ///
243 /// A statement may contain parameters, specified by `$n`, where `n` is the index of the parameter of the list
244 /// provided, 1-indexed.
245 ///
246 /// The `statement` argument can either be a `Statement`, or a raw query string. If the same statement will be
247 /// repeatedly executed (perhaps with different query parameters), consider preparing the statement up front
248 /// with the `prepare` method.
249 pub async fn query<T>(
250 &self,
251 statement: &T,
252 params: &[&(dyn ToSql + Sync)],
253 ) -> Result<Vec<Row>, Error>
254 where
255 T: ?Sized + ToStatement,
256 {
257 self.query_raw(statement, slice_iter(params))
258 .await?
259 .try_collect()
260 .await
261 }
262
263 /// Executes a statement which returns a single row, returning it.
264 ///
265 /// Returns an error if the query does not return exactly one row.
266 ///
267 /// A statement may contain parameters, specified by `$n`, where `n` is the index of the parameter of the list
268 /// provided, 1-indexed.
269 ///
270 /// The `statement` argument can either be a `Statement`, or a raw query string. If the same statement will be
271 /// repeatedly executed (perhaps with different query parameters), consider preparing the statement up front
272 /// with the `prepare` method.
273 pub async fn query_one<T>(
274 &self,
275 statement: &T,
276 params: &[&(dyn ToSql + Sync)],
277 ) -> Result<Row, Error>
278 where
279 T: ?Sized + ToStatement,
280 {
281 self.query_opt(statement, params)
282 .await
283 .and_then(|res| res.ok_or_else(Error::row_count))
284 }
285
286 /// Executes a statements which returns zero or one rows, returning it.
287 ///
288 /// Returns an error if the query returns more than one row.
289 ///
290 /// A statement may contain parameters, specified by `$n`, where `n` is the index of the parameter of the list
291 /// provided, 1-indexed.
292 ///
293 /// The `statement` argument can either be a `Statement`, or a raw query string. If the same statement will be
294 /// repeatedly executed (perhaps with different query parameters), consider preparing the statement up front
295 /// with the `prepare` method.
296 pub async fn query_opt<T>(
297 &self,
298 statement: &T,
299 params: &[&(dyn ToSql + Sync)],
300 ) -> Result<Option<Row>, Error>
301 where
302 T: ?Sized + ToStatement,
303 {
304 let stream = self.query_raw(statement, slice_iter(params)).await?;
305 pin_mut!(stream);
306
307 let mut first = None;
308
309 // Originally this was two calls to `try_next().await?`,
310 // once for the first element, and second to error if more than one.
311 //
312 // However, this new form with only one .await in a loop generates
313 // slightly smaller codegen/stack usage for the resulting future.
314 while let Some(row) = stream.try_next().await? {
315 if first.is_some() {
316 return Err(Error::row_count());
317 }
318
319 first = Some(row);
320 }
321
322 Ok(first)
323 }
324
325 /// The maximally flexible version of [`query`].
326 ///
327 /// A statement may contain parameters, specified by `$n`, where `n` is the index of the parameter of the list
328 /// provided, 1-indexed.
329 ///
330 /// The `statement` argument can either be a `Statement`, or a raw query string. If the same statement will be
331 /// repeatedly executed (perhaps with different query parameters), consider preparing the statement up front
332 /// with the `prepare` method.
333 ///
334 /// [`query`]: #method.query
335 ///
336 /// # Examples
337 ///
338 /// ```no_run
339 /// # async fn async_main(client: &tokio_postgres::Client) -> Result<(), tokio_postgres::Error> {
340 /// use futures_util::{pin_mut, TryStreamExt};
341 ///
342 /// let params: Vec<String> = vec![
343 /// "first param".into(),
344 /// "second param".into(),
345 /// ];
346 /// let mut it = client.query_raw(
347 /// "SELECT foo FROM bar WHERE biz = $1 AND baz = $2",
348 /// params,
349 /// ).await?;
350 ///
351 /// pin_mut!(it);
352 /// while let Some(row) = it.try_next().await? {
353 /// let foo: i32 = row.get("foo");
354 /// println!("foo: {}", foo);
355 /// }
356 /// # Ok(())
357 /// # }
358 /// ```
359 pub async fn query_raw<T, P, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
360 where
361 T: ?Sized + ToStatement,
362 P: BorrowToSql,
363 I: IntoIterator<Item = P>,
364 I::IntoIter: ExactSizeIterator,
365 {
366 let statement = statement.__convert().into_statement(self).await?;
367 query::query(&self.inner, statement, params).await
368 }
369
370 /// Like `query_raw`, but allows specifying the result format (text or binary).
371 ///
372 /// With `ResultFormat::Text`, PostgreSQL returns column values as UTF-8 strings —
373 /// the same format the pg Node.js library receives. This is useful for building
374 /// driver adapters for ORMs that apply their own type parsing.
375 pub async fn query_raw_with_format<T, P, I>(
376 &self,
377 statement: &T,
378 params: I,
379 result_format: crate::ResultFormat,
380 ) -> Result<RowStream, Error>
381 where
382 T: ?Sized + ToStatement,
383 P: BorrowToSql,
384 I: IntoIterator<Item = P>,
385 I::IntoIter: ExactSizeIterator,
386 {
387 let statement = statement.__convert().into_statement(self).await?;
388 query::query_with_format(&self.inner, statement, params, result_format).await
389 }
390
391 /// Like `query`, but requires the types of query parameters to be explicitly specified.
392 ///
393 /// Compared to `query`, this method allows performing queries without three round trips (for
394 /// prepare, execute, and close) by requiring the caller to specify parameter values along with
395 /// their Postgres type. Thus, this is suitable in environments where prepared statements aren't
396 /// supported (such as Cloudflare Workers with Hyperdrive).
397 ///
398 /// A statement may contain parameters, specified by `$n`, where `n` is the index of the
399 /// parameter of the list provided, 1-indexed.
400 pub async fn query_typed(
401 &self,
402 query: &str,
403 params: &[(&(dyn ToSql + Sync), Type)],
404 ) -> Result<Vec<Row>, Error> {
405 self.query_typed_raw(query, params.iter().map(|(v, t)| (*v, t.clone())))
406 .await?
407 .try_collect()
408 .await
409 }
410
411 /// The maximally flexible version of [`query_typed`].
412 ///
413 /// Compared to `query`, this method allows performing queries without three round trips (for
414 /// prepare, execute, and close) by requiring the caller to specify parameter values along with
415 /// their Postgres type. Thus, this is suitable in environments where prepared statements aren't
416 /// supported (such as Cloudflare Workers with Hyperdrive).
417 ///
418 /// A statement may contain parameters, specified by `$n`, where `n` is the index of the
419 /// parameter of the list provided, 1-indexed.
420 ///
421 /// [`query_typed`]: #method.query_typed
422 ///
423 /// # Examples
424 ///
425 /// ```no_run
426 /// # async fn async_main(client: &tokio_postgres::Client) -> Result<(), tokio_postgres::Error> {
427 /// use futures_util::{pin_mut, TryStreamExt};
428 /// use tokio_postgres::types::Type;
429 ///
430 /// let params: Vec<(String, Type)> = vec![
431 /// ("first param".into(), Type::TEXT),
432 /// ("second param".into(), Type::TEXT),
433 /// ];
434 /// let mut it = client.query_typed_raw(
435 /// "SELECT foo FROM bar WHERE biz = $1 AND baz = $2",
436 /// params,
437 /// ).await?;
438 ///
439 /// pin_mut!(it);
440 /// while let Some(row) = it.try_next().await? {
441 /// let foo: i32 = row.get("foo");
442 /// println!("foo: {}", foo);
443 /// }
444 /// # Ok(())
445 /// # }
446 /// ```
447 pub async fn query_typed_raw<P, I>(&self, query: &str, params: I) -> Result<RowStream, Error>
448 where
449 P: BorrowToSql,
450 I: IntoIterator<Item = (P, Type)>,
451 {
452 query::query_typed(&self.inner, query, params).await
453 }
454
455 /// Executes a statement, returning the number of rows modified.
456 ///
457 /// A statement may contain parameters, specified by `$n`, where `n` is the index of the parameter of the list
458 /// provided, 1-indexed.
459 ///
460 /// The `statement` argument can either be a `Statement`, or a raw query string. If the same statement will be
461 /// repeatedly executed (perhaps with different query parameters), consider preparing the statement up front
462 /// with the `prepare` method.
463 ///
464 /// If the statement does not modify any rows (e.g. `SELECT`), 0 is returned.
465 pub async fn execute<T>(
466 &self,
467 statement: &T,
468 params: &[&(dyn ToSql + Sync)],
469 ) -> Result<u64, Error>
470 where
471 T: ?Sized + ToStatement,
472 {
473 self.execute_raw(statement, slice_iter(params)).await
474 }
475
476 /// The maximally flexible version of [`execute`].
477 ///
478 /// A statement may contain parameters, specified by `$n`, where `n` is the index of the parameter of the list
479 /// provided, 1-indexed.
480 ///
481 /// The `statement` argument can either be a `Statement`, or a raw query string. If the same statement will be
482 /// repeatedly executed (perhaps with different query parameters), consider preparing the statement up front
483 /// with the `prepare` method.
484 ///
485 /// [`execute`]: #method.execute
486 pub async fn execute_raw<T, P, I>(&self, statement: &T, params: I) -> Result<u64, Error>
487 where
488 T: ?Sized + ToStatement,
489 P: BorrowToSql,
490 I: IntoIterator<Item = P>,
491 I::IntoIter: ExactSizeIterator,
492 {
493 let statement = statement.__convert().into_statement(self).await?;
494 query::execute(self.inner(), statement, params).await
495 }
496
497 /// Executes a `COPY FROM STDIN` statement, returning a sink used to write the copy data.
498 ///
499 /// PostgreSQL does not support parameters in `COPY` statements, so this method does not take any. The copy *must*
500 /// be explicitly completed via the `Sink::close` or `finish` methods. If it is not, the copy will be aborted.
501 pub async fn copy_in<T, U>(&self, statement: &T) -> Result<CopyInSink<U>, Error>
502 where
503 T: ?Sized + ToStatement,
504 U: Buf + 'static + Send,
505 {
506 let statement = statement.__convert().into_statement(self).await?;
507 copy_in::copy_in(self.inner(), statement).await
508 }
509
510 /// Executes a `COPY TO STDOUT` statement, returning a stream of the resulting data.
511 ///
512 /// PostgreSQL does not support parameters in `COPY` statements, so this method does not take any.
513 pub async fn copy_out<T>(&self, statement: &T) -> Result<CopyOutStream, Error>
514 where
515 T: ?Sized + ToStatement,
516 {
517 let statement = statement.__convert().into_statement(self).await?;
518 copy_out::copy_out(self.inner(), statement).await
519 }
520
521 /// Executes a sequence of SQL statements using the simple query protocol, returning the resulting rows.
522 ///
523 /// Statements should be separated by semicolons. If an error occurs, execution of the sequence will stop at that
524 /// point. The simple query protocol returns the values in rows as strings rather than in their binary encodings,
525 /// so the associated row type doesn't work with the `FromSql` trait. Rather than simply returning a list of the
526 /// rows, this method returns a list of an enum which indicates either the completion of one of the commands,
527 /// or a row of data. This preserves the framing between the separate statements in the request.
528 ///
529 /// # Warning
530 ///
531 /// Prepared statements should be use for any query which contains user-specified data, as they provided the
532 /// functionality to safely embed that data in the request. Do not form statements via string concatenation and pass
533 /// them to this method!
534 pub async fn simple_query(&self, query: &str) -> Result<Vec<SimpleQueryMessage>, Error> {
535 self.simple_query_raw(query).await?.try_collect().await
536 }
537
538 pub(crate) async fn simple_query_raw(&self, query: &str) -> Result<SimpleQueryStream, Error> {
539 simple_query::simple_query(self.inner(), query).await
540 }
541
542 /// Executes a sequence of SQL statements using the simple query protocol.
543 ///
544 /// Statements should be separated by semicolons. If an error occurs, execution of the sequence will stop at that
545 /// point. This is intended for use when, for example, initializing a database schema.
546 ///
547 /// # Warning
548 ///
549 /// Prepared statements should be use for any query which contains user-specified data, as they provided the
550 /// functionality to safely embed that data in the request. Do not form statements via string concatenation and pass
551 /// them to this method!
552 pub async fn batch_execute(&self, query: &str) -> Result<(), Error> {
553 simple_query::batch_execute(self.inner(), query).await
554 }
555
556 /// Begins a new database transaction.
557 ///
558 /// The transaction will roll back by default - use the `commit` method to commit it.
559 pub async fn transaction(&mut self) -> Result<Transaction<'_>, Error> {
560 self.build_transaction().start().await
561 }
562
563 /// Returns a builder for a transaction with custom settings.
564 ///
565 /// Unlike the `transaction` method, the builder can be used to control the transaction's isolation level and other
566 /// attributes.
567 pub fn build_transaction(&mut self) -> TransactionBuilder<'_> {
568 TransactionBuilder::new(self)
569 }
570
571 /// Constructs a cancellation token that can later be used to request cancellation of a query running on the
572 /// connection associated with this client.
573 pub fn cancel_token(&self) -> CancelToken {
574 CancelToken {
575 #[cfg(feature = "runtime")]
576 socket_config: self.socket_config.clone(),
577 ssl_mode: self.ssl_mode,
578 ssl_negotiation: self.ssl_negotiation,
579 process_id: self.process_id,
580 secret_key: self.secret_key,
581 }
582 }
583
584 /// Attempts to cancel an in-progress query.
585 ///
586 /// The server provides no information about whether a cancellation attempt was successful or not. An error will
587 /// only be returned if the client was unable to connect to the database.
588 ///
589 /// Requires the `runtime` Cargo feature (enabled by default).
590 #[cfg(feature = "runtime")]
591 #[deprecated(since = "0.6.0", note = "use Client::cancel_token() instead")]
592 pub async fn cancel_query<T>(&self, tls: T) -> Result<(), Error>
593 where
594 T: MakeTlsConnect<Socket>,
595 {
596 self.cancel_token().cancel_query(tls).await
597 }
598
599 /// Like `cancel_query`, but uses a stream which is already connected to the server rather than opening a new
600 /// connection itself.
601 #[deprecated(since = "0.6.0", note = "use Client::cancel_token() instead")]
602 pub async fn cancel_query_raw<S, T>(&self, stream: S, tls: T) -> Result<(), Error>
603 where
604 S: AsyncRead + AsyncWrite + Unpin,
605 T: TlsConnect<S>,
606 {
607 self.cancel_token().cancel_query_raw(stream, tls).await
608 }
609
610 /// Clears the client's type information cache.
611 ///
612 /// When user-defined types are used in a query, the client loads their definitions from the database and caches
613 /// them for the lifetime of the client. If those definitions are changed in the database, this method can be used
614 /// to flush the local cache and allow the new, updated definitions to be loaded.
615 pub fn clear_type_cache(&self) {
616 self.inner().clear_type_cache();
617 }
618
619 /// Determines if the connection to the server has already closed.
620 ///
621 /// In that case, all future queries will fail.
622 pub fn is_closed(&self) -> bool {
623 self.inner.sender.is_closed()
624 }
625
626 #[doc(hidden)]
627 pub fn __private_api_close(&mut self) {
628 self.inner.sender.close_channel()
629 }
630
631 #[doc(hidden)]
632 pub fn __private_api_rollback(&self, name: Option<&str>) {
633 let buf = self.inner().with_buf(|buf| {
634 if let Some(name) = name {
635 frontend::query(&format!("ROLLBACK TO {}", name), buf).unwrap();
636 } else {
637 frontend::query("ROLLBACK", buf).unwrap();
638 }
639 buf.split().freeze()
640 });
641 let _ = self
642 .inner()
643 .send(RequestMessages::Single(FrontendMessage::Raw(buf)));
644 }
645}
646
647impl fmt::Debug for Client {
648 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
649 f.debug_struct("Client").finish()
650 }
651}