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