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
androw
parameters are required - The
sql
parameter must be a string literal - The
row
parameter must implement FromRow (see above).
- Both the
- 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§
Sourcetype Row: FromRow
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§
Sourcefn query_all(
&self,
connection: &mut impl GenericClient,
) -> Result<Vec<Self::Row>, Error>
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).
Sourcefn query_opt(
&self,
connection: &mut impl GenericClient,
) -> Result<Option<Self::Row>, Error>
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).
Sourcefn query_one(
&self,
connection: &mut impl GenericClient,
) -> Result<Self::Row, Error>
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.