[−][src]Macro postgres_query::query_dyn
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)?;