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 pub fn not(self) -> Self {
76 match self {
77 Self::Not(inner) => *inner,
78 inner => Self::Not(Box::new(inner)),
79 }
80 }
81
82 pub fn and(self, other: impl Into<FilterExpr>) -> Self {
83 match (self, other.into()) {
84 (Self::All(mut left), Self::All(right)) => {
85 left.extend(right);
86 Self::All(left)
87 }
88 (Self::All(mut left), right) => {
89 left.push(right);
90 Self::All(left)
91 }
92 (left, Self::All(mut right)) => {
93 let mut filters = vec![left];
94 filters.append(&mut right);
95 Self::All(filters)
96 }
97 (left, right) => Self::All(vec![left, right]),
98 }
99 }
100
101 pub fn or(self, other: impl Into<FilterExpr>) -> Self {
102 match (self, other.into()) {
103 (Self::Any(mut left), Self::Any(right)) => {
104 left.extend(right);
105 Self::Any(left)
106 }
107 (Self::Any(mut left), right) => {
108 left.push(right);
109 Self::Any(left)
110 }
111 (left, Self::Any(mut right)) => {
112 let mut filters = vec![left];
113 filters.append(&mut right);
114 Self::Any(filters)
115 }
116 (left, right) => Self::Any(vec![left, right]),
117 }
118 }
119
120 pub fn relation(
121 parent_table: &'static str,
122 parent_column: &'static str,
123 related_table: &'static str,
124 related_column: &'static str,
125 filter: FilterExpr,
126 ) -> Self {
127 Self::Relation(RelationFilter::new(
128 RelationQuantifier::ToOne,
129 parent_table,
130 parent_column,
131 related_table,
132 related_column,
133 filter,
134 ))
135 }
136
137 pub fn relation_some(
138 parent_table: &'static str,
139 parent_column: &'static str,
140 related_table: &'static str,
141 related_column: &'static str,
142 filter: FilterExpr,
143 ) -> Self {
144 Self::Relation(RelationFilter::new(
145 RelationQuantifier::Some,
146 parent_table,
147 parent_column,
148 related_table,
149 related_column,
150 filter,
151 ))
152 }
153
154 pub fn relation_every(
155 parent_table: &'static str,
156 parent_column: &'static str,
157 related_table: &'static str,
158 related_column: &'static str,
159 filter: FilterExpr,
160 ) -> Self {
161 Self::Relation(RelationFilter::new(
162 RelationQuantifier::Every,
163 parent_table,
164 parent_column,
165 related_table,
166 related_column,
167 filter,
168 ))
169 }
170
171 pub fn relation_none(
172 parent_table: &'static str,
173 parent_column: &'static str,
174 related_table: &'static str,
175 related_column: &'static str,
176 filter: FilterExpr,
177 ) -> Self {
178 Self::Relation(RelationFilter::new(
179 RelationQuantifier::None,
180 parent_table,
181 parent_column,
182 related_table,
183 related_column,
184 filter,
185 ))
186 }
187}