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