elif_orm/relationships/constraints/
implementations.rs1use super::types::{ConstraintType, RelationshipConstraint};
4use crate::error::{ModelError, ModelResult};
5use crate::query::{OrderDirection, QueryBuilder, QueryOperator};
6use async_trait::async_trait;
7
8#[derive(Debug, Clone)]
10pub(crate) struct WhereConstraint {
11 pub field: String,
12 pub operator: QueryOperator,
13 pub value: serde_json::Value,
14}
15
16#[async_trait]
17impl RelationshipConstraint for WhereConstraint {
18 async fn apply(&self, query: &mut QueryBuilder) -> ModelResult<()> {
19 *query = match self.operator {
21 QueryOperator::Equal => query.clone().where_eq(&self.field, self.value.clone()),
22 QueryOperator::NotEqual => query.clone().where_ne(&self.field, self.value.clone()),
23 QueryOperator::GreaterThan => query.clone().where_gt(&self.field, self.value.clone()),
24 QueryOperator::GreaterThanOrEqual => {
25 query.clone().where_gte(&self.field, self.value.clone())
26 }
27 QueryOperator::LessThan => query.clone().where_lt(&self.field, self.value.clone()),
28 QueryOperator::LessThanOrEqual => {
29 query.clone().where_lte(&self.field, self.value.clone())
30 }
31 QueryOperator::Like => {
32 if let Some(pattern) = self.value.as_str() {
33 query.clone().where_like(&self.field, pattern)
34 } else {
35 return Err(ModelError::Validation(
36 "LIKE operator requires string value".to_string(),
37 ));
38 }
39 }
40 QueryOperator::NotLike => {
41 if let Some(pattern) = self.value.as_str() {
42 query.clone().where_not_like(&self.field, pattern)
43 } else {
44 return Err(ModelError::Validation(
45 "NOT LIKE operator requires string value".to_string(),
46 ));
47 }
48 }
49 _ => {
50 return Err(ModelError::Validation(format!(
51 "Unsupported operator {:?} for WHERE constraint",
52 self.operator
53 )));
54 }
55 };
56 Ok(())
57 }
58
59 fn constraint_type(&self) -> ConstraintType {
60 ConstraintType::Where
61 }
62
63 fn description(&self) -> String {
64 format!("WHERE {} {:?} {}", self.field, self.operator, self.value)
65 }
66
67 fn validate(&self) -> ModelResult<()> {
68 if self.field.trim().is_empty() {
69 return Err(ModelError::Validation(
70 "WHERE constraint field cannot be empty".to_string(),
71 ));
72 }
73 Ok(())
74 }
75}
76
77#[derive(Debug, Clone)]
79pub(crate) struct OrderConstraint {
80 pub field: String,
81 pub direction: OrderDirection,
82}
83
84#[async_trait]
85impl RelationshipConstraint for OrderConstraint {
86 async fn apply(&self, query: &mut QueryBuilder) -> ModelResult<()> {
87 *query = match self.direction {
89 OrderDirection::Desc => query.clone().order_by_desc(&self.field),
90 OrderDirection::Asc => query.clone().order_by(&self.field),
91 };
92 Ok(())
93 }
94
95 fn constraint_type(&self) -> ConstraintType {
96 ConstraintType::Order
97 }
98
99 fn description(&self) -> String {
100 format!("ORDER BY {} {:?}", self.field, self.direction)
101 }
102
103 fn validate(&self) -> ModelResult<()> {
104 if self.field.trim().is_empty() {
105 return Err(ModelError::Validation(
106 "ORDER BY constraint field cannot be empty".to_string(),
107 ));
108 }
109 Ok(())
110 }
111}
112
113#[derive(Debug, Clone)]
115pub(crate) struct LimitConstraint {
116 pub count: i64,
117}
118
119#[async_trait]
120impl RelationshipConstraint for LimitConstraint {
121 async fn apply(&self, query: &mut QueryBuilder) -> ModelResult<()> {
122 *query = query.clone().limit(self.count);
124 Ok(())
125 }
126
127 fn constraint_type(&self) -> ConstraintType {
128 ConstraintType::Limit
129 }
130
131 fn description(&self) -> String {
132 format!("LIMIT {}", self.count)
133 }
134
135 fn validate(&self) -> ModelResult<()> {
136 if self.count < 0 {
137 return Err(ModelError::Validation(
138 "LIMIT count must be non-negative".to_string(),
139 ));
140 }
141 Ok(())
142 }
143}
144
145#[derive(Debug, Clone)]
147pub(crate) struct OffsetConstraint {
148 pub count: i64,
149}
150
151#[async_trait]
152impl RelationshipConstraint for OffsetConstraint {
153 async fn apply(&self, query: &mut QueryBuilder) -> ModelResult<()> {
154 *query = query.clone().offset(self.count);
155 Ok(())
156 }
157
158 fn constraint_type(&self) -> ConstraintType {
159 ConstraintType::Offset
160 }
161
162 fn description(&self) -> String {
163 format!("OFFSET {}", self.count)
164 }
165
166 fn validate(&self) -> ModelResult<()> {
167 if self.count < 0 {
168 return Err(ModelError::Validation(
169 "OFFSET count must be non-negative".to_string(),
170 ));
171 }
172 Ok(())
173 }
174}
175
176#[derive(Debug, Clone)]
178pub(crate) struct WhereInConstraint {
179 pub field: String,
180 pub values: Vec<serde_json::Value>,
181}
182
183#[async_trait]
184impl RelationshipConstraint for WhereInConstraint {
185 async fn apply(&self, query: &mut QueryBuilder) -> ModelResult<()> {
186 let string_values: Vec<String> = self
188 .values
189 .iter()
190 .map(|v| match v {
191 serde_json::Value::String(s) => s.clone(),
192 _ => v.to_string(),
193 })
194 .collect();
195
196 *query = query.clone().where_in(&self.field, string_values);
197 Ok(())
198 }
199
200 fn constraint_type(&self) -> ConstraintType {
201 ConstraintType::Where
202 }
203
204 fn description(&self) -> String {
205 format!("WHERE {} IN ({} values)", self.field, self.values.len())
206 }
207
208 fn validate(&self) -> ModelResult<()> {
209 if self.field.trim().is_empty() {
210 return Err(ModelError::Validation(
211 "WHERE IN constraint field cannot be empty".to_string(),
212 ));
213 }
214 if self.values.is_empty() {
215 return Err(ModelError::Validation(
216 "WHERE IN constraint must have at least one value".to_string(),
217 ));
218 }
219 Ok(())
220 }
221}
222
223#[derive(Debug, Clone)]
225pub(crate) struct GroupByConstraint {
226 pub field: String,
227}
228
229#[async_trait]
230impl RelationshipConstraint for GroupByConstraint {
231 async fn apply(&self, query: &mut QueryBuilder) -> ModelResult<()> {
232 *query = query.clone().group_by(&self.field);
233 Ok(())
234 }
235
236 fn constraint_type(&self) -> ConstraintType {
237 ConstraintType::GroupBy
238 }
239
240 fn description(&self) -> String {
241 format!("GROUP BY {}", self.field)
242 }
243
244 fn validate(&self) -> ModelResult<()> {
245 if self.field.trim().is_empty() {
246 return Err(ModelError::Validation(
247 "GROUP BY constraint field cannot be empty".to_string(),
248 ));
249 }
250 Ok(())
251 }
252}
253
254#[derive(Debug, Clone)]
256pub(crate) struct HavingConstraint {
257 pub field: String,
258 pub operator: QueryOperator,
259 pub value: serde_json::Value,
260}
261
262#[async_trait]
263impl RelationshipConstraint for HavingConstraint {
264 async fn apply(&self, query: &mut QueryBuilder) -> ModelResult<()> {
265 *query = query
267 .clone()
268 .having(&self.field, self.operator, self.value.clone());
269 Ok(())
270 }
271
272 fn constraint_type(&self) -> ConstraintType {
273 ConstraintType::Having
274 }
275
276 fn description(&self) -> String {
277 format!("HAVING {} {:?} {}", self.field, self.operator, self.value)
278 }
279
280 fn validate(&self) -> ModelResult<()> {
281 if self.field.trim().is_empty() {
282 return Err(ModelError::Validation(
283 "HAVING constraint field cannot be empty".to_string(),
284 ));
285 }
286 Ok(())
287 }
288}
289
290#[derive(Debug, Clone)]
292pub(crate) struct RawConstraint {
293 pub sql: String,
294 pub constraint_type: ConstraintType,
295}
296
297#[async_trait]
298impl RelationshipConstraint for RawConstraint {
299 async fn apply(&self, query: &mut QueryBuilder) -> ModelResult<()> {
300 match self.constraint_type {
302 ConstraintType::Where => {
303 *query = query.clone().where_raw(&self.sql);
304 }
305 ConstraintType::Having => {
306 *query = query.clone().having_raw(&self.sql);
307 }
308 ConstraintType::Raw => {
309 return Err(ModelError::Validation(
312 "Raw constraints not yet supported".to_string(),
313 ));
314 }
315 _ => {
316 return Err(ModelError::Validation(format!(
317 "Raw constraints not supported for type {:?}",
318 self.constraint_type
319 )));
320 }
321 }
322 Ok(())
323 }
324
325 fn constraint_type(&self) -> ConstraintType {
326 self.constraint_type.clone()
327 }
328
329 fn description(&self) -> String {
330 format!("RAW {:?}: {}", self.constraint_type, self.sql)
331 }
332
333 fn validate(&self) -> ModelResult<()> {
334 if self.sql.trim().is_empty() {
335 return Err(ModelError::Validation(
336 "Raw constraint SQL cannot be empty".to_string(),
337 ));
338 }
339 Ok(())
340 }
341}