[][src]Macro postgres_query::query_dyn

macro_rules! query_dyn {
    ($($tt:tt)*) => { ... };
}

Constructs a new query dynamically at runtime. See also query!.

Usage

This macro expands to an expression with the type Result<Query>.

The first parameter is the SQL query and is always given as a &str. This string may contain parameter bindings on the form $ident where ident is any valid Rust identifier ($abc, $value_123, etc.). The order of the parameters does not matter.

// We can construct the actual query at runtime
let mut sql = "INSERT INTO people VALUES".to_owned();
sql.push_str("($age, $name)");

let age = 42;

let insert_person = query_dyn!(
    &sql,
    name = "John Wick", // Binds "$name" to "John Wick"
    age,                // Binds "$age" to the value of `age`
)?;

The query and all the parameters are passed into Query::parse, so the above would be expanded into:

// We can construct the actual query at runtime
let mut sql = "INSERT INTO people VALUES".to_string();
sql.push_str("($age, $name)");

let age = 42;

let insert_person = Query::parse(
    &sql,
    &[("name", &"John Wick"), ("age", &age)],
);

Dynamic Binding

Optionally, you may also choose to include additional bindings at runtime by using the ..bindings syntax. This is supported for any type that implements IntoIterator<Item = (&str, Parameter)>, ie. Vec<(&str, Parameter)>, HashMap<&str, Parameter>, Option<(&str, Parameter)>, iterators, and so on.

Dynamic bindings may be mixed with static bindings:

let mut bindings = Vec::new();

// We use the `as Parameter` to please the type checker.
// Alternatively, we could specify the type for bindings: `Vec<(&str, Parameter)>`.
bindings.push(("age", &42 as Parameter));
bindings.push(("name", &"John Wick" as Parameter));

let sql = "INSERT INTO people VALUES ($age, $name, $height)".to_string();
let insert_person = query_dyn!(
    &sql,
    height = 192,
    ..bindings,
)?;

A larger example

Let's say that we wanted to dynamically add filters to our query:

// We have the query we want to execute
let mut sql = "SELECT * FROM people".to_string();

// and some filters we got from the user.
let age_filter: Option<i32> = Some(32);
let name_filter: Option<&str> = None;

// Then we dynamically build a list of filters and bindings to use:
let mut filters = Vec::new();
let mut bindings = Vec::new();

// We add the filters as needed.
if let Some(age) = age_filter.as_ref() {
    filters.push("age > $min_age");
    bindings.push(("min_age", age as Parameter));
}

if let Some(name) = name_filter.as_ref() {
    filters.push("name LIKE $name");
    bindings.push(("name", name as Parameter));
}

// And add them to the query.
if filters.len() > 0 {
    sql += &format!(" WHERE {}", filters.join(" AND "));
}

// Then we can use it as normal.
let query: Query = query_dyn!(&sql, ..bindings)?;