1 unstable release
0.7.0 | Apr 29, 2023 |
---|
#2285 in Database interfaces
90 downloads per month
35KB
506 lines
tokio-postgres-extractor
This crate contains traits and proc macros for creating high-performance extractors for Rust types from tokio-postgres Rows.
License
This project is licensed under either of
- Apache License, Version 2.0
- MIT License
at your option.
lib.rs
:
High-performance extractors for [tokio_postgres].
This crate contains traits and proc macros for creating high-performance extractors
for Rust types from [Row
]s.
Examples
Extracting a single row
#[derive(Columns, Extract)]
struct User {
id: i32,
name: String,
}
async fn get_user(client: &Client, id: i32) -> Result<User, Error> {
client
.query_one("select * from user where id = $1", &[&id])
.await
.map(|r| r.extract_once())
}
Extracting a stream of rows
#[derive(Columns, Extract)]
struct User {
id: i32,
name: String,
}
async fn get_users(client: &Client) -> Result<Vec<User>, Error> {
client
.query_raw("select * from user", None::<i32>)
.await?
.extract()
.try_collect()
.await
}
Generic types
Generic types are fully supported.
#[derive(Columns, Extract)]
struct User<'a, T: ?Sized> {
id: i32,
name: &'a T,
}
fn assert_is_extract<'a, T: Extract<'a>>() { }
assert_is_extract::<User<str>>();
Custom column names
You can specify column names that are different from field names. See the
documentation of the [Columns
][macro@Columns] proc macro.
Design
A naive mapping function such as
User {
id: row.get("id"),
name: row.get("name"),
}
has O(N^2)
runtime where N
is the number of columns. Each invocation of row.get
must walk all columns and compare their name to the name of the requested column. This
crate solves this by
-
Constructing an efficient data structure at compile time that reduces lookup time to
O(N)
.This data structure is similar to a perfect hash function but more efficient.
-
Memorizing the mapping from fields to columns whenever possible.
Dependencies
~7–16MB
~218K SLoC