1pub use cratestack_policy::RelationQuantifier;
2
3use super::coalesce::CoalesceFilter;
4use super::filter::Filter;
5use super::json::JsonFilter;
6use super::spatial::SpatialFilter;
7use super::vector::VectorDistanceFilter;
8
9#[derive(Debug, Clone, PartialEq)]
10pub struct RelationFilter {
11 pub quantifier: RelationQuantifier,
12 pub parent_table: &'static str,
13 pub parent_column: &'static str,
14 pub related_table: &'static str,
15 pub related_column: &'static str,
16 pub filter: Box<FilterExpr>,
17}
18
19#[derive(Debug, Clone, PartialEq)]
20pub enum FilterExpr {
21 Filter(Filter),
22 All(Vec<FilterExpr>),
23 Any(Vec<FilterExpr>),
24 Not(Box<FilterExpr>),
25 Relation(RelationFilter),
26 Coalesce(CoalesceFilter),
29 Json(JsonFilter),
33 Spatial(SpatialFilter),
39 VectorDistance(VectorDistanceFilter),
46}
47
48impl From<Filter> for FilterExpr {
49 fn from(value: Filter) -> Self {
50 Self::Filter(value)
51 }
52}
53
54impl RelationFilter {
55 pub fn new(
56 quantifier: RelationQuantifier,
57 parent_table: &'static str,
58 parent_column: &'static str,
59 related_table: &'static str,
60 related_column: &'static str,
61 filter: FilterExpr,
62 ) -> Self {
63 Self {
64 quantifier,
65 parent_table,
66 parent_column,
67 related_table,
68 related_column,
69 filter: Box::new(filter),
70 }
71 }
72}
73
74impl FilterExpr {
75 pub fn all(filters: impl IntoIterator<Item = FilterExpr>) -> Self {
76 Self::All(filters.into_iter().collect())
77 }
78
79 pub fn any(filters: impl IntoIterator<Item = FilterExpr>) -> Self {
80 Self::Any(filters.into_iter().collect())
81 }
82
83 #[allow(clippy::should_implement_trait)]
86 pub fn not(self) -> Self {
87 match self {
88 Self::Not(inner) => *inner,
89 inner => Self::Not(Box::new(inner)),
90 }
91 }
92
93 pub fn and(self, other: impl Into<FilterExpr>) -> Self {
94 match (self, other.into()) {
95 (Self::All(mut left), Self::All(right)) => {
96 left.extend(right);
97 Self::All(left)
98 }
99 (Self::All(mut left), right) => {
100 left.push(right);
101 Self::All(left)
102 }
103 (left, Self::All(mut right)) => {
104 let mut filters = vec![left];
105 filters.append(&mut right);
106 Self::All(filters)
107 }
108 (left, right) => Self::All(vec![left, right]),
109 }
110 }
111
112 pub fn or(self, other: impl Into<FilterExpr>) -> Self {
113 match (self, other.into()) {
114 (Self::Any(mut left), Self::Any(right)) => {
115 left.extend(right);
116 Self::Any(left)
117 }
118 (Self::Any(mut left), right) => {
119 left.push(right);
120 Self::Any(left)
121 }
122 (left, Self::Any(mut right)) => {
123 let mut filters = vec![left];
124 filters.append(&mut right);
125 Self::Any(filters)
126 }
127 (left, right) => Self::Any(vec![left, right]),
128 }
129 }
130
131 pub fn relation(
132 parent_table: &'static str,
133 parent_column: &'static str,
134 related_table: &'static str,
135 related_column: &'static str,
136 filter: FilterExpr,
137 ) -> Self {
138 Self::Relation(RelationFilter::new(
139 RelationQuantifier::ToOne,
140 parent_table,
141 parent_column,
142 related_table,
143 related_column,
144 filter,
145 ))
146 }
147
148 pub fn relation_some(
149 parent_table: &'static str,
150 parent_column: &'static str,
151 related_table: &'static str,
152 related_column: &'static str,
153 filter: FilterExpr,
154 ) -> Self {
155 Self::Relation(RelationFilter::new(
156 RelationQuantifier::Some,
157 parent_table,
158 parent_column,
159 related_table,
160 related_column,
161 filter,
162 ))
163 }
164
165 pub fn relation_every(
166 parent_table: &'static str,
167 parent_column: &'static str,
168 related_table: &'static str,
169 related_column: &'static str,
170 filter: FilterExpr,
171 ) -> Self {
172 Self::Relation(RelationFilter::new(
173 RelationQuantifier::Every,
174 parent_table,
175 parent_column,
176 related_table,
177 related_column,
178 filter,
179 ))
180 }
181
182 pub fn relation_none(
183 parent_table: &'static str,
184 parent_column: &'static str,
185 related_table: &'static str,
186 related_column: &'static str,
187 filter: FilterExpr,
188 ) -> Self {
189 Self::Relation(RelationFilter::new(
190 RelationQuantifier::None,
191 parent_table,
192 parent_column,
193 related_table,
194 related_column,
195 filter,
196 ))
197 }
198}