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 #[cfg(feature = "sql")]
131 pub(in crate::db) fn direct_count_cardinality_prefix_candidate(&self) -> bool {
132 if self.intent.validate_policy_shape().is_err() {
133 return false;
134 }
135
136 let access_inputs = self.intent.planning_access_inputs();
137 let logical_inputs = self.intent.planning_logical_inputs();
138 if access_inputs.order().is_some()
139 || access_inputs.has_key_access_override()
140 || logical_inputs.distinct()
141 || logical_inputs.has_group()
142 || logical_inputs.has_having_expr()
143 || (logical_inputs.has_filter_expr() && !logical_inputs.filter_predicate_covers_expr())
144 {
145 return false;
146 }
147
148 let QueryMode::Load(load_spec) = self.intent.mode() else {
149 return false;
150 };
151 load_spec.limit().is_none()
152 && load_spec.offset() == 0
153 && access_inputs.predicate().is_some()
154 }
155
156 #[must_use]
157 const fn load_spec(&self) -> Option<LoadSpec> {
158 match self.intent.mode() {
159 QueryMode::Load(spec) => Some(spec),
160 QueryMode::Delete(_) => None,
161 }
162 }
163
164 #[must_use]
166 #[cfg(test)]
167 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
168 self.intent = self.intent.filter_predicate(predicate);
169 self
170 }
171
172 #[must_use]
174 #[cfg(any(test, feature = "sql"))]
175 pub(in crate::db) fn filter_normalized_predicate(mut self, predicate: Predicate) -> Self {
176 self.intent = self.intent.filter_normalized_predicate(predicate);
177 self
178 }
179
180 #[must_use]
181 pub(in crate::db) fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
182 self.intent = self.intent.filter(expr.into());
183 self
184 }
185
186 #[must_use]
187 #[cfg(feature = "sql")]
188 pub(in crate::db) fn filter_expr_with_normalized_predicate(
189 mut self,
190 expr: Expr,
191 predicate: Predicate,
192 ) -> Self {
193 self.intent = self
194 .intent
195 .filter_expr_with_normalized_predicate(expr, predicate);
196 self
197 }
198 pub(in crate::db) fn order_term(mut self, term: FluentOrderTerm) -> Self {
199 self.intent = self.intent.order_term(term);
200 self
201 }
202
203 #[must_use]
207 #[cfg(feature = "sql")]
208 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
209 self.intent = self.intent.filter_expr(expr);
210 self
211 }
212
213 #[must_use]
214 #[cfg(any(test, feature = "sql"))]
215 pub(in crate::db) fn order_spec(mut self, order: OrderSpec) -> Self {
216 self.intent = self.intent.order_spec(order);
217 self
218 }
219
220 #[must_use]
221 pub(in crate::db) fn distinct(mut self) -> Self {
222 self.intent = self.intent.distinct();
223 self
224 }
225
226 #[cfg(feature = "sql")]
227 #[must_use]
228 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
229 where
230 I: IntoIterator<Item = S>,
231 S: Into<String>,
232 {
233 self.intent = self.intent.select_fields(fields);
234 self
235 }
236
237 #[cfg(feature = "sql")]
238 #[must_use]
239 pub(in crate::db) fn projection_selection(mut self, selection: ProjectionSelection) -> Self {
240 self.intent = self.intent.projection_selection(selection);
241 self
242 }
243
244 pub(in crate::db) fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
245 self.try_map_intent(|intent| intent.push_group_field(field.as_ref()))
246 }
247
248 pub(in crate::db) fn group_by_with_schema(
249 self,
250 field: impl AsRef<str>,
251 schema: &SchemaInfo,
252 ) -> Result<Self, QueryError> {
253 self.try_map_intent(|intent| intent.push_group_field_with_schema(field.as_ref(), schema))
254 }
255
256 #[must_use]
257 pub(in crate::db) fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
258 self.intent = self.intent.push_group_aggregate(aggregate);
259 self
260 }
261
262 #[must_use]
263 fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
264 self.intent = self.intent.grouped_limits(max_groups, max_group_bytes);
265 self
266 }
267
268 pub(in crate::db) fn having_group(
269 self,
270 field: impl AsRef<str>,
271 op: CompareOp,
272 value: Value,
273 ) -> Result<Self, QueryError> {
274 let field = field.as_ref().to_owned();
275 self.try_map_intent(|intent| intent.push_having_group_clause(&field, op, value))
276 }
277
278 pub(in crate::db) fn having_group_with_schema(
279 self,
280 field: impl AsRef<str>,
281 schema: &SchemaInfo,
282 op: CompareOp,
283 value: Value,
284 ) -> Result<Self, QueryError> {
285 let field = field.as_ref().to_owned();
286 self.try_map_intent(|intent| {
287 intent.push_having_group_clause_with_schema(&field, schema, op, value)
288 })
289 }
290
291 pub(in crate::db) fn having_aggregate(
292 self,
293 aggregate_index: usize,
294 op: CompareOp,
295 value: Value,
296 ) -> Result<Self, QueryError> {
297 self.try_map_intent(|intent| {
298 intent.push_having_aggregate_clause(aggregate_index, op, value)
299 })
300 }
301
302 #[cfg(test)]
303 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
304 self.try_map_intent(|intent| intent.push_having_expr(expr))
305 }
306
307 #[cfg(feature = "sql")]
308 pub(in crate::db) fn having_expr_preserving_shape(
309 self,
310 expr: Expr,
311 ) -> Result<Self, QueryError> {
312 self.try_map_intent(|intent| intent.push_having_expr_preserving_shape(expr))
313 }
314
315 #[must_use]
316 fn by_id(self, id: Value) -> Self {
317 self.map_intent(|intent| intent.by_id(id))
318 }
319
320 #[must_use]
321 fn by_ids<I>(self, ids: I) -> Self
322 where
323 I: IntoIterator<Item = Value>,
324 {
325 self.map_intent(|intent| intent.by_ids(ids))
326 }
327
328 #[must_use]
329 fn only(self, id: Value) -> Self {
330 self.map_intent(|intent| intent.only(id))
331 }
332
333 #[must_use]
334 pub(in crate::db) fn delete(mut self) -> Self {
335 self.intent = self.intent.delete();
336 self
337 }
338
339 #[must_use]
340 pub(in crate::db) fn limit(mut self, limit: u32) -> Self {
341 self.intent = self.intent.limit(limit);
342 self
343 }
344
345 #[must_use]
346 pub(in crate::db) fn offset(mut self, offset: u32) -> Self {
347 self.intent = self.intent.offset(offset);
348 self
349 }
350
351 pub(in crate::db) fn build_plan(&self) -> Result<AccessPlannedQuery, QueryError> {
352 let mut plan = self.intent.build_plan_model()?;
353 self.validate_access_requirements_for_visibility(&mut plan, None)?;
354
355 Ok(plan)
356 }
357
358 pub(in crate::db) fn build_plan_with_visible_indexes(
359 &self,
360 visible_indexes: &VisibleIndexes<'_>,
361 ) -> Result<AccessPlannedQuery, QueryError> {
362 let mut plan = self.intent.build_plan_model_with_indexes(visible_indexes)?;
363 self.validate_access_requirements_for_visibility(&mut plan, Some(visible_indexes))?;
364
365 Ok(plan)
366 }
367
368 pub(in crate::db) fn prepare_scalar_planning_state_with_schema_info(
369 &self,
370 schema_info: SchemaInfo,
371 ) -> Result<PreparedScalarPlanningState<'_>, QueryError> {
372 self.intent
373 .prepare_scalar_planning_state_with_schema_info(schema_info)
374 }
375
376 pub(in crate::db) fn build_plan_with_visible_indexes_from_scalar_planning_state(
377 &self,
378 visible_indexes: &VisibleIndexes<'_>,
379 planning_state: PreparedScalarPlanningState<'_>,
380 ) -> Result<AccessPlannedQuery, QueryError> {
381 let mut plan = self
382 .intent
383 .build_plan_model_with_indexes_from_scalar_planning_state(
384 visible_indexes,
385 planning_state,
386 )?;
387 self.validate_access_requirements_for_visibility(&mut plan, Some(visible_indexes))?;
388
389 Ok(plan)
390 }
391
392 #[cfg(feature = "sql")]
393 pub(in crate::db) fn try_build_count_cardinality_prefix_access_with_schema_info(
394 &self,
395 visible_indexes: &VisibleIndexes<'_>,
396 schema_info: &SchemaInfo,
397 ) -> Result<Option<crate::db::query::plan::CountCardinalityPrefixAccess<'_>>, QueryError> {
398 crate::db::query::plan::try_build_count_cardinality_prefix_access_from_query_model(
399 &self.intent,
400 visible_indexes,
401 schema_info,
402 )
403 }
404
405 pub(in crate::db) fn try_build_trivial_scalar_load_plan_with_schema_info(
406 &self,
407 schema_info: SchemaInfo,
408 ) -> Result<Option<AccessPlannedQuery>, QueryError> {
409 let mut plan = self
410 .intent
411 .try_build_trivial_scalar_load_plan_with_schema_info(schema_info)?;
412 if let Some(plan) = &mut plan {
413 self.validate_access_requirements_for_visibility(plan, None)?;
414 }
415
416 Ok(plan)
417 }
418
419 #[must_use]
420 pub(in crate::db) fn trivial_scalar_load_fast_path_eligible_with_schema(
421 &self,
422 schema_info: &SchemaInfo,
423 ) -> bool {
424 self.intent
425 .trivial_scalar_load_fast_path_eligible_with_schema(schema_info)
426 }
427
428 #[must_use]
429 #[cfg(test)]
430 pub(in crate::db) fn structural_cache_key(
431 &self,
432 ) -> crate::db::query::intent::StructuralQueryCacheKey {
433 crate::db::query::intent::StructuralQueryCacheKey::from_query_model(&self.intent)
434 }
435
436 #[must_use]
437 pub(in crate::db) fn structural_cache_key_with_normalized_predicate_fingerprint(
438 &self,
439 predicate_fingerprint: Option<[u8; 32]>,
440 ) -> crate::db::query::intent::StructuralQueryCacheKey {
441 if predicate_fingerprint.is_none() {
442 return self
443 .structural_cache_key
444 .get_or_init(|| {
445 self.intent
446 .structural_cache_key_with_normalized_predicate_fingerprint(None)
447 })
448 .clone();
449 }
450
451 self.intent
452 .structural_cache_key_with_normalized_predicate_fingerprint(predicate_fingerprint)
453 }
454
455 fn build_plan_for_visibility(
458 &self,
459 visible_indexes: Option<&VisibleIndexes<'_>>,
460 ) -> Result<AccessPlannedQuery, QueryError> {
461 match visible_indexes {
462 Some(visible_indexes) => self.build_plan_with_visible_indexes(visible_indexes),
463 None => self.build_plan(),
464 }
465 }
466
467 fn finalize_access_choice_for_visibility(
468 &self,
469 plan: &mut AccessPlannedQuery,
470 visible_indexes: Option<&VisibleIndexes<'_>>,
471 ) {
472 match visible_indexes {
473 Some(visible_indexes) => {
474 if let Some(schema_info) = visible_indexes.accepted_schema_info() {
475 plan.finalize_access_choice_for_model_with_accepted_indexes_and_schema(
476 self.intent.model(),
477 visible_indexes.accepted_field_path_indexes(),
478 visible_indexes.accepted_expression_indexes(),
479 schema_info,
480 );
481 } else {
482 plan.finalize_access_choice_for_model_only_with_indexes(
483 self.intent.model(),
484 visible_indexes.generated_model_only_indexes(),
485 );
486 }
487 }
488 None => {
489 plan.finalize_access_choice_for_model_only_with_indexes(
490 self.intent.model(),
491 self.intent.model().indexes(),
492 );
493 }
494 }
495 }
496
497 fn validate_access_requirements_for_visibility(
498 &self,
499 plan: &mut AccessPlannedQuery,
500 visible_indexes: Option<&VisibleIndexes<'_>>,
501 ) -> Result<(), QueryError> {
502 if self.access_requirements.is_empty() {
503 return Ok(());
504 }
505
506 self.finalize_access_choice_for_visibility(plan, visible_indexes);
507 self.access_requirements.validate(plan)
508 }
509
510 const fn require_index(mut self) -> Self {
511 self.access_requirements.require_index();
512 self
513 }
514
515 fn require_index_named(mut self, index_name: impl Into<String>) -> Self {
516 self.access_requirements.require_index_named(index_name);
517 self
518 }
519
520 const fn require_access_path(mut self, path: RequiredAccessPath) -> Self {
521 self.access_requirements.require_access_path(path);
522 self
523 }
524
525 const fn require_no_residual_filter(mut self) -> Self {
526 self.access_requirements.require_no_residual_filter();
527 self
528 }
529
530 #[must_use]
531 pub(in crate::db) const fn model(&self) -> &'static crate::model::entity::EntityModel {
532 self.intent.model()
533 }
534}
535
536#[derive(Clone, Debug)]
545struct QueryPlanHandle {
546 plan: Box<AccessPlannedQuery>,
547}
548
549impl QueryPlanHandle {
550 #[must_use]
551 fn from_plan(plan: AccessPlannedQuery) -> Self {
552 Self {
553 plan: Box::new(plan),
554 }
555 }
556
557 #[must_use]
558 const fn logical_plan(&self) -> &AccessPlannedQuery {
559 &self.plan
560 }
561
562 #[must_use]
563 #[cfg(test)]
564 fn into_inner(self) -> AccessPlannedQuery {
565 *self.plan
566 }
567}
568
569#[derive(Debug)]
577pub struct PlannedQuery<E: EntityKind> {
578 plan: QueryPlanHandle,
579 _marker: PhantomData<E>,
580}
581
582impl<E: EntityKind> PlannedQuery<E> {
583 #[must_use]
584 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
585 Self {
586 plan: QueryPlanHandle::from_plan(plan),
587 _marker: PhantomData,
588 }
589 }
590
591 #[must_use]
592 pub fn explain(&self) -> ExplainPlan {
593 self.plan.logical_plan().explain()
594 }
595
596 #[must_use]
598 pub fn plan_hash_hex(&self) -> String {
599 self.plan.logical_plan().fingerprint().to_string()
600 }
601}
602
603#[derive(Clone, Debug)]
613pub struct CompiledQuery<E: EntityKind> {
614 plan: QueryPlanHandle,
615 _marker: PhantomData<E>,
616}
617
618impl<E: EntityKind> CompiledQuery<E> {
619 #[must_use]
620 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
621 Self {
622 plan: QueryPlanHandle::from_plan(plan),
623 _marker: PhantomData,
624 }
625 }
626
627 #[must_use]
628 pub fn explain(&self) -> ExplainPlan {
629 self.plan.logical_plan().explain()
630 }
631
632 #[must_use]
634 pub fn plan_hash_hex(&self) -> String {
635 self.plan.logical_plan().fingerprint().to_string()
636 }
637
638 #[must_use]
639 #[cfg(test)]
640 pub(in crate::db) fn projection_spec(&self) -> crate::db::query::plan::expr::ProjectionSpec {
641 self.plan.logical_plan().projection_spec(E::MODEL)
642 }
643
644 #[cfg(test)]
646 pub(in crate::db) fn into_plan(self) -> AccessPlannedQuery {
647 self.plan.into_inner()
648 }
649
650 #[must_use]
651 #[cfg(test)]
652 pub(in crate::db) fn into_inner(self) -> AccessPlannedQuery {
653 self.plan.into_inner()
654 }
655}
656
657#[derive(Debug)]
669pub struct Query<E: EntityKind> {
670 inner: StructuralQuery,
671 _marker: PhantomData<E>,
672}
673
674impl<E: EntityKind> Query<E> {
675 pub(in crate::db) const fn from_inner(inner: StructuralQuery) -> Self {
677 Self {
678 inner,
679 _marker: PhantomData,
680 }
681 }
682
683 #[must_use]
687 pub const fn new(consistency: MissingRowPolicy) -> Self {
688 Self::from_inner(StructuralQuery::new(E::MODEL, consistency))
689 }
690
691 #[must_use]
693 pub const fn mode(&self) -> QueryMode {
694 self.inner.mode()
695 }
696
697 #[cfg(test)]
698 pub(in crate::db) fn explain_with_visible_indexes(
699 &self,
700 visible_indexes: &VisibleIndexes<'_>,
701 ) -> Result<ExplainPlan, QueryError> {
702 let mut plan = self.build_plan_for_visibility(Some(visible_indexes))?;
703 self.inner
704 .finalize_access_choice_for_visibility(&mut plan, Some(visible_indexes));
705
706 Ok(plan.explain())
707 }
708
709 #[cfg(test)]
710 pub(in crate::db) fn plan_hash_hex_with_visible_indexes(
711 &self,
712 visible_indexes: &VisibleIndexes<'_>,
713 ) -> Result<String, QueryError> {
714 let plan = self.build_plan_for_visibility(Some(visible_indexes))?;
715
716 Ok(plan.fingerprint().to_string())
717 }
718
719 fn build_plan_for_visibility(
722 &self,
723 visible_indexes: Option<&VisibleIndexes<'_>>,
724 ) -> Result<AccessPlannedQuery, QueryError> {
725 self.inner.build_plan_for_visibility(visible_indexes)
726 }
727
728 fn map_plan_for_visibility<T>(
732 &self,
733 visible_indexes: Option<&VisibleIndexes<'_>>,
734 map: impl FnOnce(AccessPlannedQuery) -> T,
735 ) -> Result<T, QueryError> {
736 let plan = self.build_plan_for_visibility(visible_indexes)?;
737
738 Ok(map(plan))
739 }
740
741 pub(in crate::db) fn planned_query_from_plan(plan: AccessPlannedQuery) -> PlannedQuery<E> {
743 PlannedQuery::from_plan(plan)
744 }
745
746 pub(in crate::db) fn compiled_query_from_plan(plan: AccessPlannedQuery) -> CompiledQuery<E> {
748 CompiledQuery::from_plan(plan)
749 }
750
751 #[must_use]
752 pub(in crate::db::query) fn has_explicit_order(&self) -> bool {
753 self.inner.has_explicit_order()
754 }
755
756 #[must_use]
757 pub(in crate::db) const fn structural(&self) -> &StructuralQuery {
758 &self.inner
759 }
760
761 #[must_use]
762 pub const fn has_grouping(&self) -> bool {
763 self.inner.has_grouping()
764 }
765
766 #[must_use]
767 pub(in crate::db::query) const fn load_spec(&self) -> Option<LoadSpec> {
768 self.inner.load_spec()
769 }
770
771 #[must_use]
773 pub fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
774 self.inner = self.inner.filter(expr);
775 self
776 }
777
778 #[cfg(test)]
782 #[must_use]
783 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
784 self.inner = self.inner.filter_expr(expr);
785 self
786 }
787
788 #[cfg(test)]
792 #[must_use]
793 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
794 self.inner = self.inner.filter_predicate(predicate);
795 self
796 }
797
798 #[must_use]
800 pub fn order_term(mut self, term: FluentOrderTerm) -> Self {
801 self.inner = self.inner.order_term(term);
802 self
803 }
804
805 #[must_use]
807 pub fn order_terms<I>(mut self, terms: I) -> Self
808 where
809 I: IntoIterator<Item = FluentOrderTerm>,
810 {
811 for term in terms {
812 self.inner = self.inner.order_term(term);
813 }
814
815 self
816 }
817
818 #[must_use]
820 pub fn distinct(mut self) -> Self {
821 self.inner = self.inner.distinct();
822 self
823 }
824
825 #[cfg(all(test, feature = "sql"))]
828 #[must_use]
829 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
830 where
831 I: IntoIterator<Item = S>,
832 S: Into<String>,
833 {
834 self.inner = self.inner.select_fields(fields);
835 self
836 }
837
838 pub fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
840 let Self { inner, .. } = self;
841 let inner = inner.group_by(field)?;
842
843 Ok(Self::from_inner(inner))
844 }
845
846 pub(in crate::db) fn group_by_with_schema(
847 self,
848 field: impl AsRef<str>,
849 schema: &SchemaInfo,
850 ) -> Result<Self, QueryError> {
851 let Self { inner, .. } = self;
852 let inner = inner.group_by_with_schema(field, schema)?;
853
854 Ok(Self::from_inner(inner))
855 }
856
857 #[must_use]
859 pub fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
860 self.inner = self.inner.aggregate(aggregate);
861 self
862 }
863
864 #[must_use]
866 pub fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
867 self.inner = self.inner.grouped_limits(max_groups, max_group_bytes);
868 self
869 }
870
871 pub fn having_group(
873 self,
874 field: impl AsRef<str>,
875 op: CompareOp,
876 value: InputValue,
877 ) -> Result<Self, QueryError> {
878 let Self { inner, .. } = self;
879 let inner = inner.having_group(field, op, value.into())?;
880
881 Ok(Self::from_inner(inner))
882 }
883
884 pub(in crate::db) fn having_group_with_schema(
885 self,
886 field: impl AsRef<str>,
887 schema: &SchemaInfo,
888 op: CompareOp,
889 value: InputValue,
890 ) -> Result<Self, QueryError> {
891 let Self { inner, .. } = self;
892 let inner = inner.having_group_with_schema(field, schema, op, value.into())?;
893
894 Ok(Self::from_inner(inner))
895 }
896
897 pub fn having_aggregate(
899 self,
900 aggregate_index: usize,
901 op: CompareOp,
902 value: InputValue,
903 ) -> Result<Self, QueryError> {
904 let Self { inner, .. } = self;
905 let inner = inner.having_aggregate(aggregate_index, op, value.into())?;
906
907 Ok(Self::from_inner(inner))
908 }
909
910 #[cfg(test)]
914 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
915 let Self { inner, .. } = self;
916 let inner = inner.having_expr(expr)?;
917
918 Ok(Self::from_inner(inner))
919 }
920
921 pub(in crate::db) fn by_id(self, id: E::Key) -> Self {
923 let Self { inner, .. } = self;
924
925 Self::from_inner(inner.by_id(id.to_key_value()))
926 }
927
928 pub(in crate::db) fn by_ids<I>(self, ids: I) -> Self
930 where
931 I: IntoIterator<Item = E::Key>,
932 {
933 let Self { inner, .. } = self;
934
935 Self::from_inner(inner.by_ids(ids.into_iter().map(|id| id.to_key_value())))
936 }
937
938 #[must_use]
940 pub fn delete(mut self) -> Self {
941 self.inner = self.inner.delete();
942 self
943 }
944
945 #[must_use]
952 pub fn limit(mut self, limit: u32) -> Self {
953 self.inner = self.inner.limit(limit);
954 self
955 }
956
957 #[must_use]
963 pub fn offset(mut self, offset: u32) -> Self {
964 self.inner = self.inner.offset(offset);
965 self
966 }
967
968 #[must_use]
973 pub fn require_index(mut self) -> Self {
974 self.inner = self.inner.require_index();
975 self
976 }
977
978 #[must_use]
983 pub fn require_index_named(mut self, index_name: impl Into<String>) -> Self {
984 self.inner = self.inner.require_index_named(index_name);
985 self
986 }
987
988 #[must_use]
992 pub fn require_access_path(mut self, path: RequiredAccessPath) -> Self {
993 self.inner = self.inner.require_access_path(path);
994 self
995 }
996
997 #[must_use]
1002 pub fn require_no_residual_filter(mut self) -> Self {
1003 self.inner = self.inner.require_no_residual_filter();
1004 self
1005 }
1006
1007 pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
1009 let mut plan = self.build_plan_for_visibility(None)?;
1010 self.inner
1011 .finalize_access_choice_for_visibility(&mut plan, None);
1012
1013 Ok(plan.explain())
1014 }
1015
1016 pub fn plan_hash_hex(&self) -> Result<String, QueryError> {
1021 let plan = self.inner.build_plan()?;
1022
1023 Ok(plan.fingerprint().to_string())
1024 }
1025
1026 pub fn planned(&self) -> Result<PlannedQuery<E>, QueryError> {
1028 self.map_plan_for_visibility(None, Self::planned_query_from_plan)
1029 }
1030
1031 pub fn plan(&self) -> Result<CompiledQuery<E>, QueryError> {
1035 self.map_plan_for_visibility(None, Self::compiled_query_from_plan)
1036 }
1037
1038 #[cfg(test)]
1039 pub(in crate::db) fn plan_with_visible_indexes(
1040 &self,
1041 visible_indexes: &VisibleIndexes<'_>,
1042 ) -> Result<CompiledQuery<E>, QueryError> {
1043 self.map_plan_for_visibility(Some(visible_indexes), Self::compiled_query_from_plan)
1044 }
1045}
1046
1047impl<E> Query<E>
1048where
1049 E: EntityKind + SingletonEntity,
1050 E::Key: Default,
1051{
1052 pub(in crate::db) fn only(self) -> Self {
1054 let Self { inner, .. } = self;
1055
1056 Self::from_inner(inner.only(E::Key::default().to_key_value()))
1057 }
1058}