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::{QueryError, QueryModel},
17 plan::{
18 AccessPlannedQuery, LoadSpec, OrderSpec, PreparedScalarPlanningState, QueryMode,
19 VisibleIndexes, expr::Expr,
20 },
21 },
22 },
23 traits::{EntityKind, KeyValueCodec, SingletonEntity},
24 value::{InputValue, Value},
25};
26use core::marker::PhantomData;
27
28#[derive(Clone, Debug)]
37pub(in crate::db) struct StructuralQuery {
38 intent: QueryModel<'static, Value>,
39}
40
41impl StructuralQuery {
42 #[must_use]
43 pub(in crate::db) const fn new(
44 model: &'static crate::model::entity::EntityModel,
45 consistency: MissingRowPolicy,
46 ) -> Self {
47 Self {
48 intent: QueryModel::new(model, consistency),
49 }
50 }
51
52 const fn from_intent(intent: QueryModel<'static, Value>) -> Self {
56 Self { intent }
57 }
58
59 fn map_intent(
62 self,
63 map: impl FnOnce(QueryModel<'static, Value>) -> QueryModel<'static, Value>,
64 ) -> Self {
65 Self::from_intent(map(self.intent))
66 }
67
68 fn try_map_intent(
71 self,
72 map: impl FnOnce(QueryModel<'static, Value>) -> Result<QueryModel<'static, Value>, QueryError>,
73 ) -> Result<Self, QueryError> {
74 map(self.intent).map(Self::from_intent)
75 }
76
77 #[must_use]
78 const fn mode(&self) -> QueryMode {
79 self.intent.mode()
80 }
81
82 #[must_use]
83 fn has_explicit_order(&self) -> bool {
84 self.intent.has_explicit_order()
85 }
86
87 #[must_use]
88 pub(in crate::db) const fn has_grouping(&self) -> bool {
89 self.intent.has_grouping()
90 }
91
92 #[must_use]
93 const fn load_spec(&self) -> Option<LoadSpec> {
94 match self.intent.mode() {
95 QueryMode::Load(spec) => Some(spec),
96 QueryMode::Delete(_) => None,
97 }
98 }
99
100 #[must_use]
101 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
102 self.intent = self.intent.filter_predicate(predicate);
103 self
104 }
105
106 #[must_use]
107 pub(in crate::db) fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
108 self.intent = self.intent.filter(expr.into());
109 self
110 }
111
112 #[must_use]
113 pub(in crate::db) fn filter_expr_with_normalized_predicate(
114 mut self,
115 expr: Expr,
116 predicate: Predicate,
117 ) -> Self {
118 self.intent = self
119 .intent
120 .filter_expr_with_normalized_predicate(expr, predicate);
121 self
122 }
123 pub(in crate::db) fn order_term(mut self, term: FluentOrderTerm) -> Self {
124 self.intent = self.intent.order_term(term);
125 self
126 }
127
128 #[must_use]
132 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
133 self.intent = self.intent.filter_expr(expr);
134 self
135 }
136
137 #[must_use]
138 pub(in crate::db) fn order_spec(mut self, order: OrderSpec) -> Self {
139 self.intent = self.intent.order_spec(order);
140 self
141 }
142
143 #[must_use]
144 pub(in crate::db) fn distinct(mut self) -> Self {
145 self.intent = self.intent.distinct();
146 self
147 }
148
149 #[cfg(feature = "sql")]
150 #[must_use]
151 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
152 where
153 I: IntoIterator<Item = S>,
154 S: Into<String>,
155 {
156 self.intent = self.intent.select_fields(fields);
157 self
158 }
159
160 #[cfg(feature = "sql")]
161 #[must_use]
162 pub(in crate::db) fn projection_selection(mut self, selection: ProjectionSelection) -> Self {
163 self.intent = self.intent.projection_selection(selection);
164 self
165 }
166
167 pub(in crate::db) fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
168 self.try_map_intent(|intent| intent.push_group_field(field.as_ref()))
169 }
170
171 #[must_use]
172 pub(in crate::db) fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
173 self.intent = self.intent.push_group_aggregate(aggregate);
174 self
175 }
176
177 #[must_use]
178 fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
179 self.intent = self.intent.grouped_limits(max_groups, max_group_bytes);
180 self
181 }
182
183 pub(in crate::db) fn having_group(
184 self,
185 field: impl AsRef<str>,
186 op: CompareOp,
187 value: Value,
188 ) -> Result<Self, QueryError> {
189 let field = field.as_ref().to_owned();
190 self.try_map_intent(|intent| intent.push_having_group_clause(&field, op, value))
191 }
192
193 pub(in crate::db) fn having_aggregate(
194 self,
195 aggregate_index: usize,
196 op: CompareOp,
197 value: Value,
198 ) -> Result<Self, QueryError> {
199 self.try_map_intent(|intent| {
200 intent.push_having_aggregate_clause(aggregate_index, op, value)
201 })
202 }
203
204 #[cfg(test)]
205 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
206 self.try_map_intent(|intent| intent.push_having_expr(expr))
207 }
208
209 pub(in crate::db) fn having_expr_preserving_shape(
210 self,
211 expr: Expr,
212 ) -> Result<Self, QueryError> {
213 self.try_map_intent(|intent| intent.push_having_expr_preserving_shape(expr))
214 }
215
216 #[must_use]
217 fn by_id(self, id: Value) -> Self {
218 self.map_intent(|intent| intent.by_id(id))
219 }
220
221 #[must_use]
222 fn by_ids<I>(self, ids: I) -> Self
223 where
224 I: IntoIterator<Item = Value>,
225 {
226 self.map_intent(|intent| intent.by_ids(ids))
227 }
228
229 #[must_use]
230 fn only(self, id: Value) -> Self {
231 self.map_intent(|intent| intent.only(id))
232 }
233
234 #[must_use]
235 pub(in crate::db) fn delete(mut self) -> Self {
236 self.intent = self.intent.delete();
237 self
238 }
239
240 #[must_use]
241 pub(in crate::db) fn limit(mut self, limit: u32) -> Self {
242 self.intent = self.intent.limit(limit);
243 self
244 }
245
246 #[must_use]
247 pub(in crate::db) fn offset(mut self, offset: u32) -> Self {
248 self.intent = self.intent.offset(offset);
249 self
250 }
251
252 pub(in crate::db) fn build_plan(&self) -> Result<AccessPlannedQuery, QueryError> {
253 self.intent.build_plan_model()
254 }
255
256 pub(in crate::db) fn build_plan_with_visible_indexes(
257 &self,
258 visible_indexes: &VisibleIndexes<'_>,
259 ) -> Result<AccessPlannedQuery, QueryError> {
260 self.intent.build_plan_model_with_indexes(visible_indexes)
261 }
262
263 pub(in crate::db) fn prepare_scalar_planning_state(
264 &self,
265 ) -> Result<PreparedScalarPlanningState<'_>, QueryError> {
266 self.intent.prepare_scalar_planning_state()
267 }
268
269 pub(in crate::db) fn build_plan_with_visible_indexes_from_scalar_planning_state(
270 &self,
271 visible_indexes: &VisibleIndexes<'_>,
272 planning_state: PreparedScalarPlanningState<'_>,
273 ) -> Result<AccessPlannedQuery, QueryError> {
274 self.intent
275 .build_plan_model_with_indexes_from_scalar_planning_state(
276 visible_indexes,
277 planning_state,
278 )
279 }
280
281 #[must_use]
282 #[cfg(test)]
283 pub(in crate::db) fn structural_cache_key(
284 &self,
285 ) -> crate::db::query::intent::StructuralQueryCacheKey {
286 crate::db::query::intent::StructuralQueryCacheKey::from_query_model(&self.intent)
287 }
288
289 #[must_use]
290 pub(in crate::db) fn structural_cache_key_with_normalized_predicate_fingerprint(
291 &self,
292 predicate_fingerprint: Option<[u8; 32]>,
293 ) -> crate::db::query::intent::StructuralQueryCacheKey {
294 self.intent
295 .structural_cache_key_with_normalized_predicate_fingerprint(predicate_fingerprint)
296 }
297
298 fn build_plan_for_visibility(
301 &self,
302 visible_indexes: Option<&VisibleIndexes<'_>>,
303 ) -> Result<AccessPlannedQuery, QueryError> {
304 match visible_indexes {
305 Some(visible_indexes) => self.build_plan_with_visible_indexes(visible_indexes),
306 None => self.build_plan(),
307 }
308 }
309
310 #[must_use]
311 pub(in crate::db) const fn model(&self) -> &'static crate::model::entity::EntityModel {
312 self.intent.model()
313 }
314}
315
316#[derive(Clone, Debug)]
325struct QueryPlanHandle {
326 plan: Box<AccessPlannedQuery>,
327}
328
329impl QueryPlanHandle {
330 #[must_use]
331 fn from_plan(plan: AccessPlannedQuery) -> Self {
332 Self {
333 plan: Box::new(plan),
334 }
335 }
336
337 #[must_use]
338 const fn logical_plan(&self) -> &AccessPlannedQuery {
339 &self.plan
340 }
341
342 #[must_use]
343 fn into_inner(self) -> AccessPlannedQuery {
344 *self.plan
345 }
346}
347
348#[derive(Debug)]
356pub struct PlannedQuery<E: EntityKind> {
357 plan: QueryPlanHandle,
358 _marker: PhantomData<E>,
359}
360
361impl<E: EntityKind> PlannedQuery<E> {
362 #[must_use]
363 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
364 Self {
365 plan: QueryPlanHandle::from_plan(plan),
366 _marker: PhantomData,
367 }
368 }
369
370 #[must_use]
371 pub fn explain(&self) -> ExplainPlan {
372 self.plan.logical_plan().explain()
373 }
374
375 #[must_use]
377 pub fn plan_hash_hex(&self) -> String {
378 self.plan.logical_plan().fingerprint().to_string()
379 }
380}
381
382#[derive(Clone, Debug)]
392pub struct CompiledQuery<E: EntityKind> {
393 plan: QueryPlanHandle,
394 _marker: PhantomData<E>,
395}
396
397impl<E: EntityKind> CompiledQuery<E> {
398 #[must_use]
399 pub(in crate::db) fn from_plan(plan: AccessPlannedQuery) -> Self {
400 Self {
401 plan: QueryPlanHandle::from_plan(plan),
402 _marker: PhantomData,
403 }
404 }
405
406 #[must_use]
407 pub fn explain(&self) -> ExplainPlan {
408 self.plan.logical_plan().explain()
409 }
410
411 #[must_use]
413 pub fn plan_hash_hex(&self) -> String {
414 self.plan.logical_plan().fingerprint().to_string()
415 }
416
417 #[must_use]
418 #[cfg(test)]
419 pub(in crate::db) fn projection_spec(&self) -> crate::db::query::plan::expr::ProjectionSpec {
420 self.plan.logical_plan().projection_spec(E::MODEL)
421 }
422
423 pub(in crate::db) fn into_plan(self) -> AccessPlannedQuery {
425 self.plan.into_inner()
426 }
427
428 #[must_use]
429 #[cfg(test)]
430 pub(in crate::db) fn into_inner(self) -> AccessPlannedQuery {
431 self.plan.into_inner()
432 }
433}
434
435#[derive(Debug)]
447pub struct Query<E: EntityKind> {
448 inner: StructuralQuery,
449 _marker: PhantomData<E>,
450}
451
452impl<E: EntityKind> Query<E> {
453 pub(in crate::db) const fn from_inner(inner: StructuralQuery) -> Self {
455 Self {
456 inner,
457 _marker: PhantomData,
458 }
459 }
460
461 #[must_use]
465 pub const fn new(consistency: MissingRowPolicy) -> Self {
466 Self::from_inner(StructuralQuery::new(E::MODEL, consistency))
467 }
468
469 #[must_use]
471 pub const fn mode(&self) -> QueryMode {
472 self.inner.mode()
473 }
474
475 pub(in crate::db) fn explain_with_visible_indexes(
476 &self,
477 visible_indexes: &VisibleIndexes<'_>,
478 ) -> Result<ExplainPlan, QueryError> {
479 let plan = self.build_plan_for_visibility(Some(visible_indexes))?;
480
481 Ok(plan.explain())
482 }
483
484 pub(in crate::db) fn plan_hash_hex_with_visible_indexes(
485 &self,
486 visible_indexes: &VisibleIndexes<'_>,
487 ) -> Result<String, QueryError> {
488 let plan = self.build_plan_for_visibility(Some(visible_indexes))?;
489
490 Ok(plan.fingerprint().to_string())
491 }
492
493 fn build_plan_for_visibility(
496 &self,
497 visible_indexes: Option<&VisibleIndexes<'_>>,
498 ) -> Result<AccessPlannedQuery, QueryError> {
499 self.inner.build_plan_for_visibility(visible_indexes)
500 }
501
502 fn map_plan_for_visibility<T>(
506 &self,
507 visible_indexes: Option<&VisibleIndexes<'_>>,
508 map: impl FnOnce(AccessPlannedQuery) -> T,
509 ) -> Result<T, QueryError> {
510 let plan = self.build_plan_for_visibility(visible_indexes)?;
511
512 Ok(map(plan))
513 }
514
515 pub(in crate::db) fn planned_query_from_plan(plan: AccessPlannedQuery) -> PlannedQuery<E> {
517 PlannedQuery::from_plan(plan)
518 }
519
520 pub(in crate::db) fn compiled_query_from_plan(plan: AccessPlannedQuery) -> CompiledQuery<E> {
522 CompiledQuery::from_plan(plan)
523 }
524
525 #[must_use]
526 pub(crate) fn has_explicit_order(&self) -> bool {
527 self.inner.has_explicit_order()
528 }
529
530 #[must_use]
531 pub(in crate::db) const fn structural(&self) -> &StructuralQuery {
532 &self.inner
533 }
534
535 #[must_use]
536 pub const fn has_grouping(&self) -> bool {
537 self.inner.has_grouping()
538 }
539
540 #[must_use]
541 pub(crate) const fn load_spec(&self) -> Option<LoadSpec> {
542 self.inner.load_spec()
543 }
544
545 #[must_use]
547 pub fn filter(mut self, expr: impl Into<FilterExpr>) -> Self {
548 self.inner = self.inner.filter(expr);
549 self
550 }
551
552 #[cfg(test)]
556 #[must_use]
557 pub(in crate::db) fn filter_expr(mut self, expr: Expr) -> Self {
558 self.inner = self.inner.filter_expr(expr);
559 self
560 }
561
562 #[must_use]
563 pub(in crate::db) fn filter_predicate(mut self, predicate: Predicate) -> Self {
564 self.inner = self.inner.filter_predicate(predicate);
565 self
566 }
567
568 #[must_use]
570 pub fn order_term(mut self, term: FluentOrderTerm) -> Self {
571 self.inner = self.inner.order_term(term);
572 self
573 }
574
575 #[must_use]
577 pub fn order_terms<I>(mut self, terms: I) -> Self
578 where
579 I: IntoIterator<Item = FluentOrderTerm>,
580 {
581 for term in terms {
582 self.inner = self.inner.order_term(term);
583 }
584
585 self
586 }
587
588 #[must_use]
590 pub fn distinct(mut self) -> Self {
591 self.inner = self.inner.distinct();
592 self
593 }
594
595 #[cfg(all(test, feature = "sql"))]
598 #[must_use]
599 pub(in crate::db) fn select_fields<I, S>(mut self, fields: I) -> Self
600 where
601 I: IntoIterator<Item = S>,
602 S: Into<String>,
603 {
604 self.inner = self.inner.select_fields(fields);
605 self
606 }
607
608 pub fn group_by(self, field: impl AsRef<str>) -> Result<Self, QueryError> {
610 let Self { inner, .. } = self;
611 let inner = inner.group_by(field)?;
612
613 Ok(Self::from_inner(inner))
614 }
615
616 #[must_use]
618 pub fn aggregate(mut self, aggregate: AggregateExpr) -> Self {
619 self.inner = self.inner.aggregate(aggregate);
620 self
621 }
622
623 #[must_use]
625 pub fn grouped_limits(mut self, max_groups: u64, max_group_bytes: u64) -> Self {
626 self.inner = self.inner.grouped_limits(max_groups, max_group_bytes);
627 self
628 }
629
630 pub fn having_group(
632 self,
633 field: impl AsRef<str>,
634 op: CompareOp,
635 value: InputValue,
636 ) -> Result<Self, QueryError> {
637 let Self { inner, .. } = self;
638 let inner = inner.having_group(field, op, value.into())?;
639
640 Ok(Self::from_inner(inner))
641 }
642
643 pub fn having_aggregate(
645 self,
646 aggregate_index: usize,
647 op: CompareOp,
648 value: InputValue,
649 ) -> Result<Self, QueryError> {
650 let Self { inner, .. } = self;
651 let inner = inner.having_aggregate(aggregate_index, op, value.into())?;
652
653 Ok(Self::from_inner(inner))
654 }
655
656 #[cfg(test)]
660 pub(in crate::db) fn having_expr(self, expr: Expr) -> Result<Self, QueryError> {
661 let Self { inner, .. } = self;
662 let inner = inner.having_expr(expr)?;
663
664 Ok(Self::from_inner(inner))
665 }
666
667 pub(crate) fn by_id(self, id: E::Key) -> Self {
669 let Self { inner, .. } = self;
670
671 Self::from_inner(inner.by_id(id.to_key_value()))
672 }
673
674 pub(crate) fn by_ids<I>(self, ids: I) -> Self
676 where
677 I: IntoIterator<Item = E::Key>,
678 {
679 let Self { inner, .. } = self;
680
681 Self::from_inner(inner.by_ids(ids.into_iter().map(|id| id.to_key_value())))
682 }
683
684 #[must_use]
686 pub fn delete(mut self) -> Self {
687 self.inner = self.inner.delete();
688 self
689 }
690
691 #[must_use]
698 pub fn limit(mut self, limit: u32) -> Self {
699 self.inner = self.inner.limit(limit);
700 self
701 }
702
703 #[must_use]
709 pub fn offset(mut self, offset: u32) -> Self {
710 self.inner = self.inner.offset(offset);
711 self
712 }
713
714 pub fn explain(&self) -> Result<ExplainPlan, QueryError> {
716 let plan = self.planned()?;
717
718 Ok(plan.explain())
719 }
720
721 pub fn plan_hash_hex(&self) -> Result<String, QueryError> {
726 let plan = self.inner.build_plan()?;
727
728 Ok(plan.fingerprint().to_string())
729 }
730
731 pub fn planned(&self) -> Result<PlannedQuery<E>, QueryError> {
733 self.map_plan_for_visibility(None, Self::planned_query_from_plan)
734 }
735
736 pub fn plan(&self) -> Result<CompiledQuery<E>, QueryError> {
740 self.map_plan_for_visibility(None, Self::compiled_query_from_plan)
741 }
742
743 #[cfg(test)]
744 pub(in crate::db) fn plan_with_visible_indexes(
745 &self,
746 visible_indexes: &VisibleIndexes<'_>,
747 ) -> Result<CompiledQuery<E>, QueryError> {
748 self.map_plan_for_visibility(Some(visible_indexes), Self::compiled_query_from_plan)
749 }
750}
751
752impl<E> Query<E>
753where
754 E: EntityKind + SingletonEntity,
755 E::Key: Default,
756{
757 pub(crate) fn only(self) -> Self {
759 let Self { inner, .. } = self;
760
761 Self::from_inner(inner.only(E::Key::default().to_key_value()))
762 }
763}