[][src]Crate postgres_query

Helper macros and traits built around tokio-postgres to define queries with human readable parameters and return values.

Example

// Connect to the database
let client: Client = connect(/* ... */);

// Construct the query
let query = query!(
    "SELECT age, name FROM people WHERE age >= $min_age",
    min_age = 18
);

// Define the structure of the data returned from the query
#[derive(FromSqlRow)]
struct Person {
    age: i32,
    name: String,
}

// Execute the query
let people: Vec<Person> = query.fetch(&client).await?;

for person in people {
    println!("{} is {} years young", person.name, person.age);
}

Queries

The preferred way of constructing a new Query is through the query! macro. It uses a syntax similar to the format!(...) family of macros from the standard library. The first parameter is the SQL query and is always given as a string literal (this might be relaxed in the future). This string literal may contain parameter bindings on the form $ident where ident is any valid Rust identifier ($abc, $value_123, etc.).

let age = 42;
let insert_person = query!(
    "INSERT INTO people VALUES ($age, $name)",
    name = "John Wick", // Binds "$name" to "John Wick"
    age,                // Binds "$age" to the value of `age`
);

During compilation the query is converted into the format expected by PostgreSQL: parameter bindings are converted to using numbers ($1, $2, etc.) and the actual parameter values are put into a 1-indexed array. The code snippet above would be expanded into the following:

let age = 42;
let insert_person = Query {
    sql: "INSERT INTO people VALUES ($1, $2)",
    parameters: vec![&age, &"John Wick"],
};

Data Extraction

In addition to helping you define new queries this crate provides the FromSqlRow trait which makes it easy to extract typed values from the resulting rows. The easiest way to implement this trait for new structs is to use the included derive(FromSqlRow) macro.

  • If used on a tuple struct, values will be extracted from the corresponding columns based on their position in the tuple.
  • If used on a stuct with named fields, values will be extracted from the column with the same name as the field.
#[derive(FromSqlRow)]
struct TupleData(i32, String);

#[derive(FromSqlRow)]
struct NamedData {
    age: i32,
    name: String,
};

Caching queries

From time to time you probably want to execute the same query multiple times, but with different parameters. In times like these we can decrease the load on the database by preparing our queries before executing them. By wrapping a client in a Caching struct this behaviour is automatically provided for all queries that originate from this crate:

// Connect to the database
let client: Client = connect(/* ... */);

// Wrap the client in a query cache
let cached_client = Caching::new(client);

for age in 0..100i32 {
    let query = query!("SELECT name, weight FROM people WHERE age = $age", age);

    // The query is prepared and cached the first time it's executed.
    // All subsequent fetches will use the cached Statement.
    let people: Vec<(String, i32)> = query.fetch(&cached_client).await?;
     
    /* Do something with people */
}

Re-exports

pub use extract::FromSqlRow;

Modules

client

Abstractions over client-like types.

execute

Executing queries through a client.

extract

Extract typed values from rows.

Macros

query

Constructs a new query.

Structs

Caching

A client wrapper which caches prepared queries.

Query

A static query with dynamic parameters.

Enums

Error

Any error that this crate may produce.

Type Definitions

Result

Derive Macros

FromSqlRow

Extract values from a row.