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