pub(crate) fn push_equalities(
builder: &mut crate::sql::Builder,
separator: &'static str,
pairs: &[(&str, Option<&str>)],
) -> &'static str {
let mut separator = separator;
for (column, value) in pairs {
if let Some(value) = value {
builder
.push(separator)
.push(column)
.push_bind((*value).to_string());
separator = " AND ";
}
}
separator
}
pub(crate) const WHERE: &str = " WHERE ";
#[cfg(test)]
mod tests {
use super::*;
fn sql_of(pairs: &[(&str, Option<&str>)]) -> (String, &'static str) {
let mut builder = crate::sql::Builder::new(crate::sql::Dialect::Sqlite, "SELECT 1 FROM t");
let next = push_equalities(&mut builder, WHERE, pairs);
(builder.sql().to_string(), next)
}
#[test]
fn the_first_predicate_opens_the_clause_and_the_rest_extend_it() {
let (sql, next) = sql_of(&[("a = ", Some("x")), ("b = ", Some("y"))]);
assert_eq!(sql, "SELECT 1 FROM t WHERE a = ? AND b = ?");
assert_eq!(next, " AND ", "a caller with more predicates continues");
}
#[test]
fn a_none_contributes_nothing_and_does_not_consume_the_where() {
let (sql, next) = sql_of(&[("a = ", None), ("b = ", Some("y"))]);
assert_eq!(sql, "SELECT 1 FROM t WHERE b = ?");
assert_eq!(next, " AND ");
}
#[test]
fn all_none_leaves_the_clause_unopened() {
let (sql, next) = sql_of(&[("a = ", None), ("b = ", None)]);
assert_eq!(sql, "SELECT 1 FROM t");
assert_eq!(next, WHERE);
}
#[test]
fn a_value_is_bound_not_interpolated() {
let (sql, _) = sql_of(&[("a = ", Some("' OR 1=1 --"))]);
assert_eq!(sql, "SELECT 1 FROM t WHERE a = ?");
}
}