1use crate::db::predicate::MissingRowPolicy;
7use crate::{
8 db::{
9 access::{AccessPlan, ExecutableAccessPlan, SemanticIndexKeyItemRef},
10 predicate::{IndexCompileTarget, IndexCompileTargetKind, Predicate, PredicateProgram},
11 query::plan::{
12 AccessPlannedQuery, ContinuationPolicy, DistinctExecutionStrategy,
13 EffectiveRuntimeFilterProgram, ExecutionShapeSignature, FieldSlot, GroupPlan,
14 GroupedAggregateExecutionSpec, GroupedDistinctExecutionStrategy, GroupedPlanStrategy,
15 LogicalPlan, PlannerRouteProfile, PredicatePushdownDiagnostics, QueryMode,
16 ResidualFilterContract, ResidualFilterShape, ResolvedOrder, ResolvedOrderField,
17 ResolvedOrderValueSource, ScalarPlan, StaticExecutionPlanningContract,
18 derive_logical_pushdown_eligibility,
19 expr::{
20 CompiledExpr, Expr, ProjectionSpec, compile_scalar_projection_expr_with_schema,
21 compile_scalar_projection_plan_with_schema,
22 },
23 extend_unique_grouped_aggregate_specs_from_expr, grouped_aggregate_execution_specs,
24 grouped_aggregate_specs_from_projection_spec, grouped_cursor_policy_violation,
25 grouped_plan_strategy, lower_data_row_direct_projection_slots_with_schema,
26 lower_direct_projection_slots_with_schema, lower_projection_identity,
27 lower_projection_intent_with_schema, residual_query_predicate_after_access_path_bounds,
28 residual_query_predicate_after_filtered_access_contract,
29 resolved_grouped_distinct_execution_strategy_with_schema_info,
30 },
31 schema::SchemaInfo,
32 },
33 error::InternalError,
34};
35
36impl QueryMode {
37 #[must_use]
39 pub const fn is_load(&self) -> bool {
40 match self {
41 Self::Load(_) => true,
42 Self::Delete(_) => false,
43 }
44 }
45
46 #[must_use]
48 pub const fn is_delete(&self) -> bool {
49 match self {
50 Self::Delete(_) => true,
51 Self::Load(_) => false,
52 }
53 }
54}
55
56impl LogicalPlan {
57 #[must_use]
59 pub(in crate::db) const fn scalar_semantics(&self) -> &ScalarPlan {
60 match self {
61 Self::Scalar(plan) => plan,
62 Self::Grouped(plan) => &plan.scalar,
63 }
64 }
65}
66
67impl AccessPlannedQuery {
68 #[must_use]
70 pub(in crate::db) const fn scalar_plan(&self) -> &ScalarPlan {
71 self.logical.scalar_semantics()
72 }
73
74 #[must_use]
77 pub(in crate::db) fn scalar_consistency(&self) -> MissingRowPolicy {
78 if self.access.has_selected_index_access_path() {
79 MissingRowPolicy::Error
84 } else {
85 self.scalar_plan().consistency
86 }
87 }
88
89 #[must_use]
91 pub(in crate::db) const fn grouped_plan(&self) -> Option<&GroupPlan> {
92 match &self.logical {
93 LogicalPlan::Scalar(_) => None,
94 LogicalPlan::Grouped(plan) => Some(plan),
95 }
96 }
97
98 #[must_use]
100 pub(in crate::db) fn projection_spec_with_schema(&self, schema: &SchemaInfo) -> ProjectionSpec {
101 if let Some(static_contract) = &self.static_execution_planning_contract {
102 return static_contract.projection_spec.clone();
103 }
104
105 lower_projection_intent_with_schema(schema, &self.logical, &self.projection_selection)
106 }
107
108 #[must_use]
110 pub(in crate::db::query) fn projection_spec_for_identity(&self) -> ProjectionSpec {
111 lower_projection_identity(&self.logical, &self.projection_selection)
112 }
113
114 #[must_use]
120 pub(in crate::db) fn execution_preparation_predicate(&self) -> Option<Predicate> {
121 if let Some(static_contract) = self.static_execution_planning_contract.as_ref() {
122 return static_contract.execution_preparation_predicate.clone();
123 }
124
125 derive_execution_preparation_predicate(self)
126 }
127
128 #[must_use]
132 pub(in crate::db) fn effective_execution_predicate(&self) -> Option<Predicate> {
133 if let Some(static_contract) = self.static_execution_planning_contract.as_ref() {
134 return static_contract
135 .residual_filter_contract
136 .residual_filter_predicate()
137 .cloned();
138 }
139
140 derive_residual_filter_predicate(self)
141 }
142
143 #[must_use]
146 pub(in crate::db) fn has_residual_filter_predicate(&self) -> bool {
147 self.effective_execution_predicate().is_some()
148 }
149
150 #[must_use]
153 pub(in crate::db) fn residual_filter_expr(&self) -> Option<&Expr> {
154 if let Some(static_contract) = self.static_execution_planning_contract.as_ref() {
155 return static_contract
156 .residual_filter_contract
157 .residual_filter_expr();
158 }
159
160 if !derive_has_residual_filter(self) {
161 return None;
162 }
163
164 self.scalar_plan().filter_expr.as_ref()
165 }
166
167 #[must_use]
170 pub(in crate::db) fn has_residual_filter_expr(&self) -> bool {
171 self.residual_filter_expr().is_some()
172 }
173
174 #[must_use]
176 pub(in crate::db) fn residual_filter_shape(&self) -> ResidualFilterShape {
177 if let Some(static_contract) = self.static_execution_planning_contract.as_ref() {
178 return static_contract.residual_filter_contract.shape();
179 }
180
181 ResidualFilterShape::from_presence(
182 self.residual_filter_expr().is_some(),
183 self.effective_execution_predicate().is_some(),
184 )
185 }
186
187 #[must_use]
190 #[cfg(feature = "sql")]
191 pub(in crate::db) fn predicate_pushdown_label(&self) -> String {
192 self.predicate_pushdown_diagnostics().label()
193 }
194
195 #[must_use]
197 #[cfg(feature = "sql")]
198 pub(in crate::db) fn predicate_pushdown_diagnostics(&self) -> PredicatePushdownDiagnostics {
199 if let Some(static_contract) = self.static_execution_planning_contract.as_ref() {
200 return static_contract.predicate_pushdown_diagnostics;
201 }
202
203 derive_predicate_pushdown_diagnostics(self, self.residual_filter_shape())
204 }
205
206 #[must_use]
208 #[cfg(feature = "sql")]
209 pub(in crate::db) fn predicate_pushdown_outcome_label(&self) -> &'static str {
210 self.predicate_pushdown_diagnostics().outcome_label()
211 }
212
213 #[must_use]
215 #[cfg(feature = "sql")]
216 pub(in crate::db) fn predicate_pushdown_reason_label(&self) -> &'static str {
217 self.predicate_pushdown_diagnostics().reason_label()
218 }
219
220 #[must_use]
222 pub(in crate::db) fn execution_preparation_compiled_predicate(
223 &self,
224 ) -> Option<&PredicateProgram> {
225 self.static_execution_planning_contract()?
226 .execution_preparation_compiled_predicate
227 .as_ref()
228 }
229
230 #[must_use]
232 pub(in crate::db) fn effective_runtime_compiled_predicate(&self) -> Option<&PredicateProgram> {
233 match self
234 .static_execution_planning_contract()?
235 .residual_filter_contract
236 .effective_runtime_filter_program()
237 {
238 Some(program) => program.predicate_program(),
239 None => None,
240 }
241 }
242
243 #[must_use]
245 pub(in crate::db) fn effective_runtime_filter_program(
246 &self,
247 ) -> Option<&EffectiveRuntimeFilterProgram> {
248 self.static_execution_planning_contract()?
249 .residual_filter_contract
250 .effective_runtime_filter_program()
251 }
252
253 #[must_use]
255 pub(in crate::db) fn distinct_execution_strategy(&self) -> DistinctExecutionStrategy {
256 if !self.scalar_plan().distinct {
257 return DistinctExecutionStrategy::None;
258 }
259
260 match distinct_runtime_dedup_strategy(&self.access) {
264 Some(strategy) => strategy,
265 None => DistinctExecutionStrategy::None,
266 }
267 }
268
269 pub(in crate::db) fn finalize_planner_route_profile_for_model_with_schema(
271 &mut self,
272 schema_info: &SchemaInfo,
273 ) {
274 self.set_planner_route_profile(project_planner_route_profile_for_schema(schema_info, self));
275 }
276
277 pub(in crate::db) fn finalize_static_execution_planning_contract_with_schema(
279 &mut self,
280 schema_info: &SchemaInfo,
281 ) -> Result<(), InternalError> {
282 self.bind_group_field_slots_to_schema(schema_info)?;
283 self.static_execution_planning_contract = Some(
284 project_static_execution_planning_contract_with_schema(schema_info, self)?,
285 );
286
287 Ok(())
288 }
289
290 fn bind_group_field_slots_to_schema(
293 &mut self,
294 schema_info: &SchemaInfo,
295 ) -> Result<(), InternalError> {
296 let LogicalPlan::Grouped(grouped) = &mut self.logical else {
297 return Ok(());
298 };
299
300 let accepted_slots = grouped
301 .group
302 .group_fields
303 .iter()
304 .map(|field_slot| FieldSlot::resolve_with_schema(schema_info, field_slot.field()))
305 .collect::<Option<Vec<_>>>()
306 .ok_or_else(InternalError::planner_executor_invariant)?;
307 grouped.group.group_fields = accepted_slots;
308
309 Ok(())
310 }
311
312 #[must_use]
314 pub(in crate::db) fn execution_shape_signature(
315 &self,
316 entity_path: &str,
317 ) -> ExecutionShapeSignature {
318 ExecutionShapeSignature::new(self.continuation_signature(entity_path))
319 }
320
321 #[must_use]
324 pub(in crate::db) fn predicate_fully_satisfied_by_access_contract(&self) -> bool {
325 if let Some(static_contract) = self.static_execution_planning_contract.as_ref() {
326 return self.scalar_plan().predicate.is_some()
327 && !static_contract
328 .residual_filter_contract
329 .has_residual_filter();
330 }
331
332 derive_predicate_fully_satisfied_by_access_contract(self)
333 }
334
335 #[must_use]
337 pub(in crate::db) fn scalar_projection_plan(&self) -> Option<&[CompiledExpr]> {
338 self.static_execution_planning_contract()?
339 .scalar_projection_plan
340 .as_deref()
341 }
342
343 #[must_use]
345 pub(in crate::db) const fn has_static_execution_planning_contract(&self) -> bool {
346 self.static_execution_planning_contract.is_some()
347 }
348
349 pub(in crate::db) fn primary_key_names(&self) -> Result<Vec<&str>, InternalError> {
351 Ok(self
352 .require_static_execution_planning_contract()?
353 .primary_key_names
354 .iter()
355 .map(String::as_str)
356 .collect())
357 }
358
359 pub(in crate::db) fn projection_referenced_slots(&self) -> Result<&[usize], InternalError> {
361 Ok(self
362 .require_static_execution_planning_contract()?
363 .projection_referenced_slots
364 .as_slice())
365 }
366
367 #[cfg(any(test, feature = "diagnostics"))]
369 pub(in crate::db) fn projected_slot_mask(&self) -> Result<&[bool], InternalError> {
370 Ok(self
371 .require_static_execution_planning_contract()?
372 .projected_slot_mask
373 .as_slice())
374 }
375
376 pub(in crate::db) fn projection_is_model_identity(&self) -> Result<bool, InternalError> {
378 Ok(self
379 .require_static_execution_planning_contract()?
380 .projection_is_model_identity)
381 }
382
383 #[must_use]
385 pub(in crate::db) fn order_referenced_slots(&self) -> Option<&[usize]> {
386 self.static_execution_planning_contract()?
387 .order_referenced_slots
388 .as_deref()
389 }
390
391 #[must_use]
393 pub(in crate::db) fn resolved_order(&self) -> Option<&ResolvedOrder> {
394 self.static_execution_planning_contract()?
395 .resolved_order
396 .as_ref()
397 }
398
399 #[must_use]
401 pub(in crate::db) fn slot_map(&self) -> Option<&[usize]> {
402 self.static_execution_planning_contract()?
403 .slot_map
404 .as_deref()
405 }
406
407 #[must_use]
409 pub(in crate::db) fn grouped_aggregate_execution_specs(
410 &self,
411 ) -> Option<&[GroupedAggregateExecutionSpec]> {
412 self.static_execution_planning_contract()?
413 .grouped_aggregate_execution_specs
414 .as_deref()
415 }
416
417 #[must_use]
419 pub(in crate::db) fn grouped_distinct_execution_strategy(
420 &self,
421 ) -> Option<&GroupedDistinctExecutionStrategy> {
422 self.static_execution_planning_contract()?
423 .grouped_distinct_execution_strategy
424 .as_ref()
425 }
426
427 pub(in crate::db) fn frozen_projection_spec(&self) -> Result<&ProjectionSpec, InternalError> {
429 Ok(&self
430 .require_static_execution_planning_contract()?
431 .projection_spec)
432 }
433
434 #[must_use]
436 pub(in crate::db) fn frozen_direct_projection_slots(&self) -> Option<&[usize]> {
437 self.static_execution_planning_contract()?
438 .projection_direct_slots
439 .as_deref()
440 }
441
442 #[must_use]
444 pub(in crate::db) fn frozen_data_row_direct_projection_slots(&self) -> Option<&[usize]> {
445 self.static_execution_planning_contract()?
446 .projection_data_row_direct_slots
447 .as_deref()
448 }
449
450 #[must_use]
452 pub(in crate::db) fn index_compile_targets(&self) -> Option<&[IndexCompileTarget]> {
453 self.static_execution_planning_contract()?
454 .index_compile_targets
455 .as_deref()
456 }
457
458 const fn static_execution_planning_contract(&self) -> Option<&StaticExecutionPlanningContract> {
459 self.static_execution_planning_contract.as_ref()
460 }
461
462 fn require_static_execution_planning_contract(
463 &self,
464 ) -> Result<&StaticExecutionPlanningContract, InternalError> {
465 self.static_execution_planning_contract
466 .as_ref()
467 .ok_or_else(InternalError::query_executor_invariant)
468 }
469}
470
471fn distinct_runtime_dedup_strategy<K>(access: &AccessPlan<K>) -> Option<DistinctExecutionStrategy> {
472 match access {
473 AccessPlan::Union(_) | AccessPlan::Intersection(_) => {
474 Some(DistinctExecutionStrategy::PreOrdered)
475 }
476 AccessPlan::Path(path) if path.as_ref().is_index_multi_lookup() => {
477 Some(DistinctExecutionStrategy::HashMaterialize)
478 }
479 AccessPlan::Path(_) => None,
480 }
481}
482
483fn derive_continuation_policy_validated(plan: &AccessPlannedQuery) -> ContinuationPolicy {
484 let is_grouped_safe = plan
485 .grouped_plan()
486 .is_none_or(|grouped| grouped_cursor_policy_violation(grouped, true).is_none());
487
488 ContinuationPolicy::new(
489 true, true, is_grouped_safe,
492 )
493}
494
495#[must_use]
497pub(in crate::db) fn project_planner_route_profile_for_schema(
498 schema_info: &SchemaInfo,
499 plan: &AccessPlannedQuery,
500) -> PlannerRouteProfile {
501 let primary_key_names = primary_key_names_from_schema(schema_info);
502 let secondary_order_contract = plan.scalar_plan().order.as_ref().and_then(|order| {
503 order.deterministic_secondary_order_contract_fields(primary_key_names.as_slice())
504 });
505
506 PlannerRouteProfile::new(
507 derive_continuation_policy_validated(plan),
508 derive_logical_pushdown_eligibility(plan, secondary_order_contract.as_ref()),
509 secondary_order_contract,
510 )
511}
512
513fn project_static_execution_planning_contract_with_schema(
514 schema_info: &SchemaInfo,
515 plan: &AccessPlannedQuery,
516) -> Result<StaticExecutionPlanningContract, InternalError> {
517 let projection_spec =
518 lower_projection_intent_with_schema(schema_info, &plan.logical, &plan.projection_selection);
519 let execution_preparation_predicate = plan.execution_preparation_predicate();
520 let residual_filter_predicate = derive_residual_filter_predicate_from_preparation(
521 plan,
522 execution_preparation_predicate.as_ref(),
523 );
524 let residual_filter_expr = derive_residual_filter_expr(plan);
525 let effective_runtime_filter_program = compile_effective_runtime_filter_program(
526 schema_info,
527 residual_filter_expr.as_ref(),
528 residual_filter_predicate.as_ref(),
529 )?;
530 let residual_filter_contract = ResidualFilterContract::new(
531 residual_filter_expr,
532 residual_filter_predicate,
533 effective_runtime_filter_program,
534 );
535 let residual_filter_shape = residual_filter_contract.shape();
536 let execution_preparation_compiled_predicate =
537 should_compile_execution_preparation_predicate(residual_filter_shape)
538 .then(|| {
539 compile_optional_predicate(schema_info, execution_preparation_predicate.as_ref())
540 })
541 .flatten();
542 let predicate_pushdown_diagnostics =
543 derive_predicate_pushdown_diagnostics(plan, residual_filter_shape);
544 let scalar_projection_plan = if plan.grouped_plan().is_none() {
545 Some(
546 compile_scalar_projection_plan_with_schema(schema_info, &projection_spec)
547 .ok_or_else(InternalError::query_executor_invariant)?
548 .iter()
549 .map(CompiledExpr::compile)
550 .collect(),
551 )
552 } else {
553 None
554 };
555 let (grouped_aggregate_execution_specs, grouped_distinct_execution_strategy) =
556 resolve_grouped_static_planning_semantics(schema_info, plan, &projection_spec)?;
557 let projection_direct_slots = lower_direct_projection_slots_with_schema(
558 schema_info,
559 &plan.logical,
560 &plan.projection_selection,
561 );
562 let projection_data_row_direct_slots = lower_data_row_direct_projection_slots_with_schema(
563 schema_info,
564 &plan.logical,
565 &plan.projection_selection,
566 );
567 let projection_referenced_slots = projection_spec.referenced_slots_for_schema(schema_info)?;
568 let projected_slot_mask =
569 projected_slot_mask_for_spec(schema_info, projection_direct_slots.as_deref());
570 let projection_is_model_identity = projection_spec.is_schema_identity_for(schema_info);
571 let resolved_order = resolved_order_for_plan(schema_info, plan)?;
572 let order_referenced_slots = order_referenced_slots_for_resolved_order(resolved_order.as_ref());
573 let slot_map = slot_map_for_schema_plan(schema_info, plan);
574 let index_compile_targets = index_compile_targets_for_schema_plan(schema_info, plan);
575
576 Ok(StaticExecutionPlanningContract {
577 primary_key_names: schema_info.primary_key_names().to_vec(),
578 projection_spec,
579 execution_preparation_predicate,
580 execution_preparation_compiled_predicate,
581 residual_filter_contract,
582 predicate_pushdown_diagnostics,
583 scalar_projection_plan,
584 grouped_aggregate_execution_specs,
585 grouped_distinct_execution_strategy,
586 projection_direct_slots,
587 projection_data_row_direct_slots,
588 projection_referenced_slots,
589 projected_slot_mask,
590 projection_is_model_identity,
591 resolved_order,
592 order_referenced_slots,
593 slot_map,
594 index_compile_targets,
595 })
596}
597
598fn primary_key_names_from_schema(schema_info: &SchemaInfo) -> Vec<&str> {
599 schema_info
600 .primary_key_names()
601 .iter()
602 .map(String::as_str)
603 .collect()
604}
605
606fn compile_effective_runtime_filter_program(
610 schema_info: &SchemaInfo,
611 residual_filter_expr: Option<&Expr>,
612 residual_filter_predicate: Option<&Predicate>,
613) -> Result<Option<EffectiveRuntimeFilterProgram>, InternalError> {
614 if let Some(predicate) = residual_filter_predicate {
619 return Ok(Some(EffectiveRuntimeFilterProgram::predicate(
620 PredicateProgram::compile_with_schema_info(schema_info, predicate),
621 )));
622 }
623
624 if let Some(filter_expr) = residual_filter_expr {
625 let compiled = compile_scalar_projection_expr_with_schema(schema_info, filter_expr)
626 .ok_or_else(InternalError::query_invalid_logical_plan)?;
627
628 return Ok(Some(EffectiveRuntimeFilterProgram::expression(
629 CompiledExpr::compile(&compiled),
630 )));
631 }
632
633 Ok(None)
634}
635
636fn derive_execution_preparation_predicate(plan: &AccessPlannedQuery) -> Option<Predicate> {
640 let query_predicate = plan.scalar_plan().predicate.as_ref()?;
641
642 match plan.access.selected_index_contract() {
643 Some(index) => {
644 residual_query_predicate_after_filtered_access_contract(index, query_predicate)
645 }
646 None => Some(query_predicate.clone()),
647 }
648}
649
650fn derive_residual_filter_predicate(plan: &AccessPlannedQuery) -> Option<Predicate> {
654 let filtered_residual = derive_execution_preparation_predicate(plan);
655
656 derive_residual_filter_predicate_from_preparation(plan, filtered_residual.as_ref())
657}
658
659fn derive_residual_filter_predicate_from_preparation(
660 plan: &AccessPlannedQuery,
661 execution_preparation_predicate: Option<&Predicate>,
662) -> Option<Predicate> {
663 let execution_preparation_predicate = execution_preparation_predicate?;
664
665 residual_query_predicate_after_access_path_bounds(
666 plan.access.as_path(),
667 execution_preparation_predicate,
668 )
669}
670
671fn derive_residual_filter_expr(plan: &AccessPlannedQuery) -> Option<Expr> {
675 let filter_expr = plan.scalar_plan().filter_expr.as_ref()?;
676 if derive_semantic_filter_fully_satisfied_by_access_contract(plan) {
677 return None;
678 }
679
680 Some(filter_expr.clone())
681}
682
683fn derive_has_residual_filter(plan: &AccessPlannedQuery) -> bool {
687 match (
688 plan.scalar_plan().filter_expr.as_ref(),
689 plan.scalar_plan().predicate.as_ref(),
690 ) {
691 (None, None) => false,
692 (Some(_), None) => true,
693 (Some(_) | None, Some(_)) => !plan.predicate_fully_satisfied_by_access_contract(),
694 }
695}
696
697fn derive_predicate_pushdown_diagnostics(
701 plan: &AccessPlannedQuery,
702 residual_filter_shape: ResidualFilterShape,
703) -> PredicatePushdownDiagnostics {
704 PredicatePushdownDiagnostics::from_plan(
705 plan.scalar_plan().filter_expr.is_some(),
706 plan.scalar_plan().predicate_covers_filter_expr,
707 plan.scalar_plan().predicate.as_ref(),
708 &plan.access,
709 residual_filter_shape,
710 )
711}
712
713fn derive_predicate_fully_satisfied_by_access_contract(plan: &AccessPlannedQuery) -> bool {
716 plan.scalar_plan().predicate.is_some()
717 && derive_residual_filter_predicate(plan).is_none()
718 && derive_residual_filter_expr(plan).is_none()
719}
720
721const fn derive_semantic_filter_fully_satisfied_by_access_contract(
725 plan: &AccessPlannedQuery,
726) -> bool {
727 plan.scalar_plan().filter_expr.is_some()
728 && plan.scalar_plan().predicate.is_some()
729 && plan.scalar_plan().predicate_covers_filter_expr
730}
731
732fn compile_optional_predicate(
735 schema_info: &SchemaInfo,
736 predicate: Option<&Predicate>,
737) -> Option<PredicateProgram> {
738 predicate.map(|predicate| PredicateProgram::compile_with_schema_info(schema_info, predicate))
739}
740
741const fn should_compile_execution_preparation_predicate(
746 residual_filter_shape: ResidualFilterShape,
747) -> bool {
748 !residual_filter_shape.is_absent()
749}
750
751fn resolve_grouped_static_planning_semantics(
755 schema_info: &SchemaInfo,
756 plan: &AccessPlannedQuery,
757 projection_spec: &ProjectionSpec,
758) -> Result<
759 (
760 Option<Vec<GroupedAggregateExecutionSpec>>,
761 Option<GroupedDistinctExecutionStrategy>,
762 ),
763 InternalError,
764> {
765 let Some(grouped) = plan.grouped_plan() else {
766 return Ok((None, None));
767 };
768
769 let mut aggregate_specs = grouped_aggregate_specs_from_projection_spec(
770 projection_spec,
771 grouped.group.group_fields.as_slice(),
772 grouped.group.aggregates.as_slice(),
773 )?;
774 extend_grouped_having_aggregate_specs(&mut aggregate_specs, grouped)?;
775
776 let grouped_aggregate_execution_specs = Some(grouped_aggregate_execution_specs(
777 schema_info,
778 aggregate_specs.as_slice(),
779 )?);
780 let grouped_distinct_execution_strategy = Some(
781 resolved_grouped_distinct_execution_strategy_with_schema_info(
782 schema_info,
783 grouped.group.group_fields.as_slice(),
784 grouped.group.aggregates.as_slice(),
785 grouped.having_expr.as_ref(),
786 )?,
787 );
788
789 Ok((
790 grouped_aggregate_execution_specs,
791 grouped_distinct_execution_strategy,
792 ))
793}
794
795fn extend_grouped_having_aggregate_specs(
796 aggregate_specs: &mut Vec<GroupedAggregateExecutionSpec>,
797 grouped: &GroupPlan,
798) -> Result<(), InternalError> {
799 if let Some(having_expr) = grouped.having_expr.as_ref() {
800 extend_unique_grouped_aggregate_specs_from_expr(aggregate_specs, having_expr)?;
801 }
802
803 Ok(())
804}
805
806fn projected_slot_mask_for_spec(
807 schema_info: &SchemaInfo,
808 direct_projection_slots: Option<&[usize]>,
809) -> Vec<bool> {
810 let schema_slot_len = direct_projection_slots
811 .and_then(|slots| slots.iter().copied().max())
812 .map_or(0, |slot| slot.saturating_add(1));
813 let mut projected_slots = vec![
814 false;
815 schema_info
816 .field_names_in_slot_order()
817 .len()
818 .max(schema_slot_len)
819 ];
820
821 let Some(direct_projection_slots) = direct_projection_slots else {
822 return projected_slots;
823 };
824
825 for slot in direct_projection_slots.iter().copied() {
826 if let Some(projected) = projected_slots.get_mut(slot) {
827 *projected = true;
828 }
829 }
830
831 projected_slots
832}
833
834fn resolved_order_for_plan(
835 schema_info: &SchemaInfo,
836 plan: &AccessPlannedQuery,
837) -> Result<Option<ResolvedOrder>, InternalError> {
838 if grouped_plan_strategy(plan).is_some_and(GroupedPlanStrategy::is_top_k_group) {
839 return Ok(None);
840 }
841
842 let Some(order) = plan.scalar_plan().order.as_ref() else {
843 return Ok(None);
844 };
845
846 let mut fields = Vec::with_capacity(order.fields.len());
847 for term in &order.fields {
848 fields.push(ResolvedOrderField::new(
849 resolved_order_value_source_for_term(schema_info, term)?,
850 term.direction(),
851 ));
852 }
853
854 Ok(Some(ResolvedOrder::new(fields)))
855}
856
857fn resolved_order_value_source_for_term(
858 schema_info: &SchemaInfo,
859 term: &crate::db::query::plan::OrderTerm,
860) -> Result<ResolvedOrderValueSource, InternalError> {
861 if term.direct_field().is_none() {
862 let rendered = term.rendered_label();
863 validate_resolved_order_expr_fields(schema_info, term.expr(), rendered.as_str())?;
864 let compiled = compile_scalar_projection_expr_with_schema(schema_info, term.expr())
865 .ok_or_else(|| order_expression_scalar_seam_error(rendered.as_str()))?;
866
867 return Ok(ResolvedOrderValueSource::expression(CompiledExpr::compile(
868 &compiled,
869 )));
870 }
871
872 let Some(field) = term.direct_field() else {
873 return Err(InternalError::query_invalid_logical_plan());
874 };
875 let slot = resolve_required_schema_slot(
876 schema_info,
877 field,
878 InternalError::query_invalid_logical_plan,
879 )?;
880
881 Ok(ResolvedOrderValueSource::direct_field(slot))
882}
883
884fn validate_resolved_order_expr_fields(
885 schema_info: &SchemaInfo,
886 expr: &Expr,
887 rendered: &str,
888) -> Result<(), InternalError> {
889 expr.try_for_each_tree_expr(&mut |node| match node {
890 Expr::Field(field_id) => resolve_required_schema_slot(
891 schema_info,
892 field_id.as_str(),
893 InternalError::query_invalid_logical_plan,
894 )
895 .map(|_| ()),
896 Expr::Aggregate(_) => Err(order_expression_scalar_seam_error(rendered)),
897 #[cfg(test)]
898 Expr::Alias { .. } => Err(order_expression_scalar_seam_error(rendered)),
899 Expr::Unary { .. } => Err(order_expression_scalar_seam_error(rendered)),
900 _ => Ok(()),
901 })
902}
903
904fn resolve_required_schema_slot<F>(
908 schema_info: &SchemaInfo,
909 field: &str,
910 invalid_plan_error: F,
911) -> Result<usize, InternalError>
912where
913 F: FnOnce() -> InternalError,
914{
915 schema_info
916 .field_slot_index(field)
917 .ok_or_else(invalid_plan_error)
918}
919
920fn order_expression_scalar_seam_error(_rendered: &str) -> InternalError {
923 InternalError::query_invalid_logical_plan()
924}
925
926fn order_referenced_slots_for_resolved_order(
931 resolved_order: Option<&ResolvedOrder>,
932) -> Option<Vec<usize>> {
933 Some(resolved_order?.referenced_slots())
934}
935
936fn slot_map_for_schema_plan(
937 schema_info: &SchemaInfo,
938 plan: &AccessPlannedQuery,
939) -> Option<Vec<usize>> {
940 let executable = plan.access.executable_contract();
941
942 resolved_index_slots_for_access_path(schema_info, &executable)
943}
944
945fn resolved_index_slots_for_access_path(
946 schema_info: &SchemaInfo,
947 access: &ExecutableAccessPlan<'_, crate::value::Value>,
948) -> Option<Vec<usize>> {
949 let path = access.as_path()?;
950 let path_facts = path.shape_facts();
951 let key_items = path_facts.index_key_items_for_slot_map()?;
952 let mut slots = Vec::with_capacity(key_items.key_arity());
953 for key_item in key_items.key_items() {
954 let slot = schema_info.field_slot_index(key_item.as_ref().field())?;
955 slots.push(slot);
956 }
957
958 Some(slots)
959}
960
961fn index_compile_targets_for_schema_plan(
962 schema_info: &SchemaInfo,
963 plan: &AccessPlannedQuery,
964) -> Option<Vec<IndexCompileTarget>> {
965 let executable = plan.access.executable_contract();
966 let path = executable.as_path()?;
967 let key_items = path.shape_facts().index_key_items_for_slot_map()?;
968 let mut targets = Vec::new();
969
970 for (component_index, key_item) in key_items.key_items().iter().enumerate() {
971 let key_item = key_item.as_ref();
972 let field_slot = schema_info.field_slot_index(key_item.field())?;
973 targets.push(IndexCompileTarget {
974 component_index,
975 field_slot,
976 kind: match key_item {
977 SemanticIndexKeyItemRef::Field(_) => IndexCompileTargetKind::Field,
978 SemanticIndexKeyItemRef::AcceptedExpression(expression) => {
979 IndexCompileTargetKind::Expression(expression.op())
980 }
981 },
982 });
983 }
984
985 Some(targets)
986}