1#[cfg(feature = "sql")]
7use crate::db::query::plan::expr::ProjectionSelection;
8use crate::{
9 db::{
10 predicate::{CompareOp, MissingRowPolicy, Predicate},
11 query::{
12 builder::AggregateExpr,
13 explain::ExplainPlan,
14 expr::FilterExpr,
15 expr::OrderTerm as FluentOrderTerm,
16 intent::{AccessRequirements, QueryError, QueryModel, RequiredAccessPath},
17 plan::{
18 AccessPlannedQuery, LoadSpec, OrderSpec, PreparedScalarPlanningState, QueryMode,
19 VisibleIndexes, expr::Expr,
20 },
21 },
22 schema::SchemaInfo,
23 },
24 traits::{EntityKind, KeyValueCodec, SingletonEntity},
25 value::{InputValue, Value},
26};
27use core::marker::PhantomData;
28
29#[derive(Clone, Debug)]
38pub(in crate::db) struct StructuralQuery {
39 intent: QueryModel<'static, Value>,
40 access_requirements: AccessRequirements,
41}
42
43impl StructuralQuery {
44 #[must_use]
45 pub(in crate::db) const fn new(
46 model: &'static crate::model::entity::EntityModel,
47 consistency: MissingRowPolicy,
48 ) -> Self {
49 Self {
50 intent: QueryModel::new(model, consistency),
51 access_requirements: AccessRequirements::new(),
52 }
53 }
54
55 const fn from_parts(
59 intent: QueryModel<'static, Value>,
60 access_requirements: AccessRequirements,
61 ) -> Self {
62 Self {
63 intent,
64 access_requirements,
65 }
66 }
67
68 fn map_intent(
71 self,
72 map: impl FnOnce(QueryModel<'static, Value>) -> QueryModel<'static, Value>,
73 ) -> Self {
74 let Self {
75 intent,
76 access_requirements,
77 } = self;
78
79 Self::from_parts(map(intent), access_requirements)
80 }
81
82 fn try_map_intent(
85 self,
86 map: impl FnOnce(QueryModel<'static, Value>) -> Result<QueryModel<'static, Value>, QueryError>,
87 ) -> Result<Self, QueryError> {
88 let Self {
89 intent,
90 access_requirements,
91 } = self;
92
93 map(intent).map(|intent| Self::from_parts(intent, access_requirements))
94 }
95
96 #[must_use]
97 const fn mode(&self) -> QueryMode {
98 self.intent.mode()
99 }
100
101 #[must_use]
102 fn has_explicit_order(&self) -> bool {
103 self.intent.has_explicit_order()
104 }
105
106 #[must_use]
107 pub(in crate::db) const fn has_grouping(&self) -> bool {
108 self.intent.has_grouping()
109 }
110
111 #[must_use]
112 const fn load_spec(&self) -> Option<LoadSpec> {
113 match self.intent.mode() {
114 QueryMode::Load(spec) => Some(spec),
115 QueryMode::Delete(_) => None,
116 }
117 }
118
119 #[must_use]
120 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
121 self.intent = self.intent.filter_predicate(predicate);
122 self
123 }
124
125 #[must_use]
126 pub(in crate::db) fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
127 self.intent = self.intent.filter(expr.into());
128 self
129 }
130
131 #[must_use]
132 pub(in crate::db) fn filter_expr_with_normalized_predicate(
133 mut self,
134 expr: Expr,
135 predicate: Predicate,
136 ) -> Self {
137 self.intent = self
138 .intent
139 .filter_expr_with_normalized_predicate(expr, predicate);
140 self
141 }
142 pub(in crate::db) fn order_term(mut self, term: FluentOrderTerm) -> Self {
143 self.intent = self.intent.order_term(term);
144 self
145 }
146
147 #[must_use]
151 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
152 self.intent = self.intent.filter_expr(expr);
153 self
154 }
155
156 #[must_use]
157 pub(in crate::db) fn order_spec(mut self, order: OrderSpec) -> Self {
158 self.intent = self.intent.order_spec(order);
159 self
160 }
161
162 #[must_use]
163 pub(in crate::db) fn distinct(mut self) -> Self {
164 self.intent = self.intent.distinct();
165 self
166 }
167
168 #[cfg(feature = "sql")]
169 #[must_use]
170 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
171 where
172 I: IntoIterator<Item = S>,
173 S: Into<String>,
174 {
175 self.intent = self.intent.select_fields(fields);
176 self
177 }
178
179 #[cfg(feature = "sql")]
180 #[must_use]
181 pub(in crate::db) fn projection_selection(mut self, selection: ProjectionSelection) -> Self {
182 self.intent = self.intent.projection_selection(selection);
183 self
184 }
185
186 pub(in crate::db) fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
187 self.try_map_intent(|intent| intent.push_group_field(field.as_ref()))
188 }
189
190 pub(in crate::db) fn group_by_with_schema(
191 self,
192 field: impl AsRef<str>,
193 schema: &SchemaInfo,
194 ) -> Result<Self, QueryError> {
195 self.try_map_intent(|intent| intent.push_group_field_with_schema(field.as_ref(), schema))
196 }
197
198 #[must_use]
199 pub(in crate::db) fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
200 self.intent = self.intent.push_group_aggregate(aggregate);
201 self
202 }
203
204 #[must_use]
205 fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
206 self.intent = self.intent.grouped_limits(max_groups, max_group_bytes);
207 self
208 }
209
210 pub(in crate::db) fn having_group(
211 self,
212 field: impl AsRef<str>,
213 op: CompareOp,
214 value: Value,
215 ) -> Result<Self, QueryError> {
216 let field = field.as_ref().to_owned();
217 self.try_map_intent(|intent| intent.push_having_group_clause(&field, op, value))
218 }
219
220 pub(in crate::db) fn having_group_with_schema(
221 self,
222 field: impl AsRef<str>,
223 schema: &SchemaInfo,
224 op: CompareOp,
225 value: Value,
226 ) -> Result<Self, QueryError> {
227 let field = field.as_ref().to_owned();
228 self.try_map_intent(|intent| {
229 intent.push_having_group_clause_with_schema(&field, schema, op, value)
230 })
231 }
232
233 pub(in crate::db) fn having_aggregate(
234 self,
235 aggregate_index: usize,
236 op: CompareOp,
237 value: Value,
238 ) -> Result<Self, QueryError> {
239 self.try_map_intent(|intent| {
240 intent.push_having_aggregate_clause(aggregate_index, op, value)
241 })
242 }
243
244 #[cfg(test)]
245 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
246 self.try_map_intent(|intent| intent.push_having_expr(expr))
247 }
248
249 pub(in crate::db) fn having_expr_preserving_shape(
250 self,
251 expr: Expr,
252 ) -> Result<Self, QueryError> {
253 self.try_map_intent(|intent| intent.push_having_expr_preserving_shape(expr))
254 }
255
256 #[must_use]
257 fn by_id(self, id: Value) -> Self {
258 self.map_intent(|intent| intent.by_id(id))
259 }
260
261 #[must_use]
262 fn by_ids<I>(self, ids: I) -> Self
263 where
264 I: IntoIterator<Item = Value>,
265 {
266 self.map_intent(|intent| intent.by_ids(ids))
267 }
268
269 #[must_use]
270 fn only(self, id: Value) -> Self {
271 self.map_intent(|intent| intent.only(id))
272 }
273
274 #[must_use]
275 pub(in crate::db) fn delete(mut self) -> Self {
276 self.intent = self.intent.delete();
277 self
278 }
279
280 #[must_use]
281 pub(in crate::db) fn limit(mut self, limit: u32) -> Self {
282 self.intent = self.intent.limit(limit);
283 self
284 }
285
286 #[must_use]
287 pub(in crate::db) fn offset(mut self, offset: u32) -> Self {
288 self.intent = self.intent.offset(offset);
289 self
290 }
291
292 pub(in crate::db) fn build_plan(&self) -> Result<AccessPlannedQuery, QueryError> {
293 let mut plan = self.intent.build_plan_model()?;
294 self.validate_access_requirements_for_visibility(&mut plan, None)?;
295
296 Ok(plan)
297 }
298
299 pub(in crate::db) fn build_plan_with_visible_indexes(
300 &self,
301 visible_indexes: &VisibleIndexes<'_>,
302 ) -> Result<AccessPlannedQuery, QueryError> {
303 let mut plan = self.intent.build_plan_model_with_indexes(visible_indexes)?;
304 self.validate_access_requirements_for_visibility(&mut plan, Some(visible_indexes))?;
305
306 Ok(plan)
307 }
308
309 pub(in crate::db) fn prepare_scalar_planning_state_with_schema_info(
310 &self,
311 schema_info: SchemaInfo,
312 ) -> Result<PreparedScalarPlanningState<'_>, QueryError> {
313 self.intent
314 .prepare_scalar_planning_state_with_schema_info(schema_info)
315 }
316
317 pub(in crate::db) fn build_plan_with_visible_indexes_from_scalar_planning_state(
318 &self,
319 visible_indexes: &VisibleIndexes<'_>,
320 planning_state: PreparedScalarPlanningState<'_>,
321 ) -> Result<AccessPlannedQuery, QueryError> {
322 let mut plan = self
323 .intent
324 .build_plan_model_with_indexes_from_scalar_planning_state(
325 visible_indexes,
326 planning_state,
327 )?;
328 self.validate_access_requirements_for_visibility(&mut plan, Some(visible_indexes))?;
329
330 Ok(plan)
331 }
332
333 pub(in crate::db) fn try_build_trivial_scalar_load_plan_with_schema_info(
334 &self,
335 schema_info: SchemaInfo,
336 ) -> Result<Option<AccessPlannedQuery>, QueryError> {
337 let mut plan = self
338 .intent
339 .try_build_trivial_scalar_load_plan_with_schema_info(schema_info)?;
340 if let Some(plan) = &mut plan {
341 self.validate_access_requirements_for_visibility(plan, None)?;
342 }
343
344 Ok(plan)
345 }
346
347 #[must_use]
348 pub(in crate::db) fn trivial_scalar_load_fast_path_eligible(&self) -> bool {
349 self.intent.trivial_scalar_load_fast_path_eligible()
350 }
351
352 #[must_use]
353 #[cfg(test)]
354 pub(in crate::db) fn structural_cache_key(
355 &self,
356 ) -> crate::db::query::intent::StructuralQueryCacheKey {
357 crate::db::query::intent::StructuralQueryCacheKey::from_query_model(&self.intent)
358 }
359
360 #[must_use]
361 pub(in crate::db) fn structural_cache_key_with_normalized_predicate_fingerprint(
362 &self,
363 predicate_fingerprint: Option<[u8; 32]>,
364 ) -> crate::db::query::intent::StructuralQueryCacheKey {
365 self.intent
366 .structural_cache_key_with_normalized_predicate_fingerprint(predicate_fingerprint)
367 }
368
369 fn build_plan_for_visibility(
372 &self,
373 visible_indexes: Option<&VisibleIndexes<'_>>,
374 ) -> Result<AccessPlannedQuery, QueryError> {
375 match visible_indexes {
376 Some(visible_indexes) => self.build_plan_with_visible_indexes(visible_indexes),
377 None => self.build_plan(),
378 }
379 }
380
381 fn finalize_access_choice_for_visibility(
382 &self,
383 plan: &mut AccessPlannedQuery,
384 visible_indexes: Option<&VisibleIndexes<'_>>,
385 ) {
386 match visible_indexes {
387 Some(visible_indexes) => {
388 if let Some(schema_info) = visible_indexes.accepted_schema_info() {
389 plan.finalize_access_choice_for_model_with_accepted_indexes_and_schema(
390 self.intent.model(),
391 visible_indexes.accepted_field_path_indexes(),
392 visible_indexes.accepted_expression_indexes(),
393 schema_info,
394 );
395 } else {
396 plan.finalize_access_choice_for_model_only_with_indexes(
397 self.intent.model(),
398 visible_indexes.generated_model_only_indexes(),
399 );
400 }
401 }
402 None => {
403 plan.finalize_access_choice_for_model_only_with_indexes(
404 self.intent.model(),
405 self.intent.model().indexes(),
406 );
407 }
408 }
409 }
410
411 fn validate_access_requirements_for_visibility(
412 &self,
413 plan: &mut AccessPlannedQuery,
414 visible_indexes: Option<&VisibleIndexes<'_>>,
415 ) -> Result<(), QueryError> {
416 if self.access_requirements.is_empty() {
417 return Ok(());
418 }
419
420 self.finalize_access_choice_for_visibility(plan, visible_indexes);
421 self.access_requirements.validate(plan)
422 }
423
424 const fn require_index(mut self) -> Self {
425 self.access_requirements.require_index();
426 self
427 }
428
429 fn require_index_named(mut self, index_name: impl Into<String>) -> Self {
430 self.access_requirements.require_index_named(index_name);
431 self
432 }
433
434 const fn require_access_path(mut self, path: RequiredAccessPath) -> Self {
435 self.access_requirements.require_access_path(path);
436 self
437 }
438
439 const fn require_no_residual_filter(mut self) -> Self {
440 self.access_requirements.require_no_residual_filter();
441 self
442 }
443
444 #[must_use]
445 pub(in crate::db) const fn model(&self) -> &'static crate::model::entity::EntityModel {
446 self.intent.model()
447 }
448}
449
450#[derive(Clone, Debug)]
459struct QueryPlanHandle {
460 plan: Box<AccessPlannedQuery>,
461}
462
463impl QueryPlanHandle {
464 #[must_use]
465 fn from_plan(plan: AccessPlannedQuery) -> Self {
466 Self {
467 plan: Box::new(plan),
468 }
469 }
470
471 #[must_use]
472 const fn logical_plan(&self) -> &AccessPlannedQuery {
473 &self.plan
474 }
475
476 #[must_use]
477 #[cfg(test)]
478 fn into_inner(self) -> AccessPlannedQuery {
479 *self.plan
480 }
481}
482
483#[derive(Debug)]
491pub struct PlannedQuery<E: EntityKind> {
492 plan: QueryPlanHandle,
493 _marker: PhantomData<E>,
494}
495
496impl<E: EntityKind> PlannedQuery<E> {
497 #[must_use]
498 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
499 Self {
500 plan: QueryPlanHandle::from_plan(plan),
501 _marker: PhantomData,
502 }
503 }
504
505 #[must_use]
506 pub fn explain(&self) -> ExplainPlan {
507 self.plan.logical_plan().explain()
508 }
509
510 #[must_use]
512 pub fn plan_hash_hex(&self) -> String {
513 self.plan.logical_plan().fingerprint().to_string()
514 }
515}
516
517#[derive(Clone, Debug)]
527pub struct CompiledQuery<E: EntityKind> {
528 plan: QueryPlanHandle,
529 _marker: PhantomData<E>,
530}
531
532impl<E: EntityKind> CompiledQuery<E> {
533 #[must_use]
534 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
535 Self {
536 plan: QueryPlanHandle::from_plan(plan),
537 _marker: PhantomData,
538 }
539 }
540
541 #[must_use]
542 pub fn explain(&self) -> ExplainPlan {
543 self.plan.logical_plan().explain()
544 }
545
546 #[must_use]
548 pub fn plan_hash_hex(&self) -> String {
549 self.plan.logical_plan().fingerprint().to_string()
550 }
551
552 #[must_use]
553 #[cfg(test)]
554 pub(in crate::db) fn projection_spec(&self) -> crate::db::query::plan::expr::ProjectionSpec {
555 self.plan.logical_plan().projection_spec(E::MODEL)
556 }
557
558 #[cfg(test)]
560 pub(in crate::db) fn into_plan(self) -> AccessPlannedQuery {
561 self.plan.into_inner()
562 }
563
564 #[must_use]
565 #[cfg(test)]
566 pub(in crate::db) fn into_inner(self) -> AccessPlannedQuery {
567 self.plan.into_inner()
568 }
569}
570
571#[derive(Debug)]
583pub struct Query<E: EntityKind> {
584 inner: StructuralQuery,
585 _marker: PhantomData<E>,
586}
587
588impl<E: EntityKind> Query<E> {
589 pub(in crate::db) const fn from_inner(inner: StructuralQuery) -> Self {
591 Self {
592 inner,
593 _marker: PhantomData,
594 }
595 }
596
597 #[must_use]
601 pub const fn new(consistency: MissingRowPolicy) -> Self {
602 Self::from_inner(StructuralQuery::new(E::MODEL, consistency))
603 }
604
605 #[must_use]
607 pub const fn mode(&self) -> QueryMode {
608 self.inner.mode()
609 }
610
611 #[cfg(test)]
612 pub(in crate::db) fn explain_with_visible_indexes(
613 &self,
614 visible_indexes: &VisibleIndexes<'_>,
615 ) -> Result<ExplainPlan, QueryError> {
616 let mut plan = self.build_plan_for_visibility(Some(visible_indexes))?;
617 self.inner
618 .finalize_access_choice_for_visibility(&mut plan, Some(visible_indexes));
619
620 Ok(plan.explain())
621 }
622
623 #[cfg(test)]
624 pub(in crate::db) fn plan_hash_hex_with_visible_indexes(
625 &self,
626 visible_indexes: &VisibleIndexes<'_>,
627 ) -> Result<String, QueryError> {
628 let plan = self.build_plan_for_visibility(Some(visible_indexes))?;
629
630 Ok(plan.fingerprint().to_string())
631 }
632
633 fn build_plan_for_visibility(
636 &self,
637 visible_indexes: Option<&VisibleIndexes<'_>>,
638 ) -> Result<AccessPlannedQuery, QueryError> {
639 self.inner.build_plan_for_visibility(visible_indexes)
640 }
641
642 fn map_plan_for_visibility<T>(
646 &self,
647 visible_indexes: Option<&VisibleIndexes<'_>>,
648 map: impl FnOnce(AccessPlannedQuery) -> T,
649 ) -> Result<T, QueryError> {
650 let plan = self.build_plan_for_visibility(visible_indexes)?;
651
652 Ok(map(plan))
653 }
654
655 pub(in crate::db) fn planned_query_from_plan(plan: AccessPlannedQuery) -> PlannedQuery<E> {
657 PlannedQuery::from_plan(plan)
658 }
659
660 pub(in crate::db) fn compiled_query_from_plan(plan: AccessPlannedQuery) -> CompiledQuery<E> {
662 CompiledQuery::from_plan(plan)
663 }
664
665 #[must_use]
666 pub(in crate::db::query) fn has_explicit_order(&self) -> bool {
667 self.inner.has_explicit_order()
668 }
669
670 #[must_use]
671 pub(in crate::db) const fn structural(&self) -> &StructuralQuery {
672 &self.inner
673 }
674
675 #[must_use]
676 pub const fn has_grouping(&self) -> bool {
677 self.inner.has_grouping()
678 }
679
680 #[must_use]
681 pub(in crate::db::query) const fn load_spec(&self) -> Option<LoadSpec> {
682 self.inner.load_spec()
683 }
684
685 #[must_use]
687 pub fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
688 self.inner = self.inner.filter(expr);
689 self
690 }
691
692 #[cfg(test)]
696 #[must_use]
697 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
698 self.inner = self.inner.filter_expr(expr);
699 self
700 }
701
702 #[cfg(test)]
706 #[must_use]
707 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
708 self.inner = self.inner.filter_predicate(predicate);
709 self
710 }
711
712 #[must_use]
714 pub fn order_term(mut self, term: FluentOrderTerm) -> Self {
715 self.inner = self.inner.order_term(term);
716 self
717 }
718
719 #[must_use]
721 pub fn order_terms<I>(mut self, terms: I) -> Self
722 where
723 I: IntoIterator<Item = FluentOrderTerm>,
724 {
725 for term in terms {
726 self.inner = self.inner.order_term(term);
727 }
728
729 self
730 }
731
732 #[must_use]
734 pub fn distinct(mut self) -> Self {
735 self.inner = self.inner.distinct();
736 self
737 }
738
739 #[cfg(all(test, feature = "sql"))]
742 #[must_use]
743 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
744 where
745 I: IntoIterator<Item = S>,
746 S: Into<String>,
747 {
748 self.inner = self.inner.select_fields(fields);
749 self
750 }
751
752 pub fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
754 let Self { inner, .. } = self;
755 let inner = inner.group_by(field)?;
756
757 Ok(Self::from_inner(inner))
758 }
759
760 pub(in crate::db) fn group_by_with_schema(
761 self,
762 field: impl AsRef<str>,
763 schema: &SchemaInfo,
764 ) -> Result<Self, QueryError> {
765 let Self { inner, .. } = self;
766 let inner = inner.group_by_with_schema(field, schema)?;
767
768 Ok(Self::from_inner(inner))
769 }
770
771 #[must_use]
773 pub fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
774 self.inner = self.inner.aggregate(aggregate);
775 self
776 }
777
778 #[must_use]
780 pub fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
781 self.inner = self.inner.grouped_limits(max_groups, max_group_bytes);
782 self
783 }
784
785 pub fn having_group(
787 self,
788 field: impl AsRef<str>,
789 op: CompareOp,
790 value: InputValue,
791 ) -> Result<Self, QueryError> {
792 let Self { inner, .. } = self;
793 let inner = inner.having_group(field, op, value.into())?;
794
795 Ok(Self::from_inner(inner))
796 }
797
798 pub(in crate::db) fn having_group_with_schema(
799 self,
800 field: impl AsRef<str>,
801 schema: &SchemaInfo,
802 op: CompareOp,
803 value: InputValue,
804 ) -> Result<Self, QueryError> {
805 let Self { inner, .. } = self;
806 let inner = inner.having_group_with_schema(field, schema, op, value.into())?;
807
808 Ok(Self::from_inner(inner))
809 }
810
811 pub fn having_aggregate(
813 self,
814 aggregate_index: usize,
815 op: CompareOp,
816 value: InputValue,
817 ) -> Result<Self, QueryError> {
818 let Self { inner, .. } = self;
819 let inner = inner.having_aggregate(aggregate_index, op, value.into())?;
820
821 Ok(Self::from_inner(inner))
822 }
823
824 #[cfg(test)]
828 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
829 let Self { inner, .. } = self;
830 let inner = inner.having_expr(expr)?;
831
832 Ok(Self::from_inner(inner))
833 }
834
835 pub(in crate::db) fn by_id(self, id: E::Key) -> Self {
837 let Self { inner, .. } = self;
838
839 Self::from_inner(inner.by_id(id.to_key_value()))
840 }
841
842 pub(in crate::db) fn by_ids<I>(self, ids: I) -> Self
844 where
845 I: IntoIterator<Item = E::Key>,
846 {
847 let Self { inner, .. } = self;
848
849 Self::from_inner(inner.by_ids(ids.into_iter().map(|id| id.to_key_value())))
850 }
851
852 #[must_use]
854 pub fn delete(mut self) -> Self {
855 self.inner = self.inner.delete();
856 self
857 }
858
859 #[must_use]
866 pub fn limit(mut self, limit: u32) -> Self {
867 self.inner = self.inner.limit(limit);
868 self
869 }
870
871 #[must_use]
877 pub fn offset(mut self, offset: u32) -> Self {
878 self.inner = self.inner.offset(offset);
879 self
880 }
881
882 #[must_use]
887 pub fn require_index(mut self) -> Self {
888 self.inner = self.inner.require_index();
889 self
890 }
891
892 #[must_use]
897 pub fn require_index_named(mut self, index_name: impl Into<String>) -> Self {
898 self.inner = self.inner.require_index_named(index_name);
899 self
900 }
901
902 #[must_use]
906 pub fn require_access_path(mut self, path: RequiredAccessPath) -> Self {
907 self.inner = self.inner.require_access_path(path);
908 self
909 }
910
911 #[must_use]
916 pub fn require_no_residual_filter(mut self) -> Self {
917 self.inner = self.inner.require_no_residual_filter();
918 self
919 }
920
921 pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
923 let mut plan = self.build_plan_for_visibility(None)?;
924 self.inner
925 .finalize_access_choice_for_visibility(&mut plan, None);
926
927 Ok(plan.explain())
928 }
929
930 pub fn plan_hash_hex(&self) -> Result<String, QueryError> {
935 let plan = self.inner.build_plan()?;
936
937 Ok(plan.fingerprint().to_string())
938 }
939
940 pub fn planned(&self) -> Result<PlannedQuery<E>, QueryError> {
942 self.map_plan_for_visibility(None, Self::planned_query_from_plan)
943 }
944
945 pub fn plan(&self) -> Result<CompiledQuery<E>, QueryError> {
949 self.map_plan_for_visibility(None, Self::compiled_query_from_plan)
950 }
951
952 #[cfg(test)]
953 pub(in crate::db) fn plan_with_visible_indexes(
954 &self,
955 visible_indexes: &VisibleIndexes<'_>,
956 ) -> Result<CompiledQuery<E>, QueryError> {
957 self.map_plan_for_visibility(Some(visible_indexes), Self::compiled_query_from_plan)
958 }
959}
960
961impl<E> Query<E>
962where
963 E: EntityKind + SingletonEntity,
964 E::Key: Default,
965{
966 pub(in crate::db) fn only(self) -> Self {
968 let Self { inner, .. } = self;
969
970 Self::from_inner(inner.only(E::Key::default().to_key_value()))
971 }
972}