tokio_postgres_cursor/lib.rs
1//! [`tokio-postgres`](https://docs.rs/tokio-postgres) extension to support forward fetching cursors.
2//!
3//! # Example
4//! ```no_run
5//! use futures::StreamExt;
6//!
7//! use tokio_postgres::{Error, NoTls};
8//! use tokio_postgres_cursor::TransactionExt;
9//!
10//! #[tokio::main]
11//! async fn main() -> Result<(), Error> {
12//! let (mut client, connection) =
13//! tokio_postgres::connect("host=localhost user=postgres", NoTls).await?;
14//!
15//! tokio::spawn(async move {
16//! if let Err(e) = connection.await {
17//! eprintln!("connection error: {}", e);
18//! }
19//! });
20//!
21//! // Cursors require to be declared inside a transaction
22//! let tx = client.transaction().await?;
23//!
24//! // Following line will declare cursor inside transaction and return CursorStream
25//! let mut cursor_stream = tx.query_cursor("SELECT * FROM my_table", 10).await?;
26//!
27//! // Fetch rows in batches of 10
28//! while let Some(result) = cursor_stream.next().await {
29//! match result {
30//! Ok(rows) => {
31//! for row in rows {
32//! println!("{row:?}");
33//! }
34//! }
35//! Err(e) => eprintln!("{e}"),
36//! }
37//! }
38//!
39//! // Explicitly closing cursor
40//! cursor_stream.close().await?;
41//! tx.commit().await?;
42//! Ok(())
43//! }
44//! ```
45//!
46//! # Queries
47//! [`query_cursor`](crate::cursor::ext::TransactionExt::query_cursor) will create
48//! a new instance of [`CursorStream`]
49//! which will execute the following query to declare a cursor:
50//! ```sql
51//! DECLARE <cursor> NO SCROLL CURSOR FOR <query>
52//! ```
53//!
54//! [`CursorStream`] implements
55//! [`Stream`](https://docs.rs/futures/latest/futures/stream/trait.Stream.html) trait
56//! and will execute the following query to fetch rows in batches:
57//! ```sql
58//! FETCH FORWARD <batch_size> FROM <cursor>
59//! ```
60//! Cursor won't be closed automatically when the stream is exhausted,
61//! subsequent polls of [`CursorStream`] will return [`None`].
62//!
63//! Cursor can be closed manually by using [`close`](crate::cursor::stream::CursorStream::close).
64//! It doesn't leak outside of transaction and will be closed automatically when transaction ends.
65//!
66//! # Vulnerabilities
67//! It's up to the user to ensure that the query passed to
68//! [`query_cursor`](crate::cursor::ext::TransactionExt::query_cursor) is safe
69//! from SQL injection vulnerabilities.
70
71mod cursor;
72
73pub use crate::cursor::ext::TransactionExt;
74pub use crate::cursor::stream::CursorStream;