rust-postgres/tokio-postgres/src/lib.rs

233 lines
7.5 KiB
Rust
Raw Normal View History

2019-01-06 05:39:08 +00:00
//! An asynchronous, pipelined, PostgreSQL client.
//!
//! # Example
//!
//! ```no_run
2019-11-05 19:55:59 +00:00
//! use tokio_postgres::{NoTls, Error};
2019-01-06 05:39:08 +00:00
//!
2019-08-02 01:43:38 +00:00
//! # #[cfg(not(feature = "runtime"))] fn main() {}
2019-01-06 05:39:08 +00:00
//! # #[cfg(feature = "runtime")]
2019-07-31 04:25:30 +00:00
//! #[tokio::main] // By default, tokio_postgres uses the tokio crate as its runtime.
2019-07-30 01:54:59 +00:00
//! async fn main() -> Result<(), Error> {
//! // Connect to the database.
2019-11-05 19:55:59 +00:00
//! let (client, connection) =
2019-07-31 04:25:30 +00:00
//! tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
2019-07-30 01:54:59 +00:00
//!
//! // The connection object performs the actual communication with the database,
//! // so spawn it off to run on its own.
2019-11-05 17:56:38 +00:00
//! tokio::spawn(async move {
//! if let Err(e) = connection.await {
2019-07-30 01:54:59 +00:00
//! eprintln!("connection error: {}", e);
//! }
//! });
//!
//! // Now we can prepare a simple statement that just returns its parameter.
//! let stmt = client.prepare("SELECT $1::TEXT").await?;
//!
2019-11-05 17:56:38 +00:00
//! // And then execute it, returning a list of the resulting rows.
//! let rows = client
2019-07-30 01:54:59 +00:00
//! .query(&stmt, &[&"hello world"])
//! .await?;
2019-01-06 05:39:08 +00:00
//!
//! // Now we can check that we got back the same string we sent over.
2019-07-30 01:54:59 +00:00
//! let value: &str = rows[0].get(0);
//! assert_eq!(value, "hello world");
2019-01-06 05:39:08 +00:00
//!
2019-07-30 01:54:59 +00:00
//! Ok(())
//! }
2019-01-06 05:39:08 +00:00
//! ```
//!
2019-01-18 04:45:51 +00:00
//! # Behavior
//!
//! Calling a method like `Client::query` on its own does nothing. The associated request is not sent to the database
//! until the future returned by the method is first polled. Requests are executed in the order that they are first
//! polled, not in the order that their futures are created.
//!
2019-01-06 05:39:08 +00:00
//! # Pipelining
//!
//! The client supports *pipelined* requests. Pipelining can improve performance in use cases in which multiple,
//! independent queries need to be executed. In a traditional workflow, each query is sent to the server after the
//! previous query completes. In contrast, pipelining allows the client to send all of the queries to the server up
2019-01-08 04:43:52 +00:00
//! front, minimizing time spent by one side waiting for the other to finish sending data:
2019-01-06 05:39:08 +00:00
//!
//! ```not_rust
//! Sequential Pipelined
//! | Client | Server | | Client | Server |
//! |----------------|-----------------| |----------------|-----------------|
//! | send query 1 | | | send query 1 | |
//! | | process query 1 | | send query 2 | process query 1 |
//! | receive rows 1 | | | send query 3 | process query 2 |
//! | send query 2 | | | receive rows 1 | process query 3 |
//! | | process query 2 | | receive rows 2 | |
//! | receive rows 2 | | | receive rows 3 | |
//! | send query 3 | |
//! | | process query 3 |
//! | receive rows 3 | |
//! ```
//!
//! In both cases, the PostgreSQL server is executing the queries sequentially - pipelining just allows both sides of
//! the connection to work concurrently when possible.
//!
//! Pipelining happens automatically when futures are polled concurrently (for example, by using the futures `join`
2019-01-15 06:08:13 +00:00
//! combinator):
//!
//! ```rust
2019-07-30 01:54:59 +00:00
//! use futures::future;
//! use std::future::Future;
2019-01-15 06:08:13 +00:00
//! use tokio_postgres::{Client, Error, Statement};
//!
2019-09-28 14:48:15 +00:00
//! async fn pipelined_prepare(
//! client: &Client,
//! ) -> Result<(Statement, Statement), Error>
2019-01-15 06:08:13 +00:00
//! {
2019-07-30 01:54:59 +00:00
//! future::try_join(
//! client.prepare("SELECT * FROM foo"),
//! client.prepare("INSERT INTO bar (id, name) VALUES ($1, $2)")
2019-09-28 14:48:15 +00:00
//! ).await
2019-01-15 06:08:13 +00:00
//! }
//! ```
2019-01-06 05:39:08 +00:00
//!
//! # Runtime
//!
//! The client works with arbitrary `AsyncRead + AsyncWrite` streams. Convenience APIs are provided to handle the
//! connection process, but these are gated by the `runtime` Cargo feature, which is enabled by default. If disabled,
//! all dependence on the tokio runtime is removed.
2019-04-02 04:56:25 +00:00
//!
//! # SSL/TLS support
//!
//! TLS support is implemented via external libraries. `Client::connect` and `Config::connect` take a TLS implementation
//! as an argument. The `NoTls` type in this crate can be used when TLS is not required. Otherwise, the
//! `postgres-openssl` and `postgres-native-tls` crates provide implementations backed by the `openssl` and `native-tls`
//! crates, respectively.
2019-10-15 01:14:11 +00:00
#![doc(html_root_url = "https://docs.rs/tokio-postgres/0.5")]
2019-03-05 05:22:50 +00:00
#![warn(rust_2018_idioms, clippy::all, missing_docs)]
2019-07-23 03:17:29 +00:00
pub use crate::client::Client;
pub use crate::config::Config;
pub use crate::connection::Connection;
pub use crate::copy_in::CopyInSink;
2019-11-27 00:32:36 +00:00
pub use crate::copy_out::CopyStream;
2019-07-23 04:27:21 +00:00
use crate::error::DbError;
2019-07-23 03:17:29 +00:00
pub use crate::error::Error;
2019-08-02 03:43:13 +00:00
pub use crate::portal::Portal;
2019-10-16 01:17:10 +00:00
pub use crate::query::RowStream;
2019-07-25 02:18:15 +00:00
pub use crate::row::{Row, SimpleQueryRow};
2019-10-16 01:17:10 +00:00
pub use crate::simple_query::SimpleQueryStream;
2019-07-23 03:17:29 +00:00
#[cfg(feature = "runtime")]
pub use crate::socket::Socket;
pub use crate::statement::{Column, Statement};
2019-07-23 03:17:29 +00:00
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
pub use crate::tls::NoTls;
pub use crate::to_statement::ToStatement;
2019-07-31 04:25:30 +00:00
pub use crate::transaction::Transaction;
use crate::types::ToSql;
2019-08-02 03:43:13 +00:00
mod bind;
2019-07-30 04:36:07 +00:00
#[cfg(feature = "runtime")]
mod cancel_query;
mod cancel_query_raw;
mod client;
mod codec;
pub mod config;
2019-07-23 03:17:29 +00:00
#[cfg(feature = "runtime")]
mod connect;
mod connect_raw;
2019-07-23 03:17:29 +00:00
#[cfg(feature = "runtime")]
mod connect_socket;
mod connect_tls;
mod connection;
2019-07-31 04:25:30 +00:00
mod copy_in;
2019-08-01 04:19:56 +00:00
mod copy_out;
pub mod error;
mod maybe_tls_stream;
2019-08-02 03:43:13 +00:00
mod portal;
2019-07-24 02:54:22 +00:00
mod prepare;
2019-07-25 02:18:15 +00:00
mod query;
pub mod row;
2019-07-28 22:52:46 +00:00
mod simple_query;
2019-07-23 03:17:29 +00:00
#[cfg(feature = "runtime")]
mod socket;
2019-07-24 02:54:22 +00:00
mod statement;
pub mod tls;
mod to_statement;
2019-07-31 04:25:30 +00:00
mod transaction;
2018-12-09 01:39:20 +00:00
pub mod types;
2019-07-23 03:17:29 +00:00
/// A convenience function which parses a connection string and connects to the database.
///
/// See the documentation for [`Config`] for details on the connection string format.
///
/// Requires the `runtime` Cargo feature (enabled by default).
///
2019-09-08 23:54:57 +00:00
/// [`Config`]: config/struct.Config.html
2019-07-23 03:17:29 +00:00
#[cfg(feature = "runtime")]
pub async fn connect<T>(
config: &str,
tls: T,
) -> Result<(Client, Connection<Socket, T::Stream>), Error>
where
T: MakeTlsConnect<Socket>,
{
let config = config.parse::<Config>()?;
2019-09-23 22:52:27 +00:00
config.connect(tls).await
2019-07-23 03:17:29 +00:00
}
2019-07-23 04:27:21 +00:00
/// An asynchronous notification.
#[derive(Clone, Debug)]
pub struct Notification {
process_id: i32,
channel: String,
payload: String,
}
2019-08-02 01:44:38 +00:00
impl Notification {
/// The process ID of the notifying backend process.
pub fn process_id(&self) -> i32 {
self.process_id
}
/// The name of the channel that the notify has been raised on.
pub fn channel(&self) -> &str {
&self.channel
}
/// The "payload" string passed from the notifying process.
pub fn payload(&self) -> &str {
&self.payload
}
}
2019-07-23 04:27:21 +00:00
/// An asynchronous message from the server.
#[allow(clippy::large_enum_variant)]
pub enum AsyncMessage {
/// A notice.
///
/// Notices use the same format as errors, but aren't "errors" per-se.
Notice(DbError),
/// A notification.
///
/// Connections can subscribe to notifications with the `LISTEN` command.
Notification(Notification),
#[doc(hidden)]
__NonExhaustive,
}
2019-07-28 22:52:46 +00:00
/// Message returned by the `SimpleQuery` stream.
pub enum SimpleQueryMessage {
/// A row of data.
Row(SimpleQueryRow),
/// A statement in the query has completed.
///
/// The number of rows modified or selected is returned.
CommandComplete(u64),
#[doc(hidden)]
__NonExhaustive,
}
fn slice_iter<'a>(
s: &'a [&'a (dyn ToSql + Sync)],
) -> impl ExactSizeIterator<Item = &'a dyn ToSql> + 'a {
s.iter().map(|s| *s as _)
}