1use crate::{
2 db::{
3 query::fluent::load::FluentLoadQuery,
4 query::{api::ResponseCardinalityExt, intent::QueryError},
5 response::EntityResponse,
6 },
7 traits::{EntityKind, EntityValue},
8 types::{Decimal, Id},
9 value::Value,
10};
11
12type MinMaxByIds<E> = Option<(Id<E>, Id<E>)>;
13
14impl<E> FluentLoadQuery<'_, E>
15where
16 E: EntityKind,
17{
18 pub fn execute(&self) -> Result<EntityResponse<E>, QueryError>
24 where
25 E: EntityValue,
26 {
27 self.ensure_non_paged_mode_ready()?;
28
29 self.session.execute_query(self.query())
30 }
31
32 pub fn is_empty(&self) -> Result<bool, QueryError>
38 where
39 E: EntityValue,
40 {
41 Ok(!self.exists()?)
42 }
43
44 pub fn exists(&self) -> Result<bool, QueryError>
46 where
47 E: EntityValue,
48 {
49 self.ensure_non_paged_mode_ready()?;
50
51 self.session
52 .execute_load_query_with(self.query(), |load, plan| load.aggregate_exists(plan))
53 }
54
55 pub fn count(&self) -> Result<u32, QueryError>
57 where
58 E: EntityValue,
59 {
60 self.ensure_non_paged_mode_ready()?;
61
62 self.session
63 .execute_load_query_with(self.query(), |load, plan| load.aggregate_count(plan))
64 }
65
66 pub fn min(&self) -> Result<Option<Id<E>>, QueryError>
68 where
69 E: EntityValue,
70 {
71 self.ensure_non_paged_mode_ready()?;
72
73 self.session
74 .execute_load_query_with(self.query(), |load, plan| load.aggregate_min(plan))
75 }
76
77 pub fn min_by(&self, field: impl AsRef<str>) -> Result<Option<Id<E>>, QueryError>
81 where
82 E: EntityValue,
83 {
84 self.ensure_non_paged_mode_ready()?;
85
86 Self::with_slot(field, |target_slot| {
87 self.session
88 .execute_load_query_with(self.query(), move |load, plan| {
89 load.aggregate_min_by_slot(plan, target_slot)
90 })
91 })
92 }
93
94 pub fn max(&self) -> Result<Option<Id<E>>, QueryError>
96 where
97 E: EntityValue,
98 {
99 self.ensure_non_paged_mode_ready()?;
100
101 self.session
102 .execute_load_query_with(self.query(), |load, plan| load.aggregate_max(plan))
103 }
104
105 pub fn max_by(&self, field: impl AsRef<str>) -> Result<Option<Id<E>>, QueryError>
109 where
110 E: EntityValue,
111 {
112 self.ensure_non_paged_mode_ready()?;
113
114 Self::with_slot(field, |target_slot| {
115 self.session
116 .execute_load_query_with(self.query(), move |load, plan| {
117 load.aggregate_max_by_slot(plan, target_slot)
118 })
119 })
120 }
121
122 pub fn nth_by(&self, field: impl AsRef<str>, nth: usize) -> Result<Option<Id<E>>, QueryError>
125 where
126 E: EntityValue,
127 {
128 self.ensure_non_paged_mode_ready()?;
129
130 Self::with_slot(field, |target_slot| {
131 self.session
132 .execute_load_query_with(self.query(), move |load, plan| {
133 load.aggregate_nth_by_slot(plan, target_slot, nth)
134 })
135 })
136 }
137
138 pub fn sum_by(&self, field: impl AsRef<str>) -> Result<Option<Decimal>, QueryError>
140 where
141 E: EntityValue,
142 {
143 self.ensure_non_paged_mode_ready()?;
144
145 Self::with_slot(field, |target_slot| {
146 self.session
147 .execute_load_query_with(self.query(), move |load, plan| {
148 load.aggregate_sum_by_slot(plan, target_slot)
149 })
150 })
151 }
152
153 pub fn sum_distinct_by(&self, field: impl AsRef<str>) -> Result<Option<Decimal>, QueryError>
155 where
156 E: EntityValue,
157 {
158 self.ensure_non_paged_mode_ready()?;
159
160 Self::with_slot(field, |target_slot| {
161 self.session
162 .execute_load_query_with(self.query(), move |load, plan| {
163 load.aggregate_sum_distinct_by_slot(plan, target_slot)
164 })
165 })
166 }
167
168 pub fn avg_by(&self, field: impl AsRef<str>) -> Result<Option<Decimal>, QueryError>
170 where
171 E: EntityValue,
172 {
173 self.ensure_non_paged_mode_ready()?;
174
175 Self::with_slot(field, |target_slot| {
176 self.session
177 .execute_load_query_with(self.query(), move |load, plan| {
178 load.aggregate_avg_by_slot(plan, target_slot)
179 })
180 })
181 }
182
183 pub fn median_by(&self, field: impl AsRef<str>) -> Result<Option<Id<E>>, QueryError>
188 where
189 E: EntityValue,
190 {
191 self.ensure_non_paged_mode_ready()?;
192
193 Self::with_slot(field, |target_slot| {
194 self.session
195 .execute_load_query_with(self.query(), move |load, plan| {
196 load.aggregate_median_by_slot(plan, target_slot)
197 })
198 })
199 }
200
201 pub fn count_distinct_by(&self, field: impl AsRef<str>) -> Result<u32, QueryError>
204 where
205 E: EntityValue,
206 {
207 self.ensure_non_paged_mode_ready()?;
208
209 Self::with_slot(field, |target_slot| {
210 self.session
211 .execute_load_query_with(self.query(), move |load, plan| {
212 load.aggregate_count_distinct_by_slot(plan, target_slot)
213 })
214 })
215 }
216
217 pub fn min_max_by(&self, field: impl AsRef<str>) -> Result<MinMaxByIds<E>, QueryError>
221 where
222 E: EntityValue,
223 {
224 self.ensure_non_paged_mode_ready()?;
225
226 Self::with_slot(field, |target_slot| {
227 self.session
228 .execute_load_query_with(self.query(), move |load, plan| {
229 load.aggregate_min_max_by_slot(plan, target_slot)
230 })
231 })
232 }
233
234 pub fn values_by(&self, field: impl AsRef<str>) -> Result<Vec<Value>, QueryError>
236 where
237 E: EntityValue,
238 {
239 self.ensure_non_paged_mode_ready()?;
240
241 Self::with_slot(field, |target_slot| {
242 self.session
243 .execute_load_query_with(self.query(), move |load, plan| {
244 load.values_by_slot(plan, target_slot)
245 })
246 })
247 }
248
249 pub fn take(&self, take_count: u32) -> Result<EntityResponse<E>, QueryError>
251 where
252 E: EntityValue,
253 {
254 self.ensure_non_paged_mode_ready()?;
255
256 self.session
257 .execute_load_query_with(self.query(), |load, plan| load.take(plan, take_count))
258 }
259
260 pub fn top_k_by(
268 &self,
269 field: impl AsRef<str>,
270 take_count: u32,
271 ) -> Result<EntityResponse<E>, QueryError>
272 where
273 E: EntityValue,
274 {
275 self.ensure_non_paged_mode_ready()?;
276
277 Self::with_slot(field, |target_slot| {
278 self.session
279 .execute_load_query_with(self.query(), move |load, plan| {
280 load.top_k_by_slot(plan, target_slot, take_count)
281 })
282 })
283 }
284
285 pub fn bottom_k_by(
293 &self,
294 field: impl AsRef<str>,
295 take_count: u32,
296 ) -> Result<EntityResponse<E>, QueryError>
297 where
298 E: EntityValue,
299 {
300 self.ensure_non_paged_mode_ready()?;
301
302 Self::with_slot(field, |target_slot| {
303 self.session
304 .execute_load_query_with(self.query(), move |load, plan| {
305 load.bottom_k_by_slot(plan, target_slot, take_count)
306 })
307 })
308 }
309
310 pub fn top_k_by_values(
318 &self,
319 field: impl AsRef<str>,
320 take_count: u32,
321 ) -> Result<Vec<Value>, QueryError>
322 where
323 E: EntityValue,
324 {
325 self.ensure_non_paged_mode_ready()?;
326
327 Self::with_slot(field, |target_slot| {
328 self.session
329 .execute_load_query_with(self.query(), move |load, plan| {
330 load.top_k_by_values_slot(plan, target_slot, take_count)
331 })
332 })
333 }
334
335 pub fn bottom_k_by_values(
343 &self,
344 field: impl AsRef<str>,
345 take_count: u32,
346 ) -> Result<Vec<Value>, QueryError>
347 where
348 E: EntityValue,
349 {
350 self.ensure_non_paged_mode_ready()?;
351
352 Self::with_slot(field, |target_slot| {
353 self.session
354 .execute_load_query_with(self.query(), move |load, plan| {
355 load.bottom_k_by_values_slot(plan, target_slot, take_count)
356 })
357 })
358 }
359
360 pub fn top_k_by_with_ids(
368 &self,
369 field: impl AsRef<str>,
370 take_count: u32,
371 ) -> Result<Vec<(Id<E>, Value)>, QueryError>
372 where
373 E: EntityValue,
374 {
375 self.ensure_non_paged_mode_ready()?;
376
377 Self::with_slot(field, |target_slot| {
378 self.session
379 .execute_load_query_with(self.query(), move |load, plan| {
380 load.top_k_by_with_ids_slot(plan, target_slot, take_count)
381 })
382 })
383 }
384
385 pub fn bottom_k_by_with_ids(
393 &self,
394 field: impl AsRef<str>,
395 take_count: u32,
396 ) -> Result<Vec<(Id<E>, Value)>, QueryError>
397 where
398 E: EntityValue,
399 {
400 self.ensure_non_paged_mode_ready()?;
401
402 Self::with_slot(field, |target_slot| {
403 self.session
404 .execute_load_query_with(self.query(), move |load, plan| {
405 load.bottom_k_by_with_ids_slot(plan, target_slot, take_count)
406 })
407 })
408 }
409
410 pub fn distinct_values_by(&self, field: impl AsRef<str>) -> Result<Vec<Value>, QueryError>
413 where
414 E: EntityValue,
415 {
416 self.ensure_non_paged_mode_ready()?;
417
418 Self::with_slot(field, |target_slot| {
419 self.session
420 .execute_load_query_with(self.query(), move |load, plan| {
421 load.distinct_values_by_slot(plan, target_slot)
422 })
423 })
424 }
425
426 pub fn values_by_with_ids(
429 &self,
430 field: impl AsRef<str>,
431 ) -> Result<Vec<(Id<E>, Value)>, QueryError>
432 where
433 E: EntityValue,
434 {
435 self.ensure_non_paged_mode_ready()?;
436
437 Self::with_slot(field, |target_slot| {
438 self.session
439 .execute_load_query_with(self.query(), move |load, plan| {
440 load.values_by_with_ids_slot(plan, target_slot)
441 })
442 })
443 }
444
445 pub fn first_value_by(&self, field: impl AsRef<str>) -> Result<Option<Value>, QueryError>
448 where
449 E: EntityValue,
450 {
451 self.ensure_non_paged_mode_ready()?;
452
453 Self::with_slot(field, |target_slot| {
454 self.session
455 .execute_load_query_with(self.query(), move |load, plan| {
456 load.first_value_by_slot(plan, target_slot)
457 })
458 })
459 }
460
461 pub fn last_value_by(&self, field: impl AsRef<str>) -> Result<Option<Value>, QueryError>
464 where
465 E: EntityValue,
466 {
467 self.ensure_non_paged_mode_ready()?;
468
469 Self::with_slot(field, |target_slot| {
470 self.session
471 .execute_load_query_with(self.query(), move |load, plan| {
472 load.last_value_by_slot(plan, target_slot)
473 })
474 })
475 }
476
477 pub fn first(&self) -> Result<Option<Id<E>>, QueryError>
479 where
480 E: EntityValue,
481 {
482 self.ensure_non_paged_mode_ready()?;
483
484 self.session
485 .execute_load_query_with(self.query(), |load, plan| load.aggregate_first(plan))
486 }
487
488 pub fn last(&self) -> Result<Option<Id<E>>, QueryError>
490 where
491 E: EntityValue,
492 {
493 self.ensure_non_paged_mode_ready()?;
494
495 self.session
496 .execute_load_query_with(self.query(), |load, plan| load.aggregate_last(plan))
497 }
498
499 pub fn require_one(&self) -> Result<(), QueryError>
501 where
502 E: EntityValue,
503 {
504 self.execute()?.require_one()?;
505 Ok(())
506 }
507
508 pub fn require_some(&self) -> Result<(), QueryError>
510 where
511 E: EntityValue,
512 {
513 self.execute()?.require_some()?;
514 Ok(())
515 }
516}