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_with_schema(
349 &self,
350 schema_info: &SchemaInfo,
351 ) -> bool {
352 self.intent
353 .trivial_scalar_load_fast_path_eligible_with_schema(schema_info)
354 }
355
356 #[must_use]
357 #[cfg(test)]
358 pub(in crate::db) fn structural_cache_key(
359 &self,
360 ) -> crate::db::query::intent::StructuralQueryCacheKey {
361 crate::db::query::intent::StructuralQueryCacheKey::from_query_model(&self.intent)
362 }
363
364 #[must_use]
365 pub(in crate::db) fn structural_cache_key_with_normalized_predicate_fingerprint(
366 &self,
367 predicate_fingerprint: Option<[u8; 32]>,
368 ) -> crate::db::query::intent::StructuralQueryCacheKey {
369 self.intent
370 .structural_cache_key_with_normalized_predicate_fingerprint(predicate_fingerprint)
371 }
372
373 fn build_plan_for_visibility(
376 &self,
377 visible_indexes: Option<&VisibleIndexes<'_>>,
378 ) -> Result<AccessPlannedQuery, QueryError> {
379 match visible_indexes {
380 Some(visible_indexes) => self.build_plan_with_visible_indexes(visible_indexes),
381 None => self.build_plan(),
382 }
383 }
384
385 fn finalize_access_choice_for_visibility(
386 &self,
387 plan: &mut AccessPlannedQuery,
388 visible_indexes: Option<&VisibleIndexes<'_>>,
389 ) {
390 match visible_indexes {
391 Some(visible_indexes) => {
392 if let Some(schema_info) = visible_indexes.accepted_schema_info() {
393 plan.finalize_access_choice_for_model_with_accepted_indexes_and_schema(
394 self.intent.model(),
395 visible_indexes.accepted_field_path_indexes(),
396 visible_indexes.accepted_expression_indexes(),
397 schema_info,
398 );
399 } else {
400 plan.finalize_access_choice_for_model_only_with_indexes(
401 self.intent.model(),
402 visible_indexes.generated_model_only_indexes(),
403 );
404 }
405 }
406 None => {
407 plan.finalize_access_choice_for_model_only_with_indexes(
408 self.intent.model(),
409 self.intent.model().indexes(),
410 );
411 }
412 }
413 }
414
415 fn validate_access_requirements_for_visibility(
416 &self,
417 plan: &mut AccessPlannedQuery,
418 visible_indexes: Option<&VisibleIndexes<'_>>,
419 ) -> Result<(), QueryError> {
420 if self.access_requirements.is_empty() {
421 return Ok(());
422 }
423
424 self.finalize_access_choice_for_visibility(plan, visible_indexes);
425 self.access_requirements.validate(plan)
426 }
427
428 const fn require_index(mut self) -> Self {
429 self.access_requirements.require_index();
430 self
431 }
432
433 fn require_index_named(mut self, index_name: impl Into<String>) -> Self {
434 self.access_requirements.require_index_named(index_name);
435 self
436 }
437
438 const fn require_access_path(mut self, path: RequiredAccessPath) -> Self {
439 self.access_requirements.require_access_path(path);
440 self
441 }
442
443 const fn require_no_residual_filter(mut self) -> Self {
444 self.access_requirements.require_no_residual_filter();
445 self
446 }
447
448 #[must_use]
449 pub(in crate::db) const fn model(&self) -> &'static crate::model::entity::EntityModel {
450 self.intent.model()
451 }
452}
453
454#[derive(Clone, Debug)]
463struct QueryPlanHandle {
464 plan: Box<AccessPlannedQuery>,
465}
466
467impl QueryPlanHandle {
468 #[must_use]
469 fn from_plan(plan: AccessPlannedQuery) -> Self {
470 Self {
471 plan: Box::new(plan),
472 }
473 }
474
475 #[must_use]
476 const fn logical_plan(&self) -> &AccessPlannedQuery {
477 &self.plan
478 }
479
480 #[must_use]
481 #[cfg(test)]
482 fn into_inner(self) -> AccessPlannedQuery {
483 *self.plan
484 }
485}
486
487#[derive(Debug)]
495pub struct PlannedQuery<E: EntityKind> {
496 plan: QueryPlanHandle,
497 _marker: PhantomData<E>,
498}
499
500impl<E: EntityKind> PlannedQuery<E> {
501 #[must_use]
502 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
503 Self {
504 plan: QueryPlanHandle::from_plan(plan),
505 _marker: PhantomData,
506 }
507 }
508
509 #[must_use]
510 pub fn explain(&self) -> ExplainPlan {
511 self.plan.logical_plan().explain()
512 }
513
514 #[must_use]
516 pub fn plan_hash_hex(&self) -> String {
517 self.plan.logical_plan().fingerprint().to_string()
518 }
519}
520
521#[derive(Clone, Debug)]
531pub struct CompiledQuery<E: EntityKind> {
532 plan: QueryPlanHandle,
533 _marker: PhantomData<E>,
534}
535
536impl<E: EntityKind> CompiledQuery<E> {
537 #[must_use]
538 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
539 Self {
540 plan: QueryPlanHandle::from_plan(plan),
541 _marker: PhantomData,
542 }
543 }
544
545 #[must_use]
546 pub fn explain(&self) -> ExplainPlan {
547 self.plan.logical_plan().explain()
548 }
549
550 #[must_use]
552 pub fn plan_hash_hex(&self) -> String {
553 self.plan.logical_plan().fingerprint().to_string()
554 }
555
556 #[must_use]
557 #[cfg(test)]
558 pub(in crate::db) fn projection_spec(&self) -> crate::db::query::plan::expr::ProjectionSpec {
559 self.plan.logical_plan().projection_spec(E::MODEL)
560 }
561
562 #[cfg(test)]
564 pub(in crate::db) fn into_plan(self) -> AccessPlannedQuery {
565 self.plan.into_inner()
566 }
567
568 #[must_use]
569 #[cfg(test)]
570 pub(in crate::db) fn into_inner(self) -> AccessPlannedQuery {
571 self.plan.into_inner()
572 }
573}
574
575#[derive(Debug)]
587pub struct Query<E: EntityKind> {
588 inner: StructuralQuery,
589 _marker: PhantomData<E>,
590}
591
592impl<E: EntityKind> Query<E> {
593 pub(in crate::db) const fn from_inner(inner: StructuralQuery) -> Self {
595 Self {
596 inner,
597 _marker: PhantomData,
598 }
599 }
600
601 #[must_use]
605 pub const fn new(consistency: MissingRowPolicy) -> Self {
606 Self::from_inner(StructuralQuery::new(E::MODEL, consistency))
607 }
608
609 #[must_use]
611 pub const fn mode(&self) -> QueryMode {
612 self.inner.mode()
613 }
614
615 #[cfg(test)]
616 pub(in crate::db) fn explain_with_visible_indexes(
617 &self,
618 visible_indexes: &VisibleIndexes<'_>,
619 ) -> Result<ExplainPlan, QueryError> {
620 let mut plan = self.build_plan_for_visibility(Some(visible_indexes))?;
621 self.inner
622 .finalize_access_choice_for_visibility(&mut plan, Some(visible_indexes));
623
624 Ok(plan.explain())
625 }
626
627 #[cfg(test)]
628 pub(in crate::db) fn plan_hash_hex_with_visible_indexes(
629 &self,
630 visible_indexes: &VisibleIndexes<'_>,
631 ) -> Result<String, QueryError> {
632 let plan = self.build_plan_for_visibility(Some(visible_indexes))?;
633
634 Ok(plan.fingerprint().to_string())
635 }
636
637 fn build_plan_for_visibility(
640 &self,
641 visible_indexes: Option<&VisibleIndexes<'_>>,
642 ) -> Result<AccessPlannedQuery, QueryError> {
643 self.inner.build_plan_for_visibility(visible_indexes)
644 }
645
646 fn map_plan_for_visibility<T>(
650 &self,
651 visible_indexes: Option<&VisibleIndexes<'_>>,
652 map: impl FnOnce(AccessPlannedQuery) -> T,
653 ) -> Result<T, QueryError> {
654 let plan = self.build_plan_for_visibility(visible_indexes)?;
655
656 Ok(map(plan))
657 }
658
659 pub(in crate::db) fn planned_query_from_plan(plan: AccessPlannedQuery) -> PlannedQuery<E> {
661 PlannedQuery::from_plan(plan)
662 }
663
664 pub(in crate::db) fn compiled_query_from_plan(plan: AccessPlannedQuery) -> CompiledQuery<E> {
666 CompiledQuery::from_plan(plan)
667 }
668
669 #[must_use]
670 pub(in crate::db::query) fn has_explicit_order(&self) -> bool {
671 self.inner.has_explicit_order()
672 }
673
674 #[must_use]
675 pub(in crate::db) const fn structural(&self) -> &StructuralQuery {
676 &self.inner
677 }
678
679 #[must_use]
680 pub const fn has_grouping(&self) -> bool {
681 self.inner.has_grouping()
682 }
683
684 #[must_use]
685 pub(in crate::db::query) const fn load_spec(&self) -> Option<LoadSpec> {
686 self.inner.load_spec()
687 }
688
689 #[must_use]
691 pub fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
692 self.inner = self.inner.filter(expr);
693 self
694 }
695
696 #[cfg(test)]
700 #[must_use]
701 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
702 self.inner = self.inner.filter_expr(expr);
703 self
704 }
705
706 #[cfg(test)]
710 #[must_use]
711 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
712 self.inner = self.inner.filter_predicate(predicate);
713 self
714 }
715
716 #[must_use]
718 pub fn order_term(mut self, term: FluentOrderTerm) -> Self {
719 self.inner = self.inner.order_term(term);
720 self
721 }
722
723 #[must_use]
725 pub fn order_terms<I>(mut self, terms: I) -> Self
726 where
727 I: IntoIterator<Item = FluentOrderTerm>,
728 {
729 for term in terms {
730 self.inner = self.inner.order_term(term);
731 }
732
733 self
734 }
735
736 #[must_use]
738 pub fn distinct(mut self) -> Self {
739 self.inner = self.inner.distinct();
740 self
741 }
742
743 #[cfg(all(test, feature = "sql"))]
746 #[must_use]
747 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
748 where
749 I: IntoIterator<Item = S>,
750 S: Into<String>,
751 {
752 self.inner = self.inner.select_fields(fields);
753 self
754 }
755
756 pub fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
758 let Self { inner, .. } = self;
759 let inner = inner.group_by(field)?;
760
761 Ok(Self::from_inner(inner))
762 }
763
764 pub(in crate::db) fn group_by_with_schema(
765 self,
766 field: impl AsRef<str>,
767 schema: &SchemaInfo,
768 ) -> Result<Self, QueryError> {
769 let Self { inner, .. } = self;
770 let inner = inner.group_by_with_schema(field, schema)?;
771
772 Ok(Self::from_inner(inner))
773 }
774
775 #[must_use]
777 pub fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
778 self.inner = self.inner.aggregate(aggregate);
779 self
780 }
781
782 #[must_use]
784 pub fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
785 self.inner = self.inner.grouped_limits(max_groups, max_group_bytes);
786 self
787 }
788
789 pub fn having_group(
791 self,
792 field: impl AsRef<str>,
793 op: CompareOp,
794 value: InputValue,
795 ) -> Result<Self, QueryError> {
796 let Self { inner, .. } = self;
797 let inner = inner.having_group(field, op, value.into())?;
798
799 Ok(Self::from_inner(inner))
800 }
801
802 pub(in crate::db) fn having_group_with_schema(
803 self,
804 field: impl AsRef<str>,
805 schema: &SchemaInfo,
806 op: CompareOp,
807 value: InputValue,
808 ) -> Result<Self, QueryError> {
809 let Self { inner, .. } = self;
810 let inner = inner.having_group_with_schema(field, schema, op, value.into())?;
811
812 Ok(Self::from_inner(inner))
813 }
814
815 pub fn having_aggregate(
817 self,
818 aggregate_index: usize,
819 op: CompareOp,
820 value: InputValue,
821 ) -> Result<Self, QueryError> {
822 let Self { inner, .. } = self;
823 let inner = inner.having_aggregate(aggregate_index, op, value.into())?;
824
825 Ok(Self::from_inner(inner))
826 }
827
828 #[cfg(test)]
832 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
833 let Self { inner, .. } = self;
834 let inner = inner.having_expr(expr)?;
835
836 Ok(Self::from_inner(inner))
837 }
838
839 pub(in crate::db) fn by_id(self, id: E::Key) -> Self {
841 let Self { inner, .. } = self;
842
843 Self::from_inner(inner.by_id(id.to_key_value()))
844 }
845
846 pub(in crate::db) fn by_ids<I>(self, ids: I) -> Self
848 where
849 I: IntoIterator<Item = E::Key>,
850 {
851 let Self { inner, .. } = self;
852
853 Self::from_inner(inner.by_ids(ids.into_iter().map(|id| id.to_key_value())))
854 }
855
856 #[must_use]
858 pub fn delete(mut self) -> Self {
859 self.inner = self.inner.delete();
860 self
861 }
862
863 #[must_use]
870 pub fn limit(mut self, limit: u32) -> Self {
871 self.inner = self.inner.limit(limit);
872 self
873 }
874
875 #[must_use]
881 pub fn offset(mut self, offset: u32) -> Self {
882 self.inner = self.inner.offset(offset);
883 self
884 }
885
886 #[must_use]
891 pub fn require_index(mut self) -> Self {
892 self.inner = self.inner.require_index();
893 self
894 }
895
896 #[must_use]
901 pub fn require_index_named(mut self, index_name: impl Into<String>) -> Self {
902 self.inner = self.inner.require_index_named(index_name);
903 self
904 }
905
906 #[must_use]
910 pub fn require_access_path(mut self, path: RequiredAccessPath) -> Self {
911 self.inner = self.inner.require_access_path(path);
912 self
913 }
914
915 #[must_use]
920 pub fn require_no_residual_filter(mut self) -> Self {
921 self.inner = self.inner.require_no_residual_filter();
922 self
923 }
924
925 pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
927 let mut plan = self.build_plan_for_visibility(None)?;
928 self.inner
929 .finalize_access_choice_for_visibility(&mut plan, None);
930
931 Ok(plan.explain())
932 }
933
934 pub fn plan_hash_hex(&self) -> Result<String, QueryError> {
939 let plan = self.inner.build_plan()?;
940
941 Ok(plan.fingerprint().to_string())
942 }
943
944 pub fn planned(&self) -> Result<PlannedQuery<E>, QueryError> {
946 self.map_plan_for_visibility(None, Self::planned_query_from_plan)
947 }
948
949 pub fn plan(&self) -> Result<CompiledQuery<E>, QueryError> {
953 self.map_plan_for_visibility(None, Self::compiled_query_from_plan)
954 }
955
956 #[cfg(test)]
957 pub(in crate::db) fn plan_with_visible_indexes(
958 &self,
959 visible_indexes: &VisibleIndexes<'_>,
960 ) -> Result<CompiledQuery<E>, QueryError> {
961 self.map_plan_for_visibility(Some(visible_indexes), Self::compiled_query_from_plan)
962 }
963}
964
965impl<E> Query<E>
966where
967 E: EntityKind + SingletonEntity,
968 E::Key: Default,
969{
970 pub(in crate::db) fn only(self) -> Self {
972 let Self { inner, .. } = self;
973
974 Self::from_inner(inner.only(E::Key::default().to_key_value()))
975 }
976}