icydb_core/db/query/predicate/
ast.rs1use crate::{
2 db::query::predicate::coercion::{CoercionId, CoercionSpec},
3 value::Value,
4};
5use std::ops::{BitAnd, BitOr};
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25#[repr(u8)]
26pub enum CompareOp {
27 Eq = 0x01,
28 Ne = 0x02,
29 Lt = 0x03,
30 Lte = 0x04,
31 Gt = 0x05,
32 Gte = 0x06,
33 In = 0x07,
34 NotIn = 0x08,
35 Contains = 0x09,
36 StartsWith = 0x0a,
37 EndsWith = 0x0b,
38}
39
40impl CompareOp {
41 #[must_use]
42 pub const fn tag(self) -> u8 {
43 self as u8
44 }
45}
46
47#[derive(Clone, Debug, Eq, PartialEq)]
52pub struct ComparePredicate {
53 pub field: String,
54 pub op: CompareOp,
55 pub value: Value,
56 pub coercion: CoercionSpec,
57}
58
59impl ComparePredicate {
60 fn new(field: String, op: CompareOp, value: Value) -> Self {
61 Self {
62 field,
63 op,
64 value,
65 coercion: CoercionSpec::default(),
66 }
67 }
68
69 #[must_use]
71 pub fn with_coercion(
72 field: impl Into<String>,
73 op: CompareOp,
74 value: Value,
75 coercion: CoercionId,
76 ) -> Self {
77 Self {
78 field: field.into(),
79 op,
80 value,
81 coercion: CoercionSpec::new(coercion),
82 }
83 }
84
85 #[must_use]
86 pub fn eq(field: String, value: Value) -> Self {
87 Self::new(field, CompareOp::Eq, value)
88 }
89
90 #[must_use]
91 pub fn ne(field: String, value: Value) -> Self {
92 Self::new(field, CompareOp::Ne, value)
93 }
94
95 #[must_use]
96 pub fn lt(field: String, value: Value) -> Self {
97 Self::new(field, CompareOp::Lt, value)
98 }
99
100 #[must_use]
101 pub fn lte(field: String, value: Value) -> Self {
102 Self::new(field, CompareOp::Lte, value)
103 }
104
105 #[must_use]
106 pub fn gt(field: String, value: Value) -> Self {
107 Self::new(field, CompareOp::Gt, value)
108 }
109
110 #[must_use]
111 pub fn gte(field: String, value: Value) -> Self {
112 Self::new(field, CompareOp::Gte, value)
113 }
114
115 #[must_use]
116 pub fn in_(field: String, values: Vec<Value>) -> Self {
117 Self::new(field, CompareOp::In, Value::List(values))
118 }
119
120 #[must_use]
121 pub fn not_in(field: String, values: Vec<Value>) -> Self {
122 Self::new(field, CompareOp::NotIn, Value::List(values))
123 }
124}
125
126#[derive(Clone, Debug, Eq, PartialEq)]
131pub enum Predicate {
132 True,
133 False,
134 And(Vec<Self>),
135 Or(Vec<Self>),
136 Not(Box<Self>),
137 Compare(ComparePredicate),
138 IsNull { field: String },
139 IsMissing { field: String },
140 IsEmpty { field: String },
141 IsNotEmpty { field: String },
142 TextContains { field: String, value: Value },
143 TextContainsCi { field: String, value: Value },
144}
145
146impl Predicate {
147 #[must_use]
148 pub const fn and(preds: Vec<Self>) -> Self {
149 Self::And(preds)
150 }
151
152 #[must_use]
153 pub const fn or(preds: Vec<Self>) -> Self {
154 Self::Or(preds)
155 }
156
157 #[must_use]
158 #[expect(clippy::should_implement_trait)]
159 pub fn not(pred: Self) -> Self {
160 Self::Not(Box::new(pred))
161 }
162
163 #[must_use]
164 pub fn eq(field: String, value: Value) -> Self {
165 Self::Compare(ComparePredicate::eq(field, value))
166 }
167
168 #[must_use]
169 pub fn ne(field: String, value: Value) -> Self {
170 Self::Compare(ComparePredicate::ne(field, value))
171 }
172
173 #[must_use]
174 pub fn lt(field: String, value: Value) -> Self {
175 Self::Compare(ComparePredicate::lt(field, value))
176 }
177
178 #[must_use]
179 pub fn lte(field: String, value: Value) -> Self {
180 Self::Compare(ComparePredicate::lte(field, value))
181 }
182
183 #[must_use]
184 pub fn gt(field: String, value: Value) -> Self {
185 Self::Compare(ComparePredicate::gt(field, value))
186 }
187
188 #[must_use]
189 pub fn gte(field: String, value: Value) -> Self {
190 Self::Compare(ComparePredicate::gte(field, value))
191 }
192
193 #[must_use]
194 pub fn in_(field: String, values: Vec<Value>) -> Self {
195 Self::Compare(ComparePredicate::in_(field, values))
196 }
197
198 #[must_use]
199 pub fn not_in(field: String, values: Vec<Value>) -> Self {
200 Self::Compare(ComparePredicate::not_in(field, values))
201 }
202}
203
204impl BitAnd for Predicate {
205 type Output = Self;
206
207 fn bitand(self, rhs: Self) -> Self::Output {
208 Self::And(vec![self, rhs])
209 }
210}
211
212impl BitAnd for &Predicate {
213 type Output = Predicate;
214
215 fn bitand(self, rhs: Self) -> Self::Output {
216 Predicate::And(vec![self.clone(), rhs.clone()])
217 }
218}
219
220impl BitOr for Predicate {
221 type Output = Self;
222
223 fn bitor(self, rhs: Self) -> Self::Output {
224 Self::Or(vec![self, rhs])
225 }
226}
227
228impl BitOr for &Predicate {
229 type Output = Predicate;
230
231 fn bitor(self, rhs: Self) -> Self::Output {
232 Predicate::Or(vec![self.clone(), rhs.clone()])
233 }
234}