elif_orm/relationships/constraints/
builder.rs

1//! Constraint builder for creating type-safe relationship constraints
2
3use std::collections::HashSet;
4use crate::error::ModelResult;
5use crate::query::{QueryBuilder, OrderDirection, QueryOperator};
6use super::types::{RelationshipConstraint, ConstraintType};
7use super::implementations::*;
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.into_iter().map(|v| serde_json::Value::String(v.to_string())).collect(),
154        };
155        self.add_constraint(Box::new(constraint));
156        self
157    }
158    
159    /// Add raw WHERE constraint
160    pub fn where_raw(mut self, condition: &str) -> Self {
161        let constraint = RawConstraint {
162            sql: condition.to_string(),
163            constraint_type: ConstraintType::Where,
164        };
165        self.add_constraint(Box::new(constraint));
166        self
167    }
168
169    /// Add ORDER BY constraint
170    pub fn order_by(mut self, field: &str) -> Self {
171        let constraint = OrderConstraint {
172            field: field.to_string(),
173            direction: OrderDirection::Asc,
174        };
175        self.add_constraint(Box::new(constraint));
176        self
177    }
178    
179    /// Add ORDER BY DESC constraint
180    pub fn order_by_desc(mut self, field: &str) -> Self {
181        let constraint = OrderConstraint {
182            field: field.to_string(),
183            direction: OrderDirection::Desc,
184        };
185        self.add_constraint(Box::new(constraint));
186        self
187    }
188
189    /// Add LIMIT constraint
190    pub fn limit(mut self, count: i64) -> Self {
191        let constraint = LimitConstraint { count };
192        self.add_constraint(Box::new(constraint));
193        self
194    }
195    
196    /// Add OFFSET constraint
197    pub fn offset(mut self, count: i64) -> Self {
198        let constraint = OffsetConstraint { count };
199        self.add_constraint(Box::new(constraint));
200        self
201    }
202    
203    /// Add GROUP BY constraint
204    pub fn group_by(mut self, field: &str) -> Self {
205        let constraint = GroupByConstraint {
206            field: field.to_string(),
207        };
208        self.add_constraint(Box::new(constraint));
209        self
210    }
211    
212    /// Add HAVING constraint
213    pub fn having<V>(mut self, field: &str, operator: QueryOperator, value: V) -> Self 
214    where
215        V: Send + Sync + std::fmt::Display + Clone + 'static,
216    {
217        let constraint = HavingConstraint {
218            field: field.to_string(),
219            operator,
220            value: serde_json::Value::String(value.to_string()),
221        };
222        self.add_constraint(Box::new(constraint));
223        self
224    }
225    
226    /// Add raw HAVING constraint
227    pub fn having_raw(mut self, condition: &str) -> Self {
228        let constraint = RawConstraint {
229            sql: condition.to_string(),
230            constraint_type: ConstraintType::Having,
231        };
232        self.add_constraint(Box::new(constraint));
233        self
234    }
235}
236
237impl Default for RelationshipConstraintBuilder {
238    fn default() -> Self {
239        Self::new()
240    }
241}