1use crate::{
2 condition::{Condition, ConditionKind},
3 group::{Conjunction, Group, Node},
4 order::Order,
5 value::Value,
6};
7
8#[derive(Clone)]
9pub struct Query {
10 pub(crate) nodes: Vec<Node>,
11 pub(crate) order: Option<(String, Order)>,
12 pub(crate) limit: Option<u64>,
13 pub(crate) offset: Option<u64>,
14}
15
16impl Query {
17 pub fn new() -> Self {
18 Self { nodes: vec![], order: None, limit: None, offset: None }
19 }
20
21 fn push(mut self, kind: ConditionKind, values: Vec<Value>) -> Self {
22 self.nodes.push(Node::Cond(Condition { kind, values }));
23 self
24 }
25
26 pub fn eq(self, col: &str, val: impl Into<Value>) -> Self {
27 self.push(ConditionKind::Eq(col.into()), vec![val.into()])
28 }
29
30 pub fn ne(self, col: &str, val: impl Into<Value>) -> Self {
31 self.push(ConditionKind::Ne(col.into()), vec![val.into()])
32 }
33
34 pub fn gt(self, col: &str, val: impl Into<Value>) -> Self {
35 self.push(ConditionKind::Gt(col.into()), vec![val.into()])
36 }
37
38 pub fn gte(self, col: &str, val: impl Into<Value>) -> Self {
39 self.push(ConditionKind::Gte(col.into()), vec![val.into()])
40 }
41
42 pub fn lt(self, col: &str, val: impl Into<Value>) -> Self {
43 self.push(ConditionKind::Lt(col.into()), vec![val.into()])
44 }
45
46 pub fn lte(self, col: &str, val: impl Into<Value>) -> Self {
47 self.push(ConditionKind::Lte(col.into()), vec![val.into()])
48 }
49
50 pub fn is_null(self, col: &str) -> Self {
51 self.push(ConditionKind::IsNull(col.into()), vec![])
52 }
53
54 pub fn is_not_null(self, col: &str) -> Self {
55 self.push(ConditionKind::IsNotNull(col.into()), vec![])
56 }
57
58 pub fn filter_optional(self, col: &str, val: Option<impl Into<Value>>) -> Self {
59 let v = val.map(Into::into).unwrap_or(Value::Null);
60 self.push(ConditionKind::FilterOptional(col.into()), vec![v])
61 }
62
63 pub fn filter_optional_gte(self, col: &str, val: Option<impl Into<Value>>) -> Self {
64 let v = val.map(Into::into).unwrap_or(Value::Null);
65 self.push(ConditionKind::FilterOptionalGte(col.into()), vec![v])
66 }
67
68 pub fn filter_optional_lte(self, col: &str, val: Option<impl Into<Value>>) -> Self {
69 let v = val.map(Into::into).unwrap_or(Value::Null);
70 self.push(ConditionKind::FilterOptionalLte(col.into()), vec![v])
71 }
72
73 pub fn in_<T: Into<Value>>(self, col: &str, vals: Vec<T>) -> Self {
74 let values = vals.into_iter().map(Into::into).collect();
75 self.push(ConditionKind::In(col.into()), values)
76 }
77
78 pub fn not_in<T: Into<Value>>(self, col: &str, vals: Vec<T>) -> Self {
79 let values = vals.into_iter().map(Into::into).collect();
80 self.push(ConditionKind::NotIn(col.into()), values)
81 }
82
83 pub fn like(self, col: &str, pat: impl Into<Value>) -> Self {
84 self.push(ConditionKind::Like(col.into()), vec![pat.into()])
85 }
86
87 pub fn not_like(self, col: &str, pat: impl Into<Value>) -> Self {
88 self.push(ConditionKind::NotLike(col.into()), vec![pat.into()])
89 }
90
91 pub fn between(self, col: &str, lo: impl Into<Value>, hi: impl Into<Value>) -> Self {
92 self.push(ConditionKind::Between(col.into()), vec![lo.into(), hi.into()])
93 }
94
95 pub fn or(mut self, f: impl FnOnce(Query) -> Query) -> Self {
96 let inner = f(Query::new());
97 self.nodes.push(Node::Group(Group { conjunction: Conjunction::Or, nodes: inner.nodes }));
98 self
99 }
100
101 pub fn and(mut self, f: impl FnOnce(Query) -> Query) -> Self {
102 let inner = f(Query::new());
103 self.nodes.push(Node::Group(Group { conjunction: Conjunction::And, nodes: inner.nodes }));
104 self
105 }
106
107 pub fn order_by(mut self, col: &str, dir: Order) -> Self {
108 self.order = Some((col.into(), dir));
109 self
110 }
111
112 pub fn limit(mut self, n: u64) -> Self { self.limit = Some(n); self }
113 pub fn offset(mut self, n: u64) -> Self { self.offset = Some(n); self }
114}
115
116impl Default for Query {
117 fn default() -> Self { Self::new() }
118}