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 std::sync::OnceLock;
28
29use core::marker::PhantomData;
30
31#[derive(Clone, Debug)]
40pub(in crate::db) struct StructuralQuery {
41 intent: QueryModel<'static, Value>,
42 access_requirements: AccessRequirements,
43 structural_cache_key: OnceLock<crate::db::query::intent::StructuralQueryCacheKey>,
44}
45
46impl StructuralQuery {
47 #[must_use]
48 pub(in crate::db) const fn new(
49 model: &'static crate::model::entity::EntityModel,
50 consistency: MissingRowPolicy,
51 ) -> Self {
52 Self {
53 intent: QueryModel::new(model, consistency),
54 access_requirements: AccessRequirements::new(),
55 structural_cache_key: OnceLock::new(),
56 }
57 }
58
59 const fn from_intent_and_access_requirements(
63 intent: QueryModel<'static, Value>,
64 access_requirements: AccessRequirements,
65 ) -> Self {
66 Self {
67 intent,
68 access_requirements,
69 structural_cache_key: OnceLock::new(),
70 }
71 }
72
73 fn map_intent(
76 self,
77 map: impl FnOnce(QueryModel<'static, Value>) -> QueryModel<'static, Value>,
78 ) -> Self {
79 let Self {
80 intent,
81 access_requirements,
82 ..
83 } = self;
84
85 Self::from_intent_and_access_requirements(map(intent), access_requirements)
86 }
87
88 fn try_map_intent(
91 self,
92 map: impl FnOnce(QueryModel<'static, Value>) -> Result<QueryModel<'static, Value>, QueryError>,
93 ) -> Result<Self, QueryError> {
94 let Self {
95 intent,
96 access_requirements,
97 ..
98 } = self;
99
100 map(intent)
101 .map(|intent| Self::from_intent_and_access_requirements(intent, access_requirements))
102 }
103
104 #[must_use]
105 const fn mode(&self) -> QueryMode {
106 self.intent.mode()
107 }
108
109 #[must_use]
110 fn has_explicit_order(&self) -> bool {
111 self.intent.has_explicit_order()
112 }
113
114 #[must_use]
115 pub(in crate::db) const fn has_grouping(&self) -> bool {
116 self.intent.has_grouping()
117 }
118
119 #[must_use]
120 pub(in crate::db) const fn has_scalar_filter(&self) -> bool {
121 self.intent.has_scalar_filter()
122 }
123
124 #[must_use]
125 const fn load_spec(&self) -> Option<LoadSpec> {
126 match self.intent.mode() {
127 QueryMode::Load(spec) => Some(spec),
128 QueryMode::Delete(_) => None,
129 }
130 }
131
132 #[must_use]
133 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
134 self.intent = self.intent.filter_predicate(predicate);
135 self
136 }
137
138 #[must_use]
139 pub(in crate::db) fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
140 self.intent = self.intent.filter(expr.into());
141 self
142 }
143
144 #[must_use]
145 pub(in crate::db) fn filter_expr_with_normalized_predicate(
146 mut self,
147 expr: Expr,
148 predicate: Predicate,
149 ) -> Self {
150 self.intent = self
151 .intent
152 .filter_expr_with_normalized_predicate(expr, predicate);
153 self
154 }
155 pub(in crate::db) fn order_term(mut self, term: FluentOrderTerm) -> Self {
156 self.intent = self.intent.order_term(term);
157 self
158 }
159
160 #[must_use]
164 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
165 self.intent = self.intent.filter_expr(expr);
166 self
167 }
168
169 #[must_use]
170 pub(in crate::db) fn order_spec(mut self, order: OrderSpec) -> Self {
171 self.intent = self.intent.order_spec(order);
172 self
173 }
174
175 #[must_use]
176 pub(in crate::db) fn distinct(mut self) -> Self {
177 self.intent = self.intent.distinct();
178 self
179 }
180
181 #[cfg(feature = "sql")]
182 #[must_use]
183 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
184 where
185 I: IntoIterator<Item = S>,
186 S: Into<String>,
187 {
188 self.intent = self.intent.select_fields(fields);
189 self
190 }
191
192 #[cfg(feature = "sql")]
193 #[must_use]
194 pub(in crate::db) fn projection_selection(mut self, selection: ProjectionSelection) -> Self {
195 self.intent = self.intent.projection_selection(selection);
196 self
197 }
198
199 pub(in crate::db) fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
200 self.try_map_intent(|intent| intent.push_group_field(field.as_ref()))
201 }
202
203 pub(in crate::db) fn group_by_with_schema(
204 self,
205 field: impl AsRef<str>,
206 schema: &SchemaInfo,
207 ) -> Result<Self, QueryError> {
208 self.try_map_intent(|intent| intent.push_group_field_with_schema(field.as_ref(), schema))
209 }
210
211 #[must_use]
212 pub(in crate::db) fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
213 self.intent = self.intent.push_group_aggregate(aggregate);
214 self
215 }
216
217 #[must_use]
218 fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
219 self.intent = self.intent.grouped_limits(max_groups, max_group_bytes);
220 self
221 }
222
223 pub(in crate::db) fn having_group(
224 self,
225 field: impl AsRef<str>,
226 op: CompareOp,
227 value: Value,
228 ) -> Result<Self, QueryError> {
229 let field = field.as_ref().to_owned();
230 self.try_map_intent(|intent| intent.push_having_group_clause(&field, op, value))
231 }
232
233 pub(in crate::db) fn having_group_with_schema(
234 self,
235 field: impl AsRef<str>,
236 schema: &SchemaInfo,
237 op: CompareOp,
238 value: Value,
239 ) -> Result<Self, QueryError> {
240 let field = field.as_ref().to_owned();
241 self.try_map_intent(|intent| {
242 intent.push_having_group_clause_with_schema(&field, schema, op, value)
243 })
244 }
245
246 pub(in crate::db) fn having_aggregate(
247 self,
248 aggregate_index: usize,
249 op: CompareOp,
250 value: Value,
251 ) -> Result<Self, QueryError> {
252 self.try_map_intent(|intent| {
253 intent.push_having_aggregate_clause(aggregate_index, op, value)
254 })
255 }
256
257 #[cfg(test)]
258 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
259 self.try_map_intent(|intent| intent.push_having_expr(expr))
260 }
261
262 pub(in crate::db) fn having_expr_preserving_shape(
263 self,
264 expr: Expr,
265 ) -> Result<Self, QueryError> {
266 self.try_map_intent(|intent| intent.push_having_expr_preserving_shape(expr))
267 }
268
269 #[must_use]
270 fn by_id(self, id: Value) -> Self {
271 self.map_intent(|intent| intent.by_id(id))
272 }
273
274 #[must_use]
275 fn by_ids<I>(self, ids: I) -> Self
276 where
277 I: IntoIterator<Item = Value>,
278 {
279 self.map_intent(|intent| intent.by_ids(ids))
280 }
281
282 #[must_use]
283 fn only(self, id: Value) -> Self {
284 self.map_intent(|intent| intent.only(id))
285 }
286
287 #[must_use]
288 pub(in crate::db) fn delete(mut self) -> Self {
289 self.intent = self.intent.delete();
290 self
291 }
292
293 #[must_use]
294 pub(in crate::db) fn limit(mut self, limit: u32) -> Self {
295 self.intent = self.intent.limit(limit);
296 self
297 }
298
299 #[must_use]
300 pub(in crate::db) fn offset(mut self, offset: u32) -> Self {
301 self.intent = self.intent.offset(offset);
302 self
303 }
304
305 pub(in crate::db) fn build_plan(&self) -> Result<AccessPlannedQuery, QueryError> {
306 let mut plan = self.intent.build_plan_model()?;
307 self.validate_access_requirements_for_visibility(&mut plan, None)?;
308
309 Ok(plan)
310 }
311
312 pub(in crate::db) fn build_plan_with_visible_indexes(
313 &self,
314 visible_indexes: &VisibleIndexes<'_>,
315 ) -> Result<AccessPlannedQuery, QueryError> {
316 let mut plan = self.intent.build_plan_model_with_indexes(visible_indexes)?;
317 self.validate_access_requirements_for_visibility(&mut plan, Some(visible_indexes))?;
318
319 Ok(plan)
320 }
321
322 pub(in crate::db) fn prepare_scalar_planning_state_with_schema_info(
323 &self,
324 schema_info: SchemaInfo,
325 ) -> Result<PreparedScalarPlanningState<'_>, QueryError> {
326 self.intent
327 .prepare_scalar_planning_state_with_schema_info(schema_info)
328 }
329
330 pub(in crate::db) fn build_plan_with_visible_indexes_from_scalar_planning_state(
331 &self,
332 visible_indexes: &VisibleIndexes<'_>,
333 planning_state: PreparedScalarPlanningState<'_>,
334 ) -> Result<AccessPlannedQuery, QueryError> {
335 let mut plan = self
336 .intent
337 .build_plan_model_with_indexes_from_scalar_planning_state(
338 visible_indexes,
339 planning_state,
340 )?;
341 self.validate_access_requirements_for_visibility(&mut plan, Some(visible_indexes))?;
342
343 Ok(plan)
344 }
345
346 pub(in crate::db) fn try_build_trivial_scalar_load_plan_with_schema_info(
347 &self,
348 schema_info: SchemaInfo,
349 ) -> Result<Option<AccessPlannedQuery>, QueryError> {
350 let mut plan = self
351 .intent
352 .try_build_trivial_scalar_load_plan_with_schema_info(schema_info)?;
353 if let Some(plan) = &mut plan {
354 self.validate_access_requirements_for_visibility(plan, None)?;
355 }
356
357 Ok(plan)
358 }
359
360 #[must_use]
361 pub(in crate::db) fn trivial_scalar_load_fast_path_eligible_with_schema(
362 &self,
363 schema_info: &SchemaInfo,
364 ) -> bool {
365 self.intent
366 .trivial_scalar_load_fast_path_eligible_with_schema(schema_info)
367 }
368
369 #[must_use]
370 #[cfg(test)]
371 pub(in crate::db) fn structural_cache_key(
372 &self,
373 ) -> crate::db::query::intent::StructuralQueryCacheKey {
374 crate::db::query::intent::StructuralQueryCacheKey::from_query_model(&self.intent)
375 }
376
377 #[must_use]
378 pub(in crate::db) fn structural_cache_key_with_normalized_predicate_fingerprint(
379 &self,
380 predicate_fingerprint: Option<[u8; 32]>,
381 ) -> crate::db::query::intent::StructuralQueryCacheKey {
382 if predicate_fingerprint.is_none() {
383 return self
384 .structural_cache_key
385 .get_or_init(|| {
386 self.intent
387 .structural_cache_key_with_normalized_predicate_fingerprint(None)
388 })
389 .clone();
390 }
391
392 self.intent
393 .structural_cache_key_with_normalized_predicate_fingerprint(predicate_fingerprint)
394 }
395
396 fn build_plan_for_visibility(
399 &self,
400 visible_indexes: Option<&VisibleIndexes<'_>>,
401 ) -> Result<AccessPlannedQuery, QueryError> {
402 match visible_indexes {
403 Some(visible_indexes) => self.build_plan_with_visible_indexes(visible_indexes),
404 None => self.build_plan(),
405 }
406 }
407
408 fn finalize_access_choice_for_visibility(
409 &self,
410 plan: &mut AccessPlannedQuery,
411 visible_indexes: Option<&VisibleIndexes<'_>>,
412 ) {
413 match visible_indexes {
414 Some(visible_indexes) => {
415 if let Some(schema_info) = visible_indexes.accepted_schema_info() {
416 plan.finalize_access_choice_for_model_with_accepted_indexes_and_schema(
417 self.intent.model(),
418 visible_indexes.accepted_field_path_indexes(),
419 visible_indexes.accepted_expression_indexes(),
420 schema_info,
421 );
422 } else {
423 plan.finalize_access_choice_for_model_only_with_indexes(
424 self.intent.model(),
425 visible_indexes.generated_model_only_indexes(),
426 );
427 }
428 }
429 None => {
430 plan.finalize_access_choice_for_model_only_with_indexes(
431 self.intent.model(),
432 self.intent.model().indexes(),
433 );
434 }
435 }
436 }
437
438 fn validate_access_requirements_for_visibility(
439 &self,
440 plan: &mut AccessPlannedQuery,
441 visible_indexes: Option<&VisibleIndexes<'_>>,
442 ) -> Result<(), QueryError> {
443 if self.access_requirements.is_empty() {
444 return Ok(());
445 }
446
447 self.finalize_access_choice_for_visibility(plan, visible_indexes);
448 self.access_requirements.validate(plan)
449 }
450
451 const fn require_index(mut self) -> Self {
452 self.access_requirements.require_index();
453 self
454 }
455
456 fn require_index_named(mut self, index_name: impl Into<String>) -> Self {
457 self.access_requirements.require_index_named(index_name);
458 self
459 }
460
461 const fn require_access_path(mut self, path: RequiredAccessPath) -> Self {
462 self.access_requirements.require_access_path(path);
463 self
464 }
465
466 const fn require_no_residual_filter(mut self) -> Self {
467 self.access_requirements.require_no_residual_filter();
468 self
469 }
470
471 #[must_use]
472 pub(in crate::db) const fn model(&self) -> &'static crate::model::entity::EntityModel {
473 self.intent.model()
474 }
475}
476
477#[derive(Clone, Debug)]
486struct QueryPlanHandle {
487 plan: Box<AccessPlannedQuery>,
488}
489
490impl QueryPlanHandle {
491 #[must_use]
492 fn from_plan(plan: AccessPlannedQuery) -> Self {
493 Self {
494 plan: Box::new(plan),
495 }
496 }
497
498 #[must_use]
499 const fn logical_plan(&self) -> &AccessPlannedQuery {
500 &self.plan
501 }
502
503 #[must_use]
504 #[cfg(test)]
505 fn into_inner(self) -> AccessPlannedQuery {
506 *self.plan
507 }
508}
509
510#[derive(Debug)]
518pub struct PlannedQuery<E: EntityKind> {
519 plan: QueryPlanHandle,
520 _marker: PhantomData<E>,
521}
522
523impl<E: EntityKind> PlannedQuery<E> {
524 #[must_use]
525 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
526 Self {
527 plan: QueryPlanHandle::from_plan(plan),
528 _marker: PhantomData,
529 }
530 }
531
532 #[must_use]
533 pub fn explain(&self) -> ExplainPlan {
534 self.plan.logical_plan().explain()
535 }
536
537 #[must_use]
539 pub fn plan_hash_hex(&self) -> String {
540 self.plan.logical_plan().fingerprint().to_string()
541 }
542}
543
544#[derive(Clone, Debug)]
554pub struct CompiledQuery<E: EntityKind> {
555 plan: QueryPlanHandle,
556 _marker: PhantomData<E>,
557}
558
559impl<E: EntityKind> CompiledQuery<E> {
560 #[must_use]
561 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
562 Self {
563 plan: QueryPlanHandle::from_plan(plan),
564 _marker: PhantomData,
565 }
566 }
567
568 #[must_use]
569 pub fn explain(&self) -> ExplainPlan {
570 self.plan.logical_plan().explain()
571 }
572
573 #[must_use]
575 pub fn plan_hash_hex(&self) -> String {
576 self.plan.logical_plan().fingerprint().to_string()
577 }
578
579 #[must_use]
580 #[cfg(test)]
581 pub(in crate::db) fn projection_spec(&self) -> crate::db::query::plan::expr::ProjectionSpec {
582 self.plan.logical_plan().projection_spec(E::MODEL)
583 }
584
585 #[cfg(test)]
587 pub(in crate::db) fn into_plan(self) -> AccessPlannedQuery {
588 self.plan.into_inner()
589 }
590
591 #[must_use]
592 #[cfg(test)]
593 pub(in crate::db) fn into_inner(self) -> AccessPlannedQuery {
594 self.plan.into_inner()
595 }
596}
597
598#[derive(Debug)]
610pub struct Query<E: EntityKind> {
611 inner: StructuralQuery,
612 _marker: PhantomData<E>,
613}
614
615impl<E: EntityKind> Query<E> {
616 pub(in crate::db) const fn from_inner(inner: StructuralQuery) -> Self {
618 Self {
619 inner,
620 _marker: PhantomData,
621 }
622 }
623
624 #[must_use]
628 pub const fn new(consistency: MissingRowPolicy) -> Self {
629 Self::from_inner(StructuralQuery::new(E::MODEL, consistency))
630 }
631
632 #[must_use]
634 pub const fn mode(&self) -> QueryMode {
635 self.inner.mode()
636 }
637
638 #[cfg(test)]
639 pub(in crate::db) fn explain_with_visible_indexes(
640 &self,
641 visible_indexes: &VisibleIndexes<'_>,
642 ) -> Result<ExplainPlan, QueryError> {
643 let mut plan = self.build_plan_for_visibility(Some(visible_indexes))?;
644 self.inner
645 .finalize_access_choice_for_visibility(&mut plan, Some(visible_indexes));
646
647 Ok(plan.explain())
648 }
649
650 #[cfg(test)]
651 pub(in crate::db) fn plan_hash_hex_with_visible_indexes(
652 &self,
653 visible_indexes: &VisibleIndexes<'_>,
654 ) -> Result<String, QueryError> {
655 let plan = self.build_plan_for_visibility(Some(visible_indexes))?;
656
657 Ok(plan.fingerprint().to_string())
658 }
659
660 fn build_plan_for_visibility(
663 &self,
664 visible_indexes: Option<&VisibleIndexes<'_>>,
665 ) -> Result<AccessPlannedQuery, QueryError> {
666 self.inner.build_plan_for_visibility(visible_indexes)
667 }
668
669 fn map_plan_for_visibility<T>(
673 &self,
674 visible_indexes: Option<&VisibleIndexes<'_>>,
675 map: impl FnOnce(AccessPlannedQuery) -> T,
676 ) -> Result<T, QueryError> {
677 let plan = self.build_plan_for_visibility(visible_indexes)?;
678
679 Ok(map(plan))
680 }
681
682 pub(in crate::db) fn planned_query_from_plan(plan: AccessPlannedQuery) -> PlannedQuery<E> {
684 PlannedQuery::from_plan(plan)
685 }
686
687 pub(in crate::db) fn compiled_query_from_plan(plan: AccessPlannedQuery) -> CompiledQuery<E> {
689 CompiledQuery::from_plan(plan)
690 }
691
692 #[must_use]
693 pub(in crate::db::query) fn has_explicit_order(&self) -> bool {
694 self.inner.has_explicit_order()
695 }
696
697 #[must_use]
698 pub(in crate::db) const fn structural(&self) -> &StructuralQuery {
699 &self.inner
700 }
701
702 #[must_use]
703 pub const fn has_grouping(&self) -> bool {
704 self.inner.has_grouping()
705 }
706
707 #[must_use]
708 pub(in crate::db::query) const fn load_spec(&self) -> Option<LoadSpec> {
709 self.inner.load_spec()
710 }
711
712 #[must_use]
714 pub fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
715 self.inner = self.inner.filter(expr);
716 self
717 }
718
719 #[cfg(test)]
723 #[must_use]
724 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
725 self.inner = self.inner.filter_expr(expr);
726 self
727 }
728
729 #[cfg(test)]
733 #[must_use]
734 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
735 self.inner = self.inner.filter_predicate(predicate);
736 self
737 }
738
739 #[must_use]
741 pub fn order_term(mut self, term: FluentOrderTerm) -> Self {
742 self.inner = self.inner.order_term(term);
743 self
744 }
745
746 #[must_use]
748 pub fn order_terms<I>(mut self, terms: I) -> Self
749 where
750 I: IntoIterator<Item = FluentOrderTerm>,
751 {
752 for term in terms {
753 self.inner = self.inner.order_term(term);
754 }
755
756 self
757 }
758
759 #[must_use]
761 pub fn distinct(mut self) -> Self {
762 self.inner = self.inner.distinct();
763 self
764 }
765
766 #[cfg(all(test, feature = "sql"))]
769 #[must_use]
770 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
771 where
772 I: IntoIterator<Item = S>,
773 S: Into<String>,
774 {
775 self.inner = self.inner.select_fields(fields);
776 self
777 }
778
779 pub fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
781 let Self { inner, .. } = self;
782 let inner = inner.group_by(field)?;
783
784 Ok(Self::from_inner(inner))
785 }
786
787 pub(in crate::db) fn group_by_with_schema(
788 self,
789 field: impl AsRef<str>,
790 schema: &SchemaInfo,
791 ) -> Result<Self, QueryError> {
792 let Self { inner, .. } = self;
793 let inner = inner.group_by_with_schema(field, schema)?;
794
795 Ok(Self::from_inner(inner))
796 }
797
798 #[must_use]
800 pub fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
801 self.inner = self.inner.aggregate(aggregate);
802 self
803 }
804
805 #[must_use]
807 pub fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
808 self.inner = self.inner.grouped_limits(max_groups, max_group_bytes);
809 self
810 }
811
812 pub fn having_group(
814 self,
815 field: impl AsRef<str>,
816 op: CompareOp,
817 value: InputValue,
818 ) -> Result<Self, QueryError> {
819 let Self { inner, .. } = self;
820 let inner = inner.having_group(field, op, value.into())?;
821
822 Ok(Self::from_inner(inner))
823 }
824
825 pub(in crate::db) fn having_group_with_schema(
826 self,
827 field: impl AsRef<str>,
828 schema: &SchemaInfo,
829 op: CompareOp,
830 value: InputValue,
831 ) -> Result<Self, QueryError> {
832 let Self { inner, .. } = self;
833 let inner = inner.having_group_with_schema(field, schema, op, value.into())?;
834
835 Ok(Self::from_inner(inner))
836 }
837
838 pub fn having_aggregate(
840 self,
841 aggregate_index: usize,
842 op: CompareOp,
843 value: InputValue,
844 ) -> Result<Self, QueryError> {
845 let Self { inner, .. } = self;
846 let inner = inner.having_aggregate(aggregate_index, op, value.into())?;
847
848 Ok(Self::from_inner(inner))
849 }
850
851 #[cfg(test)]
855 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
856 let Self { inner, .. } = self;
857 let inner = inner.having_expr(expr)?;
858
859 Ok(Self::from_inner(inner))
860 }
861
862 pub(in crate::db) fn by_id(self, id: E::Key) -> Self {
864 let Self { inner, .. } = self;
865
866 Self::from_inner(inner.by_id(id.to_key_value()))
867 }
868
869 pub(in crate::db) fn by_ids<I>(self, ids: I) -> Self
871 where
872 I: IntoIterator<Item = E::Key>,
873 {
874 let Self { inner, .. } = self;
875
876 Self::from_inner(inner.by_ids(ids.into_iter().map(|id| id.to_key_value())))
877 }
878
879 #[must_use]
881 pub fn delete(mut self) -> Self {
882 self.inner = self.inner.delete();
883 self
884 }
885
886 #[must_use]
893 pub fn limit(mut self, limit: u32) -> Self {
894 self.inner = self.inner.limit(limit);
895 self
896 }
897
898 #[must_use]
904 pub fn offset(mut self, offset: u32) -> Self {
905 self.inner = self.inner.offset(offset);
906 self
907 }
908
909 #[must_use]
914 pub fn require_index(mut self) -> Self {
915 self.inner = self.inner.require_index();
916 self
917 }
918
919 #[must_use]
924 pub fn require_index_named(mut self, index_name: impl Into<String>) -> Self {
925 self.inner = self.inner.require_index_named(index_name);
926 self
927 }
928
929 #[must_use]
933 pub fn require_access_path(mut self, path: RequiredAccessPath) -> Self {
934 self.inner = self.inner.require_access_path(path);
935 self
936 }
937
938 #[must_use]
943 pub fn require_no_residual_filter(mut self) -> Self {
944 self.inner = self.inner.require_no_residual_filter();
945 self
946 }
947
948 pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
950 let mut plan = self.build_plan_for_visibility(None)?;
951 self.inner
952 .finalize_access_choice_for_visibility(&mut plan, None);
953
954 Ok(plan.explain())
955 }
956
957 pub fn plan_hash_hex(&self) -> Result<String, QueryError> {
962 let plan = self.inner.build_plan()?;
963
964 Ok(plan.fingerprint().to_string())
965 }
966
967 pub fn planned(&self) -> Result<PlannedQuery<E>, QueryError> {
969 self.map_plan_for_visibility(None, Self::planned_query_from_plan)
970 }
971
972 pub fn plan(&self) -> Result<CompiledQuery<E>, QueryError> {
976 self.map_plan_for_visibility(None, Self::compiled_query_from_plan)
977 }
978
979 #[cfg(test)]
980 pub(in crate::db) fn plan_with_visible_indexes(
981 &self,
982 visible_indexes: &VisibleIndexes<'_>,
983 ) -> Result<CompiledQuery<E>, QueryError> {
984 self.map_plan_for_visibility(Some(visible_indexes), Self::compiled_query_from_plan)
985 }
986}
987
988impl<E> Query<E>
989where
990 E: EntityKind + SingletonEntity,
991 E::Key: Default,
992{
993 pub(in crate::db) fn only(self) -> Self {
995 let Self { inner, .. } = self;
996
997 Self::from_inner(inner.only(E::Key::default().to_key_value()))
998 }
999}