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