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 {
139 field: String,
140 },
141 IsMissing {
142 field: String,
143 },
144 IsEmpty {
145 field: String,
146 },
147 IsNotEmpty {
148 field: String,
149 },
150 MapContainsKey {
151 field: String,
152 key: Value,
153 coercion: CoercionSpec,
154 },
155 MapContainsValue {
156 field: String,
157 value: Value,
158 coercion: CoercionSpec,
159 },
160 MapContainsEntry {
161 field: String,
162 key: Value,
163 value: Value,
164 coercion: CoercionSpec,
165 },
166 TextContains {
167 field: String,
168 value: Value,
169 },
170 TextContainsCi {
171 field: String,
172 value: Value,
173 },
174}
175
176impl Predicate {
177 #[must_use]
178 pub const fn and(preds: Vec<Self>) -> Self {
179 Self::And(preds)
180 }
181
182 #[must_use]
183 pub const fn or(preds: Vec<Self>) -> Self {
184 Self::Or(preds)
185 }
186
187 #[allow(clippy::should_implement_trait)]
188 #[must_use]
189 pub fn not(pred: Self) -> Self {
190 Self::Not(Box::new(pred))
191 }
192
193 #[must_use]
194 pub fn eq(field: String, value: Value) -> Self {
195 Self::Compare(ComparePredicate::eq(field, value))
196 }
197
198 #[must_use]
199 pub fn ne(field: String, value: Value) -> Self {
200 Self::Compare(ComparePredicate::ne(field, value))
201 }
202
203 #[must_use]
204 pub fn lt(field: String, value: Value) -> Self {
205 Self::Compare(ComparePredicate::lt(field, value))
206 }
207
208 #[must_use]
209 pub fn lte(field: String, value: Value) -> Self {
210 Self::Compare(ComparePredicate::lte(field, value))
211 }
212
213 #[must_use]
214 pub fn gt(field: String, value: Value) -> Self {
215 Self::Compare(ComparePredicate::gt(field, value))
216 }
217
218 #[must_use]
219 pub fn gte(field: String, value: Value) -> Self {
220 Self::Compare(ComparePredicate::gte(field, value))
221 }
222
223 #[must_use]
224 pub fn in_(field: String, values: Vec<Value>) -> Self {
225 Self::Compare(ComparePredicate::in_(field, values))
226 }
227
228 #[must_use]
229 pub fn not_in(field: String, values: Vec<Value>) -> Self {
230 Self::Compare(ComparePredicate::not_in(field, values))
231 }
232}
233
234impl BitAnd for Predicate {
235 type Output = Self;
236
237 fn bitand(self, rhs: Self) -> Self::Output {
238 Self::And(vec![self, rhs])
239 }
240}
241
242impl BitAnd for &Predicate {
243 type Output = Predicate;
244
245 fn bitand(self, rhs: Self) -> Self::Output {
246 Predicate::And(vec![self.clone(), rhs.clone()])
247 }
248}
249
250impl BitOr for Predicate {
251 type Output = Self;
252
253 fn bitor(self, rhs: Self) -> Self::Output {
254 Self::Or(vec![self, rhs])
255 }
256}
257
258impl BitOr for &Predicate {
259 type Output = Predicate;
260
261 fn bitor(self, rhs: Self) -> Self::Output {
262 Predicate::Or(vec![self.clone(), rhs.clone()])
263 }
264}