Trait Query

Source
pub trait Query {
    type Row: FromRow;

    // Required methods
    fn query_all(
        &self,
        connection: &mut impl GenericClient,
    ) -> Result<Vec<Self::Row>, Error>;
    fn query_opt(
        &self,
        connection: &mut impl GenericClient,
    ) -> Result<Option<Self::Row>, Error>;
    fn query_one(
        &self,
        connection: &mut impl GenericClient,
    ) -> Result<Self::Row, Error>;
}
Expand description

A Query is a SQL query that returns rows from the database.

§Example

Query can be derived like so:

#[derive(Query)]
#[query(
    // Write the query using named parameters
    sql = "
      SELECT *
      FROM Person
      WHERE (first_name = @name OR last_name = @name)
      AND alive = @alive",
    // Specify what type the rows should be decoded to
    row = Person
)]
struct GetPeople<'a> {
    // Define the query's parameters
    alive: bool,
    name: &'a str,
}

Note that the struct you specify for row must implement FromRow. You can do this by using #[derive(FromRow)], which you can get by adding postgres-from-row to your Cargo.toml. (Note: as of time of writing, postgres-from-row does not yet support borrowed fields.)

#[derive(FromRow, Debug)]
struct Person {
    first_name: String,
    last_name: String,
    hobby: Option<String>,
    alive: bool,
}

Your can then use your query like this:

fn main() -> Result<(), postgres::Error> {
    let connection_string = std::env::var("POSTGRES_CONNECTION_STRING")
        .unwrap_or("host=localhost user=postgres".to_owned());
    let mut db = postgres::Client::connect(&connection_string, postgres::NoTls)?;

    let people = GetPeople {
        alive: true,
        name: "John",
    }
    .query_all(&mut db)?;

    println!("Found: {:?}", people);
    Ok(())
}

At compile time, the SQL is transformed to use numbered parameters. For example, the above query will roughly desugar to:

let people: Vec<Person> = db.query(
    "SELECT *
     FROM Person
     WHERE (first_name = $2 OR last_name = $2)
     AND alive = $1",
    &[&true, &"John"],
)?
.iter()
.map(Person::try_from_row)
.collect::<Result<Vec<Person>,postgres::Error>>()?;

For a more thorough example (including bulk queries), see the example project folder in the GitHub repository.

§Notes

  • In order to use #[derive(Query), you must also provide the helper attribute #[statement(sql = "...", row = ...)
    • Both the sql and row parameters are required
    • The sql parameter must be a string literal
    • The row parameter must implement FromRow (see above).
  • At compile time, the derive macro will check that the parameter names you used in your query match the field names defined in the struct. A mismatch (e.g. using “@naame” instead of “@name” when the field name is name) will cause a compiler error.
  • If you want to include a single literal @ in your SQL, you must escape it by doubling it (@@)

Required Associated Types§

Source

type Row: FromRow

The type that each individual row returned from the query should decode to. You specify this type in the derive macro using the row parameter. Note that this type must implement FromRow on the struct you intend to decode each row to. You can do this by using #[derive(FromRow), which you can get by adding postgres-from-row to your Cargo.toml.

Required Methods§

Source

fn query_all( &self, connection: &mut impl GenericClient, ) -> Result<Vec<Self::Row>, Error>

Run the query and return all the rows in a vector.

For the sole argument you can pass either a database connection (i.e. postgres::Client) or a transaction (i.e. postgres::Transaction).

Source

fn query_opt( &self, connection: &mut impl GenericClient, ) -> Result<Option<Self::Row>, Error>

Run the query, expecting exactly one or zero rows. Return Ok(None) if there are no rows, and return an Err if there is more than one row. See also: query_one.

For the sole argument you can pass either a database connection (i.e. postgres::Client) or a transaction (i.e. postgres::Transaction).

Source

fn query_one( &self, connection: &mut impl GenericClient, ) -> Result<Self::Row, Error>

Run the query, expecting exactly one row. Return an Err if no rows or more than one row are returned. See also: query_opt.

For the sole argument you can pass either a database connection (i.e. postgres::Client) or a transaction (i.e. postgres::Transaction).

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§