elif_orm/relationships/constraints/
builder.rs

1//! Constraint builder for creating type-safe relationship constraints
2
3use super::implementations::*;
4use super::types::{ConstraintType, RelationshipConstraint};
5use crate::error::ModelResult;
6use crate::query::{OrderDirection, QueryBuilder, QueryOperator};
7use std::collections::HashSet;
8
9/// Builder for relationship constraints with type safety and validation
10#[derive(Debug)]
11pub struct RelationshipConstraintBuilder {
12    constraints: Vec<Box<dyn RelationshipConstraint>>,
13    /// Track constraint types to prevent conflicts
14    applied_types: HashSet<ConstraintType>,
15}
16
17impl RelationshipConstraintBuilder {
18    pub fn new() -> Self {
19        Self {
20            constraints: Vec::new(),
21            applied_types: HashSet::new(),
22        }
23    }
24
25    /// Apply all constraints to the query builder
26    pub async fn apply_all(&self, query: &mut QueryBuilder) -> ModelResult<()> {
27        for constraint in &self.constraints {
28            constraint.validate()?;
29            constraint.apply(query).await?;
30        }
31        Ok(())
32    }
33
34    /// Get all constraints
35    pub fn constraints(&self) -> &[Box<dyn RelationshipConstraint>] {
36        &self.constraints
37    }
38
39    /// Check if a constraint type has been applied
40    pub fn has_constraint_type(&self, constraint_type: &ConstraintType) -> bool {
41        self.applied_types.contains(constraint_type)
42    }
43
44    /// Add a constraint and track its type
45    fn add_constraint(&mut self, constraint: Box<dyn RelationshipConstraint>) {
46        let constraint_type = constraint.constraint_type();
47        self.applied_types.insert(constraint_type);
48        self.constraints.push(constraint);
49    }
50
51    /// Add WHERE equals constraint
52    pub fn where_eq<V>(mut self, field: &str, value: V) -> Self
53    where
54        V: Send + Sync + std::fmt::Display + Clone + 'static,
55    {
56        let constraint = WhereConstraint {
57            field: field.to_string(),
58            operator: QueryOperator::Equal,
59            value: serde_json::Value::String(value.to_string()),
60        };
61        self.add_constraint(Box::new(constraint));
62        self
63    }
64
65    /// Add WHERE not equals constraint
66    pub fn where_ne<V>(mut self, field: &str, value: V) -> Self
67    where
68        V: Send + Sync + std::fmt::Display + Clone + 'static,
69    {
70        let constraint = WhereConstraint {
71            field: field.to_string(),
72            operator: QueryOperator::NotEqual,
73            value: serde_json::Value::String(value.to_string()),
74        };
75        self.add_constraint(Box::new(constraint));
76        self
77    }
78
79    /// Add WHERE greater than constraint
80    pub fn where_gt<V>(mut self, field: &str, value: V) -> Self
81    where
82        V: Send + Sync + std::fmt::Display + Clone + 'static,
83    {
84        let constraint = WhereConstraint {
85            field: field.to_string(),
86            operator: QueryOperator::GreaterThan,
87            value: serde_json::Value::String(value.to_string()),
88        };
89        self.add_constraint(Box::new(constraint));
90        self
91    }
92
93    /// Add WHERE greater than or equal constraint
94    pub fn where_gte<V>(mut self, field: &str, value: V) -> Self
95    where
96        V: Send + Sync + std::fmt::Display + Clone + 'static,
97    {
98        let constraint = WhereConstraint {
99            field: field.to_string(),
100            operator: QueryOperator::GreaterThanOrEqual,
101            value: serde_json::Value::String(value.to_string()),
102        };
103        self.add_constraint(Box::new(constraint));
104        self
105    }
106
107    /// Add WHERE less than constraint
108    pub fn where_lt<V>(mut self, field: &str, value: V) -> Self
109    where
110        V: Send + Sync + std::fmt::Display + Clone + 'static,
111    {
112        let constraint = WhereConstraint {
113            field: field.to_string(),
114            operator: QueryOperator::LessThan,
115            value: serde_json::Value::String(value.to_string()),
116        };
117        self.add_constraint(Box::new(constraint));
118        self
119    }
120
121    /// Add WHERE less than or equal constraint
122    pub fn where_lte<V>(mut self, field: &str, value: V) -> Self
123    where
124        V: Send + Sync + std::fmt::Display + Clone + 'static,
125    {
126        let constraint = WhereConstraint {
127            field: field.to_string(),
128            operator: QueryOperator::LessThanOrEqual,
129            value: serde_json::Value::String(value.to_string()),
130        };
131        self.add_constraint(Box::new(constraint));
132        self
133    }
134
135    /// Add WHERE LIKE constraint
136    pub fn where_like(mut self, field: &str, pattern: &str) -> Self {
137        let constraint = WhereConstraint {
138            field: field.to_string(),
139            operator: QueryOperator::Like,
140            value: serde_json::Value::String(pattern.to_string()),
141        };
142        self.add_constraint(Box::new(constraint));
143        self
144    }
145
146    /// Add WHERE IN constraint
147    pub fn where_in<V>(mut self, field: &str, values: Vec<V>) -> Self
148    where
149        V: Send + Sync + std::fmt::Display + Clone + 'static,
150    {
151        let constraint = WhereInConstraint {
152            field: field.to_string(),
153            values: values
154                .into_iter()
155                .map(|v| serde_json::Value::String(v.to_string()))
156                .collect(),
157        };
158        self.add_constraint(Box::new(constraint));
159        self
160    }
161
162    /// Add raw WHERE constraint
163    pub fn where_raw(mut self, condition: &str) -> Self {
164        let constraint = RawConstraint {
165            sql: condition.to_string(),
166            constraint_type: ConstraintType::Where,
167        };
168        self.add_constraint(Box::new(constraint));
169        self
170    }
171
172    /// Add ORDER BY constraint
173    pub fn order_by(mut self, field: &str) -> Self {
174        let constraint = OrderConstraint {
175            field: field.to_string(),
176            direction: OrderDirection::Asc,
177        };
178        self.add_constraint(Box::new(constraint));
179        self
180    }
181
182    /// Add ORDER BY DESC constraint
183    pub fn order_by_desc(mut self, field: &str) -> Self {
184        let constraint = OrderConstraint {
185            field: field.to_string(),
186            direction: OrderDirection::Desc,
187        };
188        self.add_constraint(Box::new(constraint));
189        self
190    }
191
192    /// Add LIMIT constraint
193    pub fn limit(mut self, count: i64) -> Self {
194        let constraint = LimitConstraint { count };
195        self.add_constraint(Box::new(constraint));
196        self
197    }
198
199    /// Add OFFSET constraint
200    pub fn offset(mut self, count: i64) -> Self {
201        let constraint = OffsetConstraint { count };
202        self.add_constraint(Box::new(constraint));
203        self
204    }
205
206    /// Add GROUP BY constraint
207    pub fn group_by(mut self, field: &str) -> Self {
208        let constraint = GroupByConstraint {
209            field: field.to_string(),
210        };
211        self.add_constraint(Box::new(constraint));
212        self
213    }
214
215    /// Add HAVING constraint
216    pub fn having<V>(mut self, field: &str, operator: QueryOperator, value: V) -> Self
217    where
218        V: Send + Sync + std::fmt::Display + Clone + 'static,
219    {
220        let constraint = HavingConstraint {
221            field: field.to_string(),
222            operator,
223            value: serde_json::Value::String(value.to_string()),
224        };
225        self.add_constraint(Box::new(constraint));
226        self
227    }
228
229    /// Add raw HAVING constraint
230    pub fn having_raw(mut self, condition: &str) -> Self {
231        let constraint = RawConstraint {
232            sql: condition.to_string(),
233            constraint_type: ConstraintType::Having,
234        };
235        self.add_constraint(Box::new(constraint));
236        self
237    }
238}
239
240impl Default for RelationshipConstraintBuilder {
241    fn default() -> Self {
242        Self::new()
243    }
244}