1use crate::{
7 db::{
8 PersistedRow,
9 executor::{
10 ExecutablePlan, LoadExecutor, ScalarNumericFieldBoundaryRequest,
11 ScalarProjectionBoundaryRequest, ScalarTerminalBoundaryOutput,
12 ScalarTerminalBoundaryRequest,
13 },
14 query::{
15 api::ResponseCardinalityExt,
16 builder::{
17 PreparedFluentNumericFieldRuntimeRequest, PreparedFluentNumericFieldStrategy,
18 PreparedFluentOrderSensitiveTerminalRuntimeRequest,
19 PreparedFluentOrderSensitiveTerminalStrategy,
20 PreparedFluentProjectionRuntimeRequest, PreparedFluentProjectionStrategy,
21 PreparedFluentScalarTerminalRuntimeRequest, PreparedFluentScalarTerminalStrategy,
22 },
23 explain::{ExplainAggregateTerminalPlan, ExplainExecutionNodeDescriptor},
24 fluent::load::FluentLoadQuery,
25 intent::QueryError,
26 plan::AggregateKind,
27 },
28 response::EntityResponse,
29 },
30 error::InternalError,
31 traits::EntityValue,
32 types::{Decimal, Id},
33 value::Value,
34};
35
36type MinMaxByIds<E> = Option<(Id<E>, Id<E>)>;
37
38impl<E> FluentLoadQuery<'_, E>
39where
40 E: PersistedRow,
41{
42 pub fn execute(&self) -> Result<EntityResponse<E>, QueryError>
48 where
49 E: EntityValue,
50 {
51 self.ensure_non_paged_mode_ready()?;
52
53 self.session.execute_query(self.query())
54 }
55
56 fn execute_scalar_non_paged_terminal<T, F>(&self, execute: F) -> Result<T, QueryError>
59 where
60 E: EntityValue,
61 F: FnOnce(LoadExecutor<E>, ExecutablePlan<E>) -> Result<T, InternalError>,
62 {
63 self.ensure_non_paged_mode_ready()?;
64
65 self.session.execute_load_query_with(self.query(), execute)
66 }
67
68 fn explain_prepared_scalar_non_paged_terminal(
71 &self,
72 strategy: &PreparedFluentScalarTerminalStrategy,
73 ) -> Result<ExplainAggregateTerminalPlan, QueryError>
74 where
75 E: EntityValue,
76 {
77 self.ensure_non_paged_mode_ready()?;
78
79 self.session
80 .explain_query_prepared_scalar_terminal_with_visible_indexes(self.query(), strategy)
81 }
82
83 fn execute_prepared_scalar_terminal_output(
87 &self,
88 strategy: PreparedFluentScalarTerminalStrategy,
89 ) -> Result<ScalarTerminalBoundaryOutput, QueryError>
90 where
91 E: EntityValue,
92 {
93 self.execute_scalar_non_paged_terminal(move |load, plan| {
94 load.execute_scalar_terminal_request(
95 plan,
96 scalar_terminal_boundary_request_from_prepared(strategy.runtime_request().clone()),
97 )
98 })
99 }
100
101 fn execute_prepared_numeric_field_terminal(
105 &self,
106 strategy: PreparedFluentNumericFieldStrategy,
107 ) -> Result<Option<Decimal>, QueryError>
108 where
109 E: EntityValue,
110 {
111 self.execute_scalar_non_paged_terminal(move |load, plan| {
112 load.execute_numeric_field_boundary(
113 plan,
114 strategy.target_field().clone(),
115 numeric_field_boundary_request_from_prepared(strategy.runtime_request()),
116 )
117 })
118 }
119
120 fn execute_prepared_order_sensitive_terminal_output(
124 &self,
125 strategy: PreparedFluentOrderSensitiveTerminalStrategy,
126 ) -> Result<ScalarTerminalBoundaryOutput, QueryError>
127 where
128 E: EntityValue,
129 {
130 self.execute_scalar_non_paged_terminal(move |load, plan| {
131 load.execute_scalar_terminal_request(
132 plan,
133 order_sensitive_terminal_boundary_request_from_prepared(
134 strategy.runtime_request().clone(),
135 ),
136 )
137 })
138 }
139
140 fn execute_prepared_projection_terminal_output(
144 &self,
145 strategy: PreparedFluentProjectionStrategy,
146 ) -> Result<crate::db::executor::ScalarProjectionBoundaryOutput, QueryError>
147 where
148 E: EntityValue,
149 {
150 self.execute_scalar_non_paged_terminal(move |load, plan| {
151 load.execute_scalar_projection_boundary(
152 plan,
153 strategy.target_field().clone(),
154 projection_boundary_request_from_prepared(strategy.runtime_request()),
155 )
156 })
157 }
158
159 fn explain_prepared_order_sensitive_non_paged_terminal(
162 &self,
163 strategy: &PreparedFluentOrderSensitiveTerminalStrategy,
164 ) -> Result<ExplainAggregateTerminalPlan, QueryError>
165 where
166 E: EntityValue,
167 {
168 self.ensure_non_paged_mode_ready()?;
169
170 self.session
171 .explain_query_prepared_order_sensitive_terminal_with_visible_indexes(
172 self.query(),
173 strategy,
174 )
175 }
176
177 pub fn is_empty(&self) -> Result<bool, QueryError>
183 where
184 E: EntityValue,
185 {
186 self.not_exists()
187 }
188
189 pub fn not_exists(&self) -> Result<bool, QueryError>
191 where
192 E: EntityValue,
193 {
194 Ok(!self.exists()?)
195 }
196
197 pub fn exists(&self) -> Result<bool, QueryError>
199 where
200 E: EntityValue,
201 {
202 self.execute_prepared_scalar_terminal_output(
203 PreparedFluentScalarTerminalStrategy::exists_rows(),
204 )?
205 .into_exists()
206 .map_err(QueryError::execute)
207 }
208
209 pub fn explain_exists(&self) -> Result<ExplainAggregateTerminalPlan, QueryError>
211 where
212 E: EntityValue,
213 {
214 self.explain_prepared_scalar_non_paged_terminal(
215 &PreparedFluentScalarTerminalStrategy::exists_rows(),
216 )
217 }
218
219 pub fn explain_not_exists(&self) -> Result<ExplainAggregateTerminalPlan, QueryError>
223 where
224 E: EntityValue,
225 {
226 self.explain_exists()
227 }
228
229 pub fn explain_execution(&self) -> Result<ExplainExecutionNodeDescriptor, QueryError>
231 where
232 E: EntityValue,
233 {
234 self.session
235 .explain_query_execution_with_visible_indexes(self.query())
236 }
237
238 pub fn explain_execution_text(&self) -> Result<String, QueryError>
240 where
241 E: EntityValue,
242 {
243 self.session
244 .explain_query_execution_text_with_visible_indexes(self.query())
245 }
246
247 pub fn explain_execution_json(&self) -> Result<String, QueryError>
249 where
250 E: EntityValue,
251 {
252 self.session
253 .explain_query_execution_json_with_visible_indexes(self.query())
254 }
255
256 pub fn explain_execution_verbose(&self) -> Result<String, QueryError>
258 where
259 E: EntityValue,
260 {
261 self.session
262 .explain_query_execution_verbose_with_visible_indexes(self.query())
263 }
264
265 pub fn count(&self) -> Result<u32, QueryError>
267 where
268 E: EntityValue,
269 {
270 self.execute_prepared_scalar_terminal_output(
271 PreparedFluentScalarTerminalStrategy::count_rows(),
272 )?
273 .into_count()
274 .map_err(QueryError::execute)
275 }
276
277 pub fn bytes(&self) -> Result<u64, QueryError>
280 where
281 E: EntityValue,
282 {
283 self.execute_scalar_non_paged_terminal(|load, plan| load.bytes(plan))
284 }
285
286 pub fn bytes_by(&self, field: impl AsRef<str>) -> Result<u64, QueryError>
289 where
290 E: EntityValue,
291 {
292 self.ensure_non_paged_mode_ready()?;
293
294 Self::with_slot(field, |target_slot| {
295 self.session
296 .execute_load_query_with(self.query(), move |load, plan| {
297 load.bytes_by_slot(plan, target_slot)
298 })
299 })
300 }
301
302 pub fn explain_bytes_by(
304 &self,
305 field: impl AsRef<str>,
306 ) -> Result<ExplainExecutionNodeDescriptor, QueryError>
307 where
308 E: EntityValue,
309 {
310 self.ensure_non_paged_mode_ready()?;
311
312 Self::with_slot(field, |target_slot| {
313 self.session
314 .explain_query_bytes_by_with_visible_indexes(self.query(), target_slot.field())
315 })
316 }
317
318 pub fn min(&self) -> Result<Option<Id<E>>, QueryError>
320 where
321 E: EntityValue,
322 {
323 self.execute_prepared_scalar_terminal_output(
324 PreparedFluentScalarTerminalStrategy::id_terminal(AggregateKind::Min),
325 )?
326 .into_id()
327 .map_err(QueryError::execute)
328 }
329
330 pub fn explain_min(&self) -> Result<ExplainAggregateTerminalPlan, QueryError>
332 where
333 E: EntityValue,
334 {
335 self.explain_prepared_scalar_non_paged_terminal(
336 &PreparedFluentScalarTerminalStrategy::id_terminal(AggregateKind::Min),
337 )
338 }
339
340 pub fn min_by(&self, field: impl AsRef<str>) -> Result<Option<Id<E>>, QueryError>
344 where
345 E: EntityValue,
346 {
347 self.ensure_non_paged_mode_ready()?;
348
349 Self::with_slot(field, |target_slot| {
350 self.execute_prepared_scalar_terminal_output(
351 PreparedFluentScalarTerminalStrategy::id_by_slot(AggregateKind::Min, target_slot),
352 )?
353 .into_id()
354 .map_err(QueryError::execute)
355 })
356 }
357
358 pub fn max(&self) -> Result<Option<Id<E>>, QueryError>
360 where
361 E: EntityValue,
362 {
363 self.execute_prepared_scalar_terminal_output(
364 PreparedFluentScalarTerminalStrategy::id_terminal(AggregateKind::Max),
365 )?
366 .into_id()
367 .map_err(QueryError::execute)
368 }
369
370 pub fn explain_max(&self) -> Result<ExplainAggregateTerminalPlan, QueryError>
372 where
373 E: EntityValue,
374 {
375 self.explain_prepared_scalar_non_paged_terminal(
376 &PreparedFluentScalarTerminalStrategy::id_terminal(AggregateKind::Max),
377 )
378 }
379
380 pub fn max_by(&self, field: impl AsRef<str>) -> Result<Option<Id<E>>, QueryError>
384 where
385 E: EntityValue,
386 {
387 self.ensure_non_paged_mode_ready()?;
388
389 Self::with_slot(field, |target_slot| {
390 self.execute_prepared_scalar_terminal_output(
391 PreparedFluentScalarTerminalStrategy::id_by_slot(AggregateKind::Max, target_slot),
392 )?
393 .into_id()
394 .map_err(QueryError::execute)
395 })
396 }
397
398 pub fn nth_by(&self, field: impl AsRef<str>, nth: usize) -> Result<Option<Id<E>>, QueryError>
401 where
402 E: EntityValue,
403 {
404 self.ensure_non_paged_mode_ready()?;
405
406 Self::with_slot(field, |target_slot| {
407 self.execute_prepared_order_sensitive_terminal_output(
408 PreparedFluentOrderSensitiveTerminalStrategy::nth_by_slot(target_slot, nth),
409 )?
410 .into_id()
411 .map_err(QueryError::execute)
412 })
413 }
414
415 pub fn sum_by(&self, field: impl AsRef<str>) -> Result<Option<Decimal>, QueryError>
417 where
418 E: EntityValue,
419 {
420 self.ensure_non_paged_mode_ready()?;
421
422 Self::with_slot(field, |target_slot| {
423 self.execute_prepared_numeric_field_terminal(
424 PreparedFluentNumericFieldStrategy::sum_by_slot(target_slot),
425 )
426 })
427 }
428
429 pub fn sum_distinct_by(&self, field: impl AsRef<str>) -> Result<Option<Decimal>, QueryError>
431 where
432 E: EntityValue,
433 {
434 self.ensure_non_paged_mode_ready()?;
435
436 Self::with_slot(field, |target_slot| {
437 self.execute_prepared_numeric_field_terminal(
438 PreparedFluentNumericFieldStrategy::sum_distinct_by_slot(target_slot),
439 )
440 })
441 }
442
443 pub fn avg_by(&self, field: impl AsRef<str>) -> Result<Option<Decimal>, QueryError>
445 where
446 E: EntityValue,
447 {
448 self.ensure_non_paged_mode_ready()?;
449
450 Self::with_slot(field, |target_slot| {
451 self.execute_prepared_numeric_field_terminal(
452 PreparedFluentNumericFieldStrategy::avg_by_slot(target_slot),
453 )
454 })
455 }
456
457 pub fn avg_distinct_by(&self, field: impl AsRef<str>) -> Result<Option<Decimal>, QueryError>
459 where
460 E: EntityValue,
461 {
462 self.ensure_non_paged_mode_ready()?;
463
464 Self::with_slot(field, |target_slot| {
465 self.execute_prepared_numeric_field_terminal(
466 PreparedFluentNumericFieldStrategy::avg_distinct_by_slot(target_slot),
467 )
468 })
469 }
470
471 pub fn median_by(&self, field: impl AsRef<str>) -> Result<Option<Id<E>>, QueryError>
476 where
477 E: EntityValue,
478 {
479 self.ensure_non_paged_mode_ready()?;
480
481 Self::with_slot(field, |target_slot| {
482 self.execute_prepared_order_sensitive_terminal_output(
483 PreparedFluentOrderSensitiveTerminalStrategy::median_by_slot(target_slot),
484 )?
485 .into_id()
486 .map_err(QueryError::execute)
487 })
488 }
489
490 pub fn count_distinct_by(&self, field: impl AsRef<str>) -> Result<u32, QueryError>
493 where
494 E: EntityValue,
495 {
496 self.ensure_non_paged_mode_ready()?;
497
498 Self::with_slot(field, |target_slot| {
499 self.execute_prepared_projection_terminal_output(
500 PreparedFluentProjectionStrategy::count_distinct_by_slot(target_slot),
501 )?
502 .into_count()
503 .map_err(QueryError::execute)
504 })
505 }
506
507 pub fn min_max_by(&self, field: impl AsRef<str>) -> Result<MinMaxByIds<E>, QueryError>
511 where
512 E: EntityValue,
513 {
514 self.ensure_non_paged_mode_ready()?;
515
516 Self::with_slot(field, |target_slot| {
517 self.execute_prepared_order_sensitive_terminal_output(
518 PreparedFluentOrderSensitiveTerminalStrategy::min_max_by_slot(target_slot),
519 )?
520 .into_id_pair()
521 .map_err(QueryError::execute)
522 })
523 }
524
525 pub fn values_by(&self, field: impl AsRef<str>) -> Result<Vec<Value>, QueryError>
527 where
528 E: EntityValue,
529 {
530 self.ensure_non_paged_mode_ready()?;
531
532 Self::with_slot(field, |target_slot| {
533 self.execute_prepared_projection_terminal_output(
534 PreparedFluentProjectionStrategy::values_by_slot(target_slot),
535 )?
536 .into_values()
537 .map_err(QueryError::execute)
538 })
539 }
540
541 pub fn take(&self, take_count: u32) -> Result<EntityResponse<E>, QueryError>
543 where
544 E: EntityValue,
545 {
546 self.execute_scalar_non_paged_terminal(|load, plan| load.take(plan, take_count))
547 }
548
549 pub fn top_k_by(
557 &self,
558 field: impl AsRef<str>,
559 take_count: u32,
560 ) -> Result<EntityResponse<E>, QueryError>
561 where
562 E: EntityValue,
563 {
564 self.ensure_non_paged_mode_ready()?;
565
566 Self::with_slot(field, |target_slot| {
567 self.session
568 .execute_load_query_with(self.query(), move |load, plan| {
569 load.top_k_by_slot(plan, target_slot, take_count)
570 })
571 })
572 }
573
574 pub fn bottom_k_by(
582 &self,
583 field: impl AsRef<str>,
584 take_count: u32,
585 ) -> Result<EntityResponse<E>, QueryError>
586 where
587 E: EntityValue,
588 {
589 self.ensure_non_paged_mode_ready()?;
590
591 Self::with_slot(field, |target_slot| {
592 self.session
593 .execute_load_query_with(self.query(), move |load, plan| {
594 load.bottom_k_by_slot(plan, target_slot, take_count)
595 })
596 })
597 }
598
599 pub fn top_k_by_values(
607 &self,
608 field: impl AsRef<str>,
609 take_count: u32,
610 ) -> Result<Vec<Value>, QueryError>
611 where
612 E: EntityValue,
613 {
614 self.ensure_non_paged_mode_ready()?;
615
616 Self::with_slot(field, |target_slot| {
617 self.session
618 .execute_load_query_with(self.query(), move |load, plan| {
619 load.top_k_by_values_slot(plan, target_slot, take_count)
620 })
621 })
622 }
623
624 pub fn bottom_k_by_values(
632 &self,
633 field: impl AsRef<str>,
634 take_count: u32,
635 ) -> Result<Vec<Value>, QueryError>
636 where
637 E: EntityValue,
638 {
639 self.ensure_non_paged_mode_ready()?;
640
641 Self::with_slot(field, |target_slot| {
642 self.session
643 .execute_load_query_with(self.query(), move |load, plan| {
644 load.bottom_k_by_values_slot(plan, target_slot, take_count)
645 })
646 })
647 }
648
649 pub fn top_k_by_with_ids(
657 &self,
658 field: impl AsRef<str>,
659 take_count: u32,
660 ) -> Result<Vec<(Id<E>, Value)>, QueryError>
661 where
662 E: EntityValue,
663 {
664 self.ensure_non_paged_mode_ready()?;
665
666 Self::with_slot(field, |target_slot| {
667 self.session
668 .execute_load_query_with(self.query(), move |load, plan| {
669 load.top_k_by_with_ids_slot(plan, target_slot, take_count)
670 })
671 })
672 }
673
674 pub fn bottom_k_by_with_ids(
682 &self,
683 field: impl AsRef<str>,
684 take_count: u32,
685 ) -> Result<Vec<(Id<E>, Value)>, QueryError>
686 where
687 E: EntityValue,
688 {
689 self.ensure_non_paged_mode_ready()?;
690
691 Self::with_slot(field, |target_slot| {
692 self.session
693 .execute_load_query_with(self.query(), move |load, plan| {
694 load.bottom_k_by_with_ids_slot(plan, target_slot, take_count)
695 })
696 })
697 }
698
699 pub fn distinct_values_by(&self, field: impl AsRef<str>) -> Result<Vec<Value>, QueryError>
702 where
703 E: EntityValue,
704 {
705 self.ensure_non_paged_mode_ready()?;
706
707 Self::with_slot(field, |target_slot| {
708 self.execute_prepared_projection_terminal_output(
709 PreparedFluentProjectionStrategy::distinct_values_by_slot(target_slot),
710 )?
711 .into_values()
712 .map_err(QueryError::execute)
713 })
714 }
715
716 pub fn values_by_with_ids(
719 &self,
720 field: impl AsRef<str>,
721 ) -> Result<Vec<(Id<E>, Value)>, QueryError>
722 where
723 E: EntityValue,
724 {
725 self.ensure_non_paged_mode_ready()?;
726
727 Self::with_slot(field, |target_slot| {
728 self.execute_prepared_projection_terminal_output(
729 PreparedFluentProjectionStrategy::values_by_with_ids_slot(target_slot),
730 )?
731 .into_values_with_ids()
732 .map_err(QueryError::execute)
733 })
734 }
735
736 pub fn first_value_by(&self, field: impl AsRef<str>) -> Result<Option<Value>, QueryError>
739 where
740 E: EntityValue,
741 {
742 self.ensure_non_paged_mode_ready()?;
743
744 Self::with_slot(field, |target_slot| {
745 self.execute_prepared_projection_terminal_output(
746 PreparedFluentProjectionStrategy::first_value_by_slot(target_slot),
747 )?
748 .into_terminal_value()
749 .map_err(QueryError::execute)
750 })
751 }
752
753 pub fn last_value_by(&self, field: impl AsRef<str>) -> Result<Option<Value>, QueryError>
756 where
757 E: EntityValue,
758 {
759 self.ensure_non_paged_mode_ready()?;
760
761 Self::with_slot(field, |target_slot| {
762 self.execute_prepared_projection_terminal_output(
763 PreparedFluentProjectionStrategy::last_value_by_slot(target_slot),
764 )?
765 .into_terminal_value()
766 .map_err(QueryError::execute)
767 })
768 }
769
770 pub fn first(&self) -> Result<Option<Id<E>>, QueryError>
772 where
773 E: EntityValue,
774 {
775 self.execute_prepared_order_sensitive_terminal_output(
776 PreparedFluentOrderSensitiveTerminalStrategy::first(),
777 )?
778 .into_id()
779 .map_err(QueryError::execute)
780 }
781
782 pub fn explain_first(&self) -> Result<ExplainAggregateTerminalPlan, QueryError>
784 where
785 E: EntityValue,
786 {
787 self.explain_prepared_order_sensitive_non_paged_terminal(
788 &PreparedFluentOrderSensitiveTerminalStrategy::first(),
789 )
790 }
791
792 pub fn last(&self) -> Result<Option<Id<E>>, QueryError>
794 where
795 E: EntityValue,
796 {
797 self.execute_prepared_order_sensitive_terminal_output(
798 PreparedFluentOrderSensitiveTerminalStrategy::last(),
799 )?
800 .into_id()
801 .map_err(QueryError::execute)
802 }
803
804 pub fn explain_last(&self) -> Result<ExplainAggregateTerminalPlan, QueryError>
806 where
807 E: EntityValue,
808 {
809 self.explain_prepared_order_sensitive_non_paged_terminal(
810 &PreparedFluentOrderSensitiveTerminalStrategy::last(),
811 )
812 }
813
814 pub fn require_one(&self) -> Result<(), QueryError>
816 where
817 E: EntityValue,
818 {
819 self.execute()?.require_one()?;
820 Ok(())
821 }
822
823 pub fn require_some(&self) -> Result<(), QueryError>
825 where
826 E: EntityValue,
827 {
828 self.execute()?.require_some()?;
829 Ok(())
830 }
831}
832
833fn scalar_terminal_boundary_request_from_prepared(
834 request: PreparedFluentScalarTerminalRuntimeRequest,
835) -> ScalarTerminalBoundaryRequest {
836 match request {
837 PreparedFluentScalarTerminalRuntimeRequest::CountRows => {
838 ScalarTerminalBoundaryRequest::Count
839 }
840 PreparedFluentScalarTerminalRuntimeRequest::ExistsRows => {
841 ScalarTerminalBoundaryRequest::Exists
842 }
843 PreparedFluentScalarTerminalRuntimeRequest::IdTerminal { kind } => {
844 ScalarTerminalBoundaryRequest::IdTerminal { kind }
845 }
846 PreparedFluentScalarTerminalRuntimeRequest::IdBySlot { kind, target_field } => {
847 ScalarTerminalBoundaryRequest::IdBySlot { kind, target_field }
848 }
849 }
850}
851
852const fn numeric_field_boundary_request_from_prepared(
853 request: PreparedFluentNumericFieldRuntimeRequest,
854) -> ScalarNumericFieldBoundaryRequest {
855 match request {
856 PreparedFluentNumericFieldRuntimeRequest::Sum => ScalarNumericFieldBoundaryRequest::Sum,
857 PreparedFluentNumericFieldRuntimeRequest::SumDistinct => {
858 ScalarNumericFieldBoundaryRequest::SumDistinct
859 }
860 PreparedFluentNumericFieldRuntimeRequest::Avg => ScalarNumericFieldBoundaryRequest::Avg,
861 PreparedFluentNumericFieldRuntimeRequest::AvgDistinct => {
862 ScalarNumericFieldBoundaryRequest::AvgDistinct
863 }
864 }
865}
866
867fn order_sensitive_terminal_boundary_request_from_prepared(
868 request: PreparedFluentOrderSensitiveTerminalRuntimeRequest,
869) -> ScalarTerminalBoundaryRequest {
870 match request {
871 PreparedFluentOrderSensitiveTerminalRuntimeRequest::ResponseOrder { kind } => {
872 ScalarTerminalBoundaryRequest::IdTerminal { kind }
873 }
874 PreparedFluentOrderSensitiveTerminalRuntimeRequest::NthBySlot { target_field, nth } => {
875 ScalarTerminalBoundaryRequest::NthBySlot { target_field, nth }
876 }
877 PreparedFluentOrderSensitiveTerminalRuntimeRequest::MedianBySlot { target_field } => {
878 ScalarTerminalBoundaryRequest::MedianBySlot { target_field }
879 }
880 PreparedFluentOrderSensitiveTerminalRuntimeRequest::MinMaxBySlot { target_field } => {
881 ScalarTerminalBoundaryRequest::MinMaxBySlot { target_field }
882 }
883 }
884}
885
886const fn projection_boundary_request_from_prepared(
887 request: PreparedFluentProjectionRuntimeRequest,
888) -> ScalarProjectionBoundaryRequest {
889 match request {
890 PreparedFluentProjectionRuntimeRequest::Values => ScalarProjectionBoundaryRequest::Values,
891 PreparedFluentProjectionRuntimeRequest::DistinctValues => {
892 ScalarProjectionBoundaryRequest::DistinctValues
893 }
894 PreparedFluentProjectionRuntimeRequest::CountDistinct => {
895 ScalarProjectionBoundaryRequest::CountDistinct
896 }
897 PreparedFluentProjectionRuntimeRequest::ValuesWithIds => {
898 ScalarProjectionBoundaryRequest::ValuesWithIds
899 }
900 PreparedFluentProjectionRuntimeRequest::TerminalValue { terminal_kind } => {
901 ScalarProjectionBoundaryRequest::TerminalValue { terminal_kind }
902 }
903 }
904}