keelson_core/clause/
where_.rs1use crate::expr::{Expr, IntoExpr};
2use crate::writer::{Expression, SqlWriter};
3
4#[derive(Debug, Clone, Default)]
11pub struct Where {
12 pub conditions: Vec<Expr>,
14}
15
16impl Where {
17 pub fn append_where(&mut self, condition: impl IntoExpr) {
19 self.conditions.push(condition.into_expr());
20 }
21
22 pub fn is_empty(&self) -> bool {
24 self.conditions.is_empty()
25 }
26}
27
28impl Expression for Where {
29 fn write_sql(&self, w: &mut SqlWriter<'_>) {
30 w.write_slice(&self.conditions, "WHERE ", " AND ", "");
31 }
32}
33
34pub trait HasWhere {
41 fn where_mut(&mut self) -> &mut Where;
43}
44
45impl HasWhere for Where {
46 fn where_mut(&mut self) -> &mut Where {
47 self
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use keelson_sqlcheck::testing::assert_frag_sql;
54
55 use super::*;
56 use crate::dialect::testing::Numbered;
57 use crate::expr::{Chain, arg, or, quote};
58 use crate::value::Value;
59 use crate::writer::build;
60
61 const FRAME: &str = r#"SELECT "id" FROM users {}"#;
65
66 fn sql(e: &impl Expression) -> String {
67 build(&Numbered, e).expect("render").0
68 }
69
70 #[test]
71 fn an_empty_where_writes_nothing_not_even_the_keyword() {
72 let (sql, args) = build(&Numbered, &Where::default()).unwrap();
75 assert_frag_sql(FRAME, &sql, "");
76 assert!(args.is_empty());
77 assert!(Where::default().is_empty());
78 }
79
80 #[test]
81 fn conditions_are_and_joined_and_numbered_in_order() {
82 let mut wh = Where::default();
83 wh.append_where(quote("age").eq(arg(30i32)));
84 wh.append_where(quote("name").eq(arg("kubo")));
85 wh.append_where("email IS NULL");
87
88 let (sql, args) = build(&Numbered, &wh).unwrap();
89 assert_frag_sql(
90 FRAME,
91 &sql,
92 r#"WHERE ("age" = $1) AND ("name" = $2) AND email IS NULL"#,
93 );
94 assert_eq!(args, vec![Value::I32(30), Value::Text("kubo".into())]);
95 }
96
97 #[test]
98 fn a_disjunction_is_one_condition() {
99 let mut wh = Where::default();
100 wh.append_where(or((
101 quote("age").eq(arg(30i32)),
102 quote("name").eq(arg("kubo")),
103 )));
104 assert_frag_sql(FRAME, &sql(&wh), r#"WHERE (("age" = $1) OR ("name" = $2))"#);
105 }
106}