From 0babc9dd1334cf5df7ac8bdc8b610cebc95437b8 Mon Sep 17 00:00:00 2001 From: zzylol <50204836+zzylol@users.noreply.github.com> Date: Sat, 3 Oct 2026 21:57:28 +0000 Subject: [PATCH] refactor(types): arrange asap-types modules by #511 section (#572 B1) Replace the pre_asap/post_asap split with modules named for what they hold: - ir::operator: node, non_asap, asap, operator_properties, agg_intent, maintained_population - ir::scalar: scalar expressions, expr_ir items, scalar_type_rules, column_resolution - ir::schema: Schema/Field/DataType, aggregate_schema, error, and the summary state types (state_type, formerly post_asap::sketch) - ir::properties: guarantee, timing, summary_coverage, and the execution timing/data-state types split out of execution_data_state - workload: workload, parsed_workload, resources - physical: the rest of execution_data_state, and summary_window post_asap::query_time had no callers and is deleted. Public type names are unchanged; every import across the workspace is rewritten, with no compatibility re-exports from the old paths. Co-Authored-By: Claude Opus 5.5 --- .../src/accuracy/composition.rs | 4 +- .../src/accuracy/estimators/cms.rs | 6 +- .../src/accuracy/estimators/count_sketch.rs | 6 +- .../src/accuracy/estimators/hll.rs | 4 +- .../src/accuracy/estimators/kll.rs | 4 +- .../src/accuracy/estimators/mod.rs | 4 +- .../src/accuracy/evidence.rs | 8 +- crates/asap-aware-mapping/src/accuracy/mod.rs | 9 +- .../src/accuracy/reconciliation.rs | 12 +- .../asap-aware-mapping/src/analytical_cost.rs | 26 +- crates/asap-aware-mapping/src/cost_model.rs | 52 +- .../src/empirical_comparison.rs | 8 +- .../asap-aware-mapping/src/empirical_cost.rs | 10 +- .../src/empirical_resources.rs | 6 +- .../src/exact_composition.rs | 36 +- crates/asap-aware-mapping/src/explanation.rs | 24 +- .../asap-aware-mapping/src/function_rules.rs | 5 +- crates/asap-aware-mapping/src/grouping.rs | 33 +- crates/asap-aware-mapping/src/lib.rs | 2 +- .../src/logical_candidates.rs | 13 +- .../src/maintained_population.rs | 15 +- crates/asap-aware-mapping/src/pass/mod.rs | 8 +- .../src/physical_candidates.rs | 10 +- .../src/physical_handoff_cost.rs | 2 +- .../src/physical_operator_statistics.rs | 2 +- .../src/physical_plan_cost_model.rs | 9 +- .../asap-aware-mapping/src/plan_selection.rs | 7 +- .../src/query_physical_lowering.rs | 130 ++-- crates/asap-aware-mapping/src/recurrence.rs | 33 +- crates/asap-aware-mapping/src/replacement.rs | 101 +-- crates/asap-aware-mapping/src/rewrite.rs | 22 +- crates/asap-aware-mapping/src/rollup.rs | 14 +- crates/asap-aware-mapping/src/storage_io.rs | 2 +- crates/asap-aware-mapping/src/test_support.rs | 12 +- crates/asap-aware-mapping/src/topk_reuse.rs | 4 +- .../tests/logical_candidates.rs | 14 +- .../tests/physical_handoff_cost.rs | 6 +- crates/asap-aware-mapping/tests/storage_io.rs | 4 +- crates/asap-physical-operators/README.md | 2 +- .../asap-physical-operators/src/capability.rs | 18 +- .../asap-physical-operators/src/evaluation.rs | 2 +- .../src/expressions/arithmetic.rs | 10 +- .../src/expressions/binary.rs | 7 +- .../src/expressions/mod.rs | 5 +- .../src/expressions/planner.rs | 18 +- .../src/operators/aggregate/mod.rs | 4 +- .../src/operators/aggregate/temporal.rs | 10 +- .../src/operators/joins/mod.rs | 6 +- .../src/operators/mod.rs | 20 +- .../src/operators/series_labels.rs | 8 +- .../src/operators/series_window.rs | 2 +- .../src/operators/summary/mod.rs | 20 +- .../src/operators/vector_window.rs | 2 +- .../src/physical_planner/candidates.rs | 10 +- .../src/physical_planner/mod.rs | 35 +- .../src/physical_planner/precompute.rs | 43 +- .../src/physical_planner/promql_fallback.rs | 41 +- .../src/physical_planner/promql_rows.rs | 22 +- .../src/physical_planner/promql_values.rs | 6 +- .../src/physical_planner/row_values.rs | 4 +- .../src/runtime/batch_execution.rs | 5 +- .../src/sources/mod.rs | 6 +- .../src/summary_kernels/count_min_sketch.rs | 4 +- .../src/summary_kernels/datasketches_kll.rs | 2 +- .../src/summary_kernels/dd_sketch.rs | 4 +- .../src/summary_kernels/exact.rs | 2 +- .../src/summary_kernels/factory.rs | 18 +- .../src/summary_kernels/hll_sketch.rs | 2 +- .../src/summary_kernels/traits.rs | 4 +- .../src/summary_kernels/univmon.rs | 3 +- .../src/summary_kernels/weighted_frequency.rs | 4 +- crates/asap-physical-operators/src/values.rs | 9 +- .../tests/blocking_resources.rs | 13 +- .../tests/current_series_heap.rs | 7 +- .../tests/deployment.rs | 10 +- .../tests/deployment_computation.rs | 16 +- .../tests/physical_dag.rs | 76 +-- .../tests/physical_plan_recovery.rs | 7 +- .../tests/physical_semantics.rs | 27 +- .../tests/plan_properties.rs | 22 +- .../tests/planspace_series_identity_heap.rs | 3 +- .../tests/precompute_candidates.rs | 4 +- .../tests/precompute_population.rs | 21 +- .../tests/promql_binary.rs | 26 +- .../tests/promql_fallback.rs | 7 +- .../tests/promql_values.rs | 11 +- .../asap-physical-operators/tests/raw_scan.rs | 23 +- .../tests/summary_projection.rs | 12 +- .../tests/weighted_topk_binding.rs | 21 +- .../devtools/examples/canonical_examples.rs | 2 +- crates/devtools/examples/topk_ir.rs | 2 +- crates/devtools/src/bin/analyze_corpora.rs | 2 +- crates/devtools/src/bin/dag_export.rs | 18 +- crates/devtools/src/bin/show_post_asap_ir.rs | 8 +- crates/devtools/src/bin/show_pre_asap_ir.rs | 2 +- crates/devtools/src/bin/sketch_coverage.rs | 2 +- crates/devtools/src/bin/stage_pipeline.rs | 2 +- crates/devtools/src/bin/variant_coverage.rs | 2 +- crates/devtools/tests/cross_language.rs | 4 +- crates/frontend-common/src/lib.rs | 2 +- crates/frontend-common/src/resolve.rs | 36 +- crates/frontend-common/src/schema_resolver.rs | 8 +- crates/frontend-common/src/unresolved.rs | 15 +- crates/frontend-metricsql/src/lib.rs | 8 +- crates/frontend-metricsql/tests/lowering.rs | 2 +- crates/frontend-promql/src/promql.rs | 9 +- .../frontend-promql/tests/count_planning.rs | 8 +- .../tests/histogram_metadata.rs | 2 +- .../tests/maintained_population_horizon.rs | 2 +- .../awesome_prometheus_alerts.rs | 3 +- .../tests/promql_binding_regressions.rs | 2 +- .../tests/promql_conformance.rs | 11 +- .../frontend-promql/tests/promql_lowering.rs | 7 +- crates/frontend-promql/tests/scalar_design.rs | 2 +- crates/frontend-promql/tests/support.rs | 2 +- .../tests/univmon_candidates.rs | 8 +- crates/frontend-sql/src/lib.rs | 2 +- .../src/sql/collection_planning.rs | 4 +- crates/frontend-sql/src/sql/expr.rs | 6 +- crates/frontend-sql/src/sql/mod.rs | 14 +- crates/frontend-sql/src/sql/types.rs | 11 +- .../tests/bgp_analytics/bgp_analytics.rs | 4 +- .../bgp_jan2024_workload.rs | 2 +- .../synthetic_packet_trace.rs | 4 +- .../tests/data_quality_check/tpch_deequ.rs | 2 +- .../tests/maintained_population.rs | 4 +- crates/frontend-sql/tests/netflow/netflow.rs | 4 +- crates/frontend-sql/tests/pearson_corr.rs | 3 +- crates/frontend-sql/tests/sql_lowering.rs | 11 +- crates/frontend-sql/tests/temporal_types.rs | 6 +- crates/integration-tests/src/lib.rs | 2 +- crates/integration-tests/tests/aggregate.rs | 2 +- crates/integration-tests/tests/binary_op.rs | 9 +- .../tests/exact_composition.rs | 22 +- .../tests/frontend_timestamps.rs | 2 +- .../tests/kll_pane_execution.rs | 18 +- crates/integration-tests/tests/nested.rs | 9 +- .../tests/operator_design_examples.rs | 8 +- .../tests/operator_sharing.rs | 2 +- .../tests/planner_layering_example1.rs | 6 +- .../tests/precompute_raw_samples.rs | 17 +- .../tests/promql_numeric_regressions.rs | 13 +- .../tests/promql_to_post_asap.rs | 40 +- crates/integration-tests/tests/scan.rs | 3 +- .../tests/sql_to_physical.rs | 8 +- .../tests/sql_to_post_asap.rs | 16 +- .../tests/summary_coverage_e2e.rs | 7 +- crates/integration-tests/tests/time_range.rs | 2 +- crates/planner/src/lib.rs | 2 +- crates/planner/tests/e2e_plan.rs | 2 +- crates/planner/tests/summary_sharing.rs | 12 +- crates/sql-function-catalog/src/lib.rs | 2 +- crates/types/src/dag_export.rs | 26 +- crates/types/src/ir/canonicalize.rs | 18 +- crates/types/src/ir/cse.rs | 22 +- crates/types/src/ir/flat.rs | 12 +- crates/types/src/ir/mod.rs | 32 +- .../{pre_asap => ir/operator}/agg_intent.rs | 15 +- crates/types/src/ir/{ => operator}/asap.rs | 52 +- .../operator}/maintained_population.rs | 9 +- crates/types/src/ir/operator/mod.rs | 19 + crates/types/src/ir/{ => operator}/node.rs | 23 +- .../types/src/ir/{ => operator}/non_asap.rs | 20 +- .../ir/{ => operator}/operator_properties.rs | 5 +- crates/types/src/ir/physical_export.rs | 22 +- .../properties/execution.rs} | 20 +- .../{post_asap => ir/properties}/guarantee.rs | 0 crates/types/src/ir/properties/mod.rs | 13 + .../ir/{ => properties}/summary_coverage.rs | 12 +- .../types/src/ir/{ => properties}/timing.rs | 39 +- crates/types/src/ir/query.rs | 4 +- .../scalar}/column_resolution.rs | 6 +- .../src/{pre_asap => ir/scalar}/expr_ir.rs | 4 +- .../types/src/ir/{scalar.rs => scalar/mod.rs} | 29 +- .../scalar}/scalar_type_rules.rs | 2 +- .../src/ir/{ => schema}/aggregate_schema.rs | 22 +- crates/types/src/ir/{ => schema}/error.rs | 4 +- .../{pre_asap/schema.rs => ir/schema/mod.rs} | 18 +- .../sketch.rs => ir/schema/state_type.rs} | 22 +- crates/types/src/ir/schema_support.rs | 4 +- crates/types/src/lib.rs | 31 +- .../src/physical/execution_data_state.rs | 21 + crates/types/src/physical/mod.rs | 10 + .../{post_asap => physical}/summary_window.rs | 0 crates/types/src/post_asap/mod.rs | 54 -- .../post_asap/query_time/error_estimation.rs | 643 ------------------ crates/types/src/post_asap/query_time/mod.rs | 43 -- crates/types/src/pre_asap/mod.rs | 34 - .../src/{workload.rs => workload/mod.rs} | 3 + .../src/{ => workload}/parsed_workload.rs | 0 crates/types/src/{ => workload}/resources.rs | 0 .../src/{ => workload}/resources/cache.rs | 0 .../types/src/{ => workload}/resources/cpu.rs | 0 .../{ => workload}/resources/measurement.rs | 0 .../src/{ => workload}/resources/physical.rs | 0 .../resources/physical_handoff.rs | 0 .../src/{ => workload}/resources/storage.rs | 0 crates/types/tests/physical_export.rs | 7 +- crates/types/tests/planner_vocabulary.rs | 4 +- crates/types/tests/schema_rebuilding.rs | 17 +- crates/types/tests/structure_contract.rs | 19 +- crates/types/tests/summary_coverage.rs | 19 +- crates/types/tests/summary_merge_structure.rs | 15 +- docs/design_docs/concepts/accuracy-models.md | 2 +- docs/design_docs/concepts/post-asap-ir.md | 4 +- .../decisions/concat-unique-keys.md | 2 +- docs/design_docs/decisions/cse-cost-model.md | 2 +- .../analytical-resource-cost.md | 2 +- .../design_docs/proposals/planner-layering.md | 4 +- .../end-to-end-accuracy-guarantees.md | 2 +- docs/develop_docs/library-api.md | 2 +- docs/develop_docs/offline-sketch-evidence.md | 2 +- docs/develop_docs/physical-handoff-costs.md | 2 +- docs/develop_docs/pre-asap-ir.md | 8 +- docs/develop_docs/storage-operation-costs.md | 2 +- 215 files changed, 1283 insertions(+), 1928 deletions(-) rename crates/types/src/{pre_asap => ir/operator}/agg_intent.rs (98%) rename crates/types/src/ir/{ => operator}/asap.rs (93%) rename crates/types/src/{post_asap => ir/operator}/maintained_population.rs (95%) create mode 100644 crates/types/src/ir/operator/mod.rs rename crates/types/src/ir/{ => operator}/node.rs (95%) rename crates/types/src/ir/{ => operator}/non_asap.rs (98%) rename crates/types/src/ir/{ => operator}/operator_properties.rs (99%) rename crates/types/src/{post_asap/execution_data_state.rs => ir/properties/execution.rs} (91%) rename crates/types/src/{post_asap => ir/properties}/guarantee.rs (100%) create mode 100644 crates/types/src/ir/properties/mod.rs rename crates/types/src/ir/{ => properties}/summary_coverage.rs (98%) rename crates/types/src/ir/{ => properties}/timing.rs (96%) rename crates/types/src/{pre_asap => ir/scalar}/column_resolution.rs (98%) rename crates/types/src/{pre_asap => ir/scalar}/expr_ir.rs (96%) rename crates/types/src/ir/{scalar.rs => scalar/mod.rs} (97%) rename crates/types/src/{pre_asap => ir/scalar}/scalar_type_rules.rs (99%) rename crates/types/src/ir/{ => schema}/aggregate_schema.rs (95%) rename crates/types/src/ir/{ => schema}/error.rs (88%) rename crates/types/src/{pre_asap/schema.rs => ir/schema/mod.rs} (97%) rename crates/types/src/{post_asap/sketch.rs => ir/schema/state_type.rs} (96%) create mode 100644 crates/types/src/physical/execution_data_state.rs create mode 100644 crates/types/src/physical/mod.rs rename crates/types/src/{post_asap => physical}/summary_window.rs (100%) delete mode 100644 crates/types/src/post_asap/mod.rs delete mode 100644 crates/types/src/post_asap/query_time/error_estimation.rs delete mode 100644 crates/types/src/post_asap/query_time/mod.rs delete mode 100644 crates/types/src/pre_asap/mod.rs rename crates/types/src/{workload.rs => workload/mod.rs} (99%) rename crates/types/src/{ => workload}/parsed_workload.rs (100%) rename crates/types/src/{ => workload}/resources.rs (100%) rename crates/types/src/{ => workload}/resources/cache.rs (100%) rename crates/types/src/{ => workload}/resources/cpu.rs (100%) rename crates/types/src/{ => workload}/resources/measurement.rs (100%) rename crates/types/src/{ => workload}/resources/physical.rs (100%) rename crates/types/src/{ => workload}/resources/physical_handoff.rs (100%) rename crates/types/src/{ => workload}/resources/storage.rs (100%) diff --git a/crates/asap-aware-mapping/src/accuracy/composition.rs b/crates/asap-aware-mapping/src/accuracy/composition.rs index daad8071c..55e01330a 100644 --- a/crates/asap-aware-mapping/src/accuracy/composition.rs +++ b/crates/asap-aware-mapping/src/accuracy/composition.rs @@ -705,7 +705,7 @@ pub(super) fn propagate( #[cfg(test)] mod tests { use super::*; - use asap_types::pre_asap::AggIntent; + use asap_types::ir::operator::AggIntent; fn abs(bound: f64, delta: f64) -> ResultGuarantee { ResultGuarantee { metric: ErrorMetric::AbsoluteValue, @@ -1030,7 +1030,7 @@ mod tests { #[test] fn counter_functions_have_distinct_definition_rules() { let operation = |intent| ExactOperation::Aggregate { - reduction: asap_types::pre_asap::Reduction::PerEntity, + reduction: asap_types::ir::operator::Reduction::PerEntity, measures: vec![intent], output_names: vec![], filters: vec![], diff --git a/crates/asap-aware-mapping/src/accuracy/estimators/cms.rs b/crates/asap-aware-mapping/src/accuracy/estimators/cms.rs index 9482c539a..98073fc79 100644 --- a/crates/asap-aware-mapping/src/accuracy/estimators/cms.rs +++ b/crates/asap-aware-mapping/src/accuracy/estimators/cms.rs @@ -42,8 +42,8 @@ mod tests { #[test] fn local_guarantee_inverts_frequency_sizing() { use crate::replacement::default_size_params; - use asap_types::post_asap::{GroupingStrategy, SketchKind}; - let c = asap_types::pre_asap::agg_intent::default_cardinality(); + use asap_types::ir::schema::{GroupingStrategy, SketchKind}; + let c = asap_types::ir::operator::agg_intent::default_cardinality(); let params = default_size_params(SketchAlgorithm::Cms, &c, 0.01, 0.001); let g = DefaultAccuracyModel .local_guarantee( @@ -66,7 +66,7 @@ mod tests { #[test] fn heap_evaluation_retains_frequency_metric() { - use asap_types::post_asap::{GroupingStrategy, SketchKind}; + use asap_types::ir::schema::{GroupingStrategy, SketchKind}; let cms_heap = SketchParams::CmsWithHeap { width: 272, depth: 5, diff --git a/crates/asap-aware-mapping/src/accuracy/estimators/count_sketch.rs b/crates/asap-aware-mapping/src/accuracy/estimators/count_sketch.rs index c95059637..a1fbb621e 100644 --- a/crates/asap-aware-mapping/src/accuracy/estimators/count_sketch.rs +++ b/crates/asap-aware-mapping/src/accuracy/estimators/count_sketch.rs @@ -56,8 +56,8 @@ mod tests { #[test] fn count_sketch_uses_an_l2_guarantee() { use crate::replacement::default_size_params; - use asap_types::post_asap::{GroupingStrategy, SketchKind}; - use asap_types::pre_asap::agg_intent::default_cardinality; + use asap_types::ir::operator::agg_intent::default_cardinality; + use asap_types::ir::schema::{GroupingStrategy, SketchKind}; let intent = default_cardinality(); let count_sketch = default_size_params(SketchAlgorithm::CountSketch, &intent, 0.01, 0.01); let guarantee = DefaultAccuracyModel @@ -67,7 +67,7 @@ mod tests { GroupingStrategy::default(), ), &SketchStatistic::PointCount { - key: asap_types::pre_asap::expr_ir::ColumnRef::SampleValue, + key: asap_types::ir::scalar::ColumnRef::SampleValue, value: None, }, ) diff --git a/crates/asap-aware-mapping/src/accuracy/estimators/hll.rs b/crates/asap-aware-mapping/src/accuracy/estimators/hll.rs index f4556446c..774691af4 100644 --- a/crates/asap-aware-mapping/src/accuracy/estimators/hll.rs +++ b/crates/asap-aware-mapping/src/accuracy/estimators/hll.rs @@ -231,8 +231,8 @@ mod tests { #[test] fn generic_rse_sizing_does_not_certify_confidence() { use crate::replacement::default_size_params; - use asap_types::post_asap::{GroupingStrategy, SketchKind}; - use asap_types::pre_asap::agg_intent::default_cardinality; + use asap_types::ir::operator::agg_intent::default_cardinality; + use asap_types::ir::schema::{GroupingStrategy, SketchKind}; let c = default_cardinality(); let params = default_size_params(SketchAlgorithm::Hll, &c, 0.01, 0.01); let g = DefaultAccuracyModel diff --git a/crates/asap-aware-mapping/src/accuracy/estimators/kll.rs b/crates/asap-aware-mapping/src/accuracy/estimators/kll.rs index 4f880894d..7d468cce5 100644 --- a/crates/asap-aware-mapping/src/accuracy/estimators/kll.rs +++ b/crates/asap-aware-mapping/src/accuracy/estimators/kll.rs @@ -43,8 +43,8 @@ mod tests { #[test] fn local_guarantee_inverts_rank_sizing() { use crate::replacement::default_size_params; - use asap_types::post_asap::{GroupingStrategy, SketchKind}; - use asap_types::pre_asap::agg_intent::default_quantile; + use asap_types::ir::operator::agg_intent::default_quantile; + use asap_types::ir::schema::{GroupingStrategy, SketchKind}; let q = default_quantile(0.99); let params = default_size_params(SketchAlgorithm::Kll, &q, 0.01, 0.01); let g = DefaultAccuracyModel diff --git a/crates/asap-aware-mapping/src/accuracy/estimators/mod.rs b/crates/asap-aware-mapping/src/accuracy/estimators/mod.rs index 0cd5fcb4f..34e1eadb2 100644 --- a/crates/asap-aware-mapping/src/accuracy/estimators/mod.rs +++ b/crates/asap-aware-mapping/src/accuracy/estimators/mod.rs @@ -1,7 +1,7 @@ //! Dispatch committed estimator parameters to their accuracy models. use super::*; -use asap_types::post_asap::GroupingStrategy; -use asap_types::pre_asap::AggIntent; +use asap_types::ir::operator::AggIntent; +use asap_types::ir::schema::GroupingStrategy; pub mod cardinality; pub mod cms; diff --git a/crates/asap-aware-mapping/src/accuracy/evidence.rs b/crates/asap-aware-mapping/src/accuracy/evidence.rs index f779d5782..7ba650674 100644 --- a/crates/asap-aware-mapping/src/accuracy/evidence.rs +++ b/crates/asap-aware-mapping/src/accuracy/evidence.rs @@ -172,8 +172,8 @@ mod tests { let fresh = provider.propagation_stats( &CompositionOperator::ExactSum, &FieldDataType::ExactAggregate( - asap_types::post_asap::ExactKind::Sum, - asap_types::post_asap::ExactParams::Sum, + asap_types::ir::schema::ExactKind::Sum, + asap_types::ir::schema::ExactParams::Sum, ), None, ); @@ -187,8 +187,8 @@ mod tests { .propagation_stats( &CompositionOperator::ExactSum, &FieldDataType::ExactAggregate( - asap_types::post_asap::ExactKind::Sum, - asap_types::post_asap::ExactParams::Sum, + asap_types::ir::schema::ExactKind::Sum, + asap_types::ir::schema::ExactParams::Sum, ), None, ); diff --git a/crates/asap-aware-mapping/src/accuracy/mod.rs b/crates/asap-aware-mapping/src/accuracy/mod.rs index a2f3354c0..618393d69 100644 --- a/crates/asap-aware-mapping/src/accuracy/mod.rs +++ b/crates/asap-aware-mapping/src/accuracy/mod.rs @@ -20,11 +20,12 @@ pub use evidence::{ QuantileInputDomain, WorkloadAccuracyEvidence, }; -use asap_types::ir::OperatorNode; -use asap_types::post_asap::{ - AccuracyError, BoundExpr, CompositionOperator, ErrorMetric, FieldDataType, GuaranteeSource, - ProbabilityExpr, ResultGuarantee, SketchAlgorithm, SketchParams, SketchStatistic, +use asap_types::ir::properties::{ + AccuracyError, BoundExpr, CompositionOperator, ErrorMetric, GuaranteeSource, ProbabilityExpr, + ResultGuarantee, }; +use asap_types::ir::schema::{FieldDataType, SketchAlgorithm, SketchParams, SketchStatistic}; +use asap_types::ir::OperatorNode; use asap_types::types::AccuracyTarget; use crate::exact_composition::ExactOperation; diff --git a/crates/asap-aware-mapping/src/accuracy/reconciliation.rs b/crates/asap-aware-mapping/src/accuracy/reconciliation.rs index a8b16bcae..6f7817ae6 100644 --- a/crates/asap-aware-mapping/src/accuracy/reconciliation.rs +++ b/crates/asap-aware-mapping/src/accuracy/reconciliation.rs @@ -149,13 +149,13 @@ //! same structural child, so adding the edge preserves the reference DAG's //! parent-before-child topological ordering. -use asap_types::ir::non_asap::any_measure_filtered; +use asap_types::ir::operator::non_asap::any_measure_filtered; use std::cmp::Ordering; use std::rc::Rc; -use asap_types::ir::operator_properties::Reduction; +use asap_types::ir::operator::agg_intent::AggIntent; +use asap_types::ir::operator::operator_properties::Reduction; use asap_types::ir::{NonASAPOp, OperatorNode}; -use asap_types::pre_asap::agg_intent::AggIntent; use asap_types::types::AccuracyTarget; use crate::replacement::{ @@ -392,9 +392,9 @@ mod tests { use super::*; use crate::cost_model::{CostModel, DefaultCostModel}; use asap_types::ir::cse::share_common_sub_dags; - use asap_types::ir::operator_properties::{GroupKeys, Source}; - use asap_types::post_asap::SketchAlgorithm; - use asap_types::pre_asap::schema::{ColumnId, DataType, Field, Schema}; + use asap_types::ir::operator::operator_properties::{GroupKeys, Source}; + use asap_types::ir::schema::SketchAlgorithm; + use asap_types::ir::schema::{ColumnId, DataType, Field, Schema}; /// `[ts(0), value(1), job(2)]`. /// A unique-keyed scan (`[ts]`) so `share_common_sub_dags` is actually diff --git a/crates/asap-aware-mapping/src/analytical_cost.rs b/crates/asap-aware-mapping/src/analytical_cost.rs index 7ba28d0ed..f1574be24 100644 --- a/crates/asap-aware-mapping/src/analytical_cost.rs +++ b/crates/asap-aware-mapping/src/analytical_cost.rs @@ -7,8 +7,10 @@ use std::collections::{HashMap, HashSet}; -use asap_types::post_asap::{SketchAlgorithm, SketchParams}; -pub use asap_types::resources::{CacheCapacityEvidence, CacheEvidence, CacheProfile, ModeledCpu}; +use asap_types::ir::schema::{SketchAlgorithm, SketchParams}; +pub use asap_types::workload::resources::{ + CacheCapacityEvidence, CacheEvidence, CacheProfile, ModeledCpu, +}; use asap_types::workload::DataArrival; use serde::{Deserialize, Serialize}; @@ -185,7 +187,7 @@ impl ResourceCalibration { #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] #[serde(from = "ResourceEstimateWire", into = "ResourceEstimateWire")] pub struct ResourceEstimate { - resources: asap_types::resources::PhysicalResources, + resources: asap_types::workload::resources::PhysicalResources, } // Keep the established three-field JSON format. Required fields make a missing @@ -216,7 +218,7 @@ impl From for ResourceEstimateWire { impl ResourceEstimate { pub const fn new(cpu_ops: f64, peak_memory_bytes: u64, scan_bytes: u64) -> Self { Self { - resources: asap_types::resources::PhysicalResources { + resources: asap_types::workload::resources::PhysicalResources { cpu: ModeledCpu { cpu_ops }, peak_memory_bytes: Some(peak_memory_bytes), retained_memory_bytes: None, @@ -243,7 +245,9 @@ impl ResourceEstimate { .expect("analytical scan bytes are required by construction") } - pub fn resources(&self) -> &asap_types::resources::PhysicalResources { + pub fn resources( + &self, + ) -> &asap_types::workload::resources::PhysicalResources { &self.resources } } @@ -2244,7 +2248,7 @@ mod tests { assert_eq!(estimate.cpu_ops(), 12.5); assert_eq!(estimate.peak_memory_bytes(), u64::MAX); assert_eq!(estimate.scan_bytes(), 0); - let shared: &asap_types::resources::PhysicalResources = + let shared: &asap_types::workload::resources::PhysicalResources = estimate.resources(); assert_eq!(shared.cpu.cpu_ops, 12.5); assert_eq!(shared.peak_memory_bytes, Some(u64::MAX)); @@ -2968,7 +2972,7 @@ mod tests { } fn comparison_scope() -> ComparisonScope { - use asap_types::ir::operator_properties::Source; + use asap_types::ir::operator::operator_properties::Source; use asap_types::workload::{ DurationMs, QueryRecurrence, QueryTimeScope, RepeatedDemand, RepetitionInterval, TimeSelection, TimestampMs, @@ -3243,7 +3247,7 @@ mod tests { operator: PhysicalOperator::Scan, children: vec![], scan_selection: Some(ScanSelection { - source: asap_types::ir::operator_properties::Source::Table { + source: asap_types::ir::operator::operator_properties::Source::Table { table_ref: "other_metrics".into(), }, source_snapshot_id: "catalog-version-42".into(), @@ -3308,7 +3312,7 @@ mod tests { let mut scope = comparison_scope(); let coverage = scope.sources[0].clone(); scope.sources.push(ScanSelection { - source: asap_types::ir::operator_properties::Source::Table { + source: asap_types::ir::operator::operator_properties::Source::Table { table_ref: "auxiliary".into(), }, source_snapshot_id: "catalog-version-42".into(), @@ -3672,10 +3676,10 @@ mod tests { // Legacy mapping imports are aliases of the shared schema, not a second type. #[test] fn shared_cache_types_work_through_legacy_mapping_imports() { - let central: asap_types::resources::CacheProfile = cache_profile(100, 50); + let central: asap_types::workload::resources::CacheProfile = cache_profile(100, 50); let legacy: CacheProfile = serde_json::from_value(serde_json::to_value(¢ral).unwrap()).unwrap(); - fn accepts_shared(_: &asap_types::resources::CacheProfile) {} + fn accepts_shared(_: &asap_types::workload::resources::CacheProfile) {} accepts_shared(&legacy); assert_eq!(central, legacy); assert_eq!( diff --git a/crates/asap-aware-mapping/src/cost_model.rs b/crates/asap-aware-mapping/src/cost_model.rs index 9589d1382..dfb39a4a7 100644 --- a/crates/asap-aware-mapping/src/cost_model.rs +++ b/crates/asap-aware-mapping/src/cost_model.rs @@ -16,7 +16,7 @@ //! take/return [`SketchAlgorithm`]/[`SketchParams`]) — `asap_sketch` also has //! sibling families for sampling-based, wavelet-transform, and fitted //! statistical-model summaries -//! ([`asap_types::post_asap::SamplingKind`]/…/[`asap_types::post_asap::StatModelKind`]), +//! ([`asap_types::ir::schema::SamplingKind`]/…/[`asap_types::ir::schema::StatModelKind`]), //! each with its own `(Kind, Params)` pair, deliberately *not* folded into //! this trait: no core `AggIntent` picks one of those families today (only //! [`CostModel::realize_extension`] can, for a deployment-specific @@ -49,12 +49,12 @@ use std::rc::Rc; use crate::exact_composition::ExactOperation; -use asap_types::ir::{ASAPOp, Operator, OperatorNode}; -use asap_types::post_asap::{ +use asap_types::ir::operator::agg_intent::AggIntent; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{ FieldDataType, GroupingStrategy, HydraParams, SketchAlgorithm, SketchParams, SketchStatistic, }; -use asap_types::pre_asap::agg_intent::AggIntent; -use asap_types::pre_asap::expr_ir::ColumnRef; +use asap_types::ir::{ASAPOp, Operator, OperatorNode}; use crate::exact_composition::{ExactComposition, OperationPlacement}; use crate::recurrence::{ @@ -556,7 +556,7 @@ pub trait CostModel { .find(|dtype| !matches!(dtype, FieldDataType::Plain(_))) .cloned() .unwrap_or(FieldDataType::Plain( - asap_types::pre_asap::DataType::Float64, + asap_types::ir::schema::DataType::Float64, )); default_cse_shared_maintenance_cost(&family) } @@ -806,7 +806,7 @@ pub trait CostModel { fn sketch_state( node: &OperatorNode, -) -> Option<(&asap_types::post_asap::SketchKind, &GroupingStrategy)> { +) -> Option<(&asap_types::ir::schema::SketchKind, &GroupingStrategy)> { match &node.operator { Operator::ASAP(ASAPOp::SummaryEstimate { summary_input, .. }) => { sketch_state(summary_input) @@ -979,7 +979,7 @@ impl CostModel for DefaultCostModel { mod tests { use super::*; use crate::replacement::summary_candidates; - use asap_types::pre_asap::agg_intent::default_cardinality; + use asap_types::ir::operator::agg_intent::default_cardinality; #[test] fn default_cost_model_preserves_static_order() { @@ -1101,7 +1101,7 @@ mod tests { #[test] fn custom_cost_model_can_override_sizing_independently_of_ranking() { - use asap_types::pre_asap::agg_intent::default_quantile; + use asap_types::ir::operator::agg_intent::default_quantile; let intent = default_quantile(0.99); assert_eq!( @@ -1183,7 +1183,7 @@ mod tests { assert_eq!( DefaultCostModel.value_operation_support_evidence( &ExactOperation::Aggregate { - reduction: asap_types::ir::operator_properties::Reduction::by(vec![]), + reduction: asap_types::ir::operator::operator_properties::Reduction::by(vec![]), measures: vec![AggIntent::Max { col: None }], output_names: vec![], filters: vec![], @@ -1209,12 +1209,12 @@ mod tests { // ── CSE sharing (issue #237, #223 stage 4) ────────────────────────── - use asap_types::ir::operator_properties::Source; - use asap_types::ir::{NonASAPOp, Predicate, ScalarExpr}; - use asap_types::post_asap::{ + use asap_types::ir::operator::operator_properties::Source; + use asap_types::ir::schema::DataType; + use asap_types::ir::schema::{ ExactKind, ExactParams, Field, GroupingStrategy, Schema, SketchKind, }; - use asap_types::pre_asap::schema::DataType; + use asap_types::ir::{NonASAPOp, Predicate, ScalarExpr}; fn scan() -> Rc { OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Scan { @@ -1239,10 +1239,10 @@ mod tests { asap_types::ir::Operator::ASAP(ASAPOp::SummaryAgg { child: scan(), family: family.clone(), - input: asap_types::post_asap::SummaryUpdate::column( - asap_types::pre_asap::expr_ir::ColumnRef::Named("value".into()), + input: asap_types::ir::schema::SummaryUpdate::column( + asap_types::ir::scalar::ColumnRef::Named("value".into()), ), - reduction: asap_types::ir::operator_properties::Reduction::by(vec![]), + reduction: asap_types::ir::operator::operator_properties::Reduction::by(vec![]), grouping: GroupingStrategy::default(), filter: None, }), @@ -1273,8 +1273,8 @@ mod tests { /// identity-blind recursive walk) would count it. #[test] fn default_recompute_cost_does_not_double_count_an_internally_shared_descendant() { - use asap_types::ir::operator_properties::JoinKind; - use asap_types::pre_asap::expr_ir::ScalarValue; + use asap_types::ir::operator::operator_properties::JoinKind; + use asap_types::ir::scalar::ScalarValue; let true_pred = || Predicate(ScalarExpr::Literal(ScalarValue::Boolean(true))); let shared_leaf = scan(); @@ -1348,8 +1348,8 @@ mod tests { let candidate = CseCandidate { sub_dag: &scan(), bound_summary: &summary_node(FieldDataType::StatModel( - asap_types::post_asap::StatModelKind::Parametric, - asap_types::post_asap::StatModelParams::Parametric { + asap_types::ir::schema::StatModelKind::Parametric, + asap_types::ir::schema::StatModelParams::Parametric { family: "gaussian_mixture".into(), }, )), @@ -1388,8 +1388,8 @@ mod tests { let candidate = CseCandidate { sub_dag: &scan(), bound_summary: &summary_node(FieldDataType::StatModel( - asap_types::post_asap::StatModelKind::Parametric, - asap_types::post_asap::StatModelParams::Parametric { + asap_types::ir::schema::StatModelKind::Parametric, + asap_types::ir::schema::StatModelParams::Parametric { family: "gaussian_mixture".into(), }, )), @@ -1426,7 +1426,7 @@ mod tests { let candidate = ReplacementSubDAG { strategy: "TestStrategy", replacement: Replacement::SubDAG(summary_node(FieldDataType::Plain( - asap_types::pre_asap::DataType::Float64, + asap_types::ir::schema::DataType::Float64, ))), provenance: crate::replacement::ReplacementProvenance::SummaryRealization, rationale: "whatever".into(), @@ -1459,8 +1459,8 @@ mod tests { let pricey = ReplacementSubDAG { strategy: "TestStrategy", replacement: Replacement::SubDAG(summary_node(FieldDataType::StatModel( - asap_types::post_asap::StatModelKind::Parametric, - asap_types::post_asap::StatModelParams::Parametric { + asap_types::ir::schema::StatModelKind::Parametric, + asap_types::ir::schema::StatModelParams::Parametric { family: "gaussian_mixture".into(), }, ))), diff --git a/crates/asap-aware-mapping/src/empirical_comparison.rs b/crates/asap-aware-mapping/src/empirical_comparison.rs index 17e3e9a82..e08bb37c6 100644 --- a/crates/asap-aware-mapping/src/empirical_comparison.rs +++ b/crates/asap-aware-mapping/src/empirical_comparison.rs @@ -1,7 +1,7 @@ //! Query-matched, fixed-snapshot offline recommendations. Observed error is an //! explicit acceptance criterion, never a replacement for formal guarantees. -use asap_types::post_asap::{SketchAlgorithm, SketchParams}; +use asap_types::ir::schema::{SketchAlgorithm, SketchParams}; use serde::{Deserialize, Serialize}; use crate::empirical_cost::{ @@ -596,8 +596,8 @@ mod tests { valid_until_unix_seconds: 200, provenance: row.provenance.clone(), metrics: ExactResourceMeasurements { - resources: asap_types::resources::MeasuredResources { - cpu: asap_types::resources::MeasuredCpu { + resources: asap_types::workload::resources::MeasuredResources { + cpu: asap_types::workload::resources::MeasuredCpu { build_cpu_ns: m(1.0), update_cpu_ns: m(5.0), prepare_cpu_ns: m(1000.0), @@ -721,7 +721,7 @@ mod tests { #[test] fn optional_exact_dimensions_cannot_hide_invalid_measurements() { let selectors: [fn( - &mut asap_types::resources::MeasuredResources, + &mut asap_types::workload::resources::MeasuredResources, ) -> &mut Option; 4] = [ |r| &mut r.cpu.merge_cpu_ns, |r| &mut r.serialized_bytes, diff --git a/crates/asap-aware-mapping/src/empirical_cost.rs b/crates/asap-aware-mapping/src/empirical_cost.rs index eb9904f77..59d49feba 100644 --- a/crates/asap-aware-mapping/src/empirical_cost.rs +++ b/crates/asap-aware-mapping/src/empirical_cost.rs @@ -2,8 +2,8 @@ //! configuration and environment; they are neither runtime feedback nor proofs //! of an accuracy guarantee. CPU quantities are nanoseconds, never CPU operations. -use asap_types::post_asap::{SketchAlgorithm, SketchParams}; -use asap_types::pre_asap::AggIntent; +use asap_types::ir::operator::AggIntent; +use asap_types::ir::schema::{SketchAlgorithm, SketchParams}; use serde::{Deserialize, Serialize}; use crate::cost_model::{CostModel, DefaultCostModel}; @@ -15,7 +15,7 @@ pub const EVIDENCE_SCHEMA_VERSION: u32 = 1; pub const EVIDENCE_MODEL_VERSION: &str = "empirical-update-cpu-v1"; pub use crate::empirical_resources::ResourceMeasurements; -pub use asap_types::resources::Measurement; +pub use asap_types::workload::resources::Measurement; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] @@ -522,8 +522,8 @@ mod tests { repetitions: 3, }, metrics: ResourceMeasurements { - resources: asap_types::resources::MeasuredResources { - cpu: asap_types::resources::MeasuredCpu { + resources: asap_types::workload::resources::MeasuredResources { + cpu: asap_types::workload::resources::MeasuredCpu { update_cpu_ns: Some(Measurement { value: cost, stddev: Some(1.0), diff --git a/crates/asap-aware-mapping/src/empirical_resources.rs b/crates/asap-aware-mapping/src/empirical_resources.rs index 716392f38..63bf9077f 100644 --- a/crates/asap-aware-mapping/src/empirical_resources.rs +++ b/crates/asap-aware-mapping/src/empirical_resources.rs @@ -1,12 +1,12 @@ //! Measured resource payloads and compatibility with the v1 benchmark wire format. //! -//! Physical dimensions live in `asap_types::resources`; flat wire structs below +//! Physical dimensions live in `asap_types::workload::resources`; flat wire structs below //! exist only to keep archived artifacts readable and preserve their field names. -use asap_types::resources::PhysicalResources; +use asap_types::workload::resources::PhysicalResources; use serde::{Deserialize, Serialize}; -pub use asap_types::resources::{MeasuredCpu, MeasuredResources, Measurement}; +pub use asap_types::workload::resources::{MeasuredCpu, MeasuredResources, Measurement}; #[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] #[serde(from = "SketchWire", into = "SketchWire")] diff --git a/crates/asap-aware-mapping/src/exact_composition.rs b/crates/asap-aware-mapping/src/exact_composition.rs index 618265e9b..dac7dd230 100644 --- a/crates/asap-aware-mapping/src/exact_composition.rs +++ b/crates/asap-aware-mapping/src/exact_composition.rs @@ -62,19 +62,20 @@ //! formulas (see `crate::cost_model::read_operation_plan_cost_rate` and //! siblings). Missing statistics keep the conservative kept sub-DAG. -use asap_types::ir::non_asap::any_measure_filtered; +use asap_types::ir::operator::non_asap::any_measure_filtered; use std::rc::Rc; -use asap_types::ir::aggregate_schema::aggregate_output_schema; -use asap_types::ir::operator_properties::Reduction; -use asap_types::ir::timing::{planned_data_state, validate_maintained}; -use asap_types::ir::{NonASAPOp, Operator, OperatorNode, Predicate}; -use asap_types::post_asap::execution_data_state::lift_plain; -use asap_types::post_asap::{ - AccuracyError, ExactOperationSchemaError, ExecutionDataState, ExecutionDataStateError, - ResultGuarantee, Schema, +use asap_types::ir::operator::agg_intent::AggIntent; +use asap_types::ir::operator::operator_properties::Reduction; +use asap_types::ir::properties::timing::{planned_data_state, validate_maintained}; +use asap_types::ir::properties::{ + AccuracyError, ExecutionDataState, ExecutionDataStateError, ResultGuarantee, }; -use asap_types::pre_asap::agg_intent::AggIntent; +use asap_types::ir::schema::aggregate_schema::aggregate_output_schema; +use asap_types::ir::schema::Schema; +use asap_types::ir::{NonASAPOp, Operator, OperatorNode, Predicate}; +use asap_types::physical::execution_data_state::lift_plain; +use asap_types::physical::ExactOperationSchemaError; use asap_types::types::AccuracyTarget; use crate::cost_model::CostModel; @@ -85,7 +86,7 @@ use crate::replacement::{ use crate::{AccuracyModel, DefaultAccuracyModel, PropagationStats}; #[cfg(test)] -use asap_types::post_asap::ExecutionTiming; +use asap_types::ir::properties::ExecutionTiming; /// Which side of the maintenance/read boundary an [`ExactComposition`]'s /// exact function executes on. @@ -202,7 +203,7 @@ impl ExactComposition { /// Build the composed, data_state-validated node over `child`. Every edge of /// the result (including everything beneath `child`) is checked by - /// `asap_types::ir::timing::validate_maintained`; an illegal + /// `asap_types::ir::properties::timing::validate_maintained`; an illegal /// placement is a typed [`RealizationError::ExecutionDataState`], never deferred to a /// runtime. pub fn compose(&self, child: Rc) -> Result, RealizationError> { @@ -509,9 +510,10 @@ mod tests { use crate::cost_model::{DefaultCostModel, ValueOperationCapabilities}; use crate::replacement::retain_exact; use crate::test_support::{agg, agg_per_entity as per_entity, metric_scan, timed}; + use asap_types::ir::operator::agg_intent::default_quantile; + use asap_types::ir::properties::ExecutionDataStateError; + use asap_types::ir::schema::{FieldDataType, SketchAlgorithm}; use asap_types::ir::ASAPOp; - use asap_types::post_asap::{ExecutionDataStateError, FieldDataType, SketchAlgorithm}; - use asap_types::pre_asap::agg_intent::default_quantile; /// `max by (zone) (quantile by (zone, host) (m))`. fn max_over_quantile() -> Rc { @@ -730,11 +732,11 @@ mod tests { #[test] fn exact_operator_rejects_non_plain_input() { let state = Schema::lifted( - vec![asap_types::pre_asap::Field::new( + vec![asap_types::ir::schema::Field::new( "state", FieldDataType::ExactAggregate( - asap_types::post_asap::ExactKind::Sum, - asap_types::post_asap::ExactParams::Sum, + asap_types::ir::schema::ExactKind::Sum, + asap_types::ir::schema::ExactParams::Sum, ), false, )], diff --git a/crates/asap-aware-mapping/src/explanation.rs b/crates/asap-aware-mapping/src/explanation.rs index bc67be96f..8bbe0a02d 100644 --- a/crates/asap-aware-mapping/src/explanation.rs +++ b/crates/asap-aware-mapping/src/explanation.rs @@ -165,7 +165,7 @@ //! | Roll-ups (fine-to-coarse group-by reuse) | [`RollupStrategy`](crate::rollup::RollupStrategy), derived from workload siblings after CSE/target discovery (issue #254) | Any `Replacement::SubDAG` rewrite candidate that rolls a coarse aggregate up from a compatible finer aggregate | //! | Wavelets/OMP | Params type exists (`WaveletKind`/`WaveletParams`), reachable only via a deployment `CostModel::realize_extension` (no core `AggIntent` dispatch picks it) | A `ReplacementStrategy` that inspects a deployment's own `CostModel`, once some intent shape actually maps to `Realization::Wavelet` | //! | Sampling | Same story as Wavelets: `SamplingKind`/`SamplingParams` exist, unreachable from core dispatch | Same hook as Wavelets, for `Realization::Sample` | -//! | Deep generative compression | No representation at all — no `Realization`/`FieldDataType` variant | Needs a new summary family added to `asap_types::post_asap` first | +//! | Deep generative compression | No representation at all — no `Realization`/`FieldDataType` variant | Needs a new summary family added to `asap_types::ir::schema::state_type` first | //! | Approximation frameworks for windows | No representation — `TimeRange`/`PromqlSubquery` windows are always evaluated exactly | Would key off those node types once an approximate-window operator exists | //! | Function decomposition | No representation anywhere | No hook point identified yet | //! | Continuous distributed monitoring | No representation — `RepeatingEntry`/`RepetitionInterval` in `asap_types::workload` describe *that* a query repeats, not any monitoring-specific decomposition | Would likely key off `RepeatingEntry` once such logic exists | @@ -186,8 +186,8 @@ use std::fmt::Display; use std::rc::Rc; use asap_types::ir::cse::{structural_hash, HashCache}; +use asap_types::ir::schema::FieldDataType; use asap_types::ir::{ASAPOp, Operator, OperatorNode}; -use asap_types::post_asap::FieldDataType; use crate::replacement::{ self, CandidateLogicalASAPDAGs, Replacement, ReplacementStrategy, TargetSubDAGCandidates, @@ -510,10 +510,10 @@ fn visit_children( #[cfg(test)] mod tests { use super::*; - use asap_types::ir::operator_properties::{BinaryOpKind, Reduction, Source}; + use asap_types::ir::operator::agg_intent::{default_quantile, AggIntent}; + use asap_types::ir::operator::operator_properties::{BinaryOpKind, Reduction, Source}; + use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{BinaryOperator, NonASAPOp, OperatorNode, Predicate, ScalarExpr}; - use asap_types::pre_asap::agg_intent::{default_quantile, AggIntent}; - use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; @@ -660,7 +660,7 @@ mod tests { /// A sketch-applicable `Aggregate` reachable via two paths that CSE /// collapses onto one `Rc` — the same `median(x) == median(x)` shape - /// `pre_asap::cse`'s own `single_query_shares_its_own_repeated_sub-DAG` + /// `ir::cse`'s own `single_query_shares_its_own_repeated_sub-DAG` /// test uses — must be reported once, not once per path: it is exactly /// one [`crate::replacement::TargetSubDAGCandidates`], keyed by `Rc` pointer identity, /// not one per path that reaches it. @@ -668,7 +668,7 @@ mod tests { fn a_shared_sketchable_aggregate_is_reported_only_once() { let quantile = agg(vec![2], default_quantile(0.99), metric_scan(&["job"])); let root = binary( - BinaryOpKind::Compare(asap_types::pre_asap::expr_ir::CompareOpKind::Eq), + BinaryOpKind::Compare(asap_types::ir::scalar::CompareOpKind::Eq), Rc::clone(&quantile), quantile, ); @@ -759,7 +759,7 @@ mod tests { // shape) — single-query CSE. let branch = agg(vec![2], AggIntent::Sum { col: None }, metric_scan(&["job"])); let q = binary( - BinaryOpKind::Arithmetic(asap_types::pre_asap::expr_ir::ArithmeticOpKind::Div), + BinaryOpKind::Arithmetic(asap_types::ir::scalar::ArithmeticOpKind::Div), Rc::clone(&branch), branch, ); @@ -786,7 +786,7 @@ mod tests { /// (deleted) traversal. #[test] fn a_deeply_shared_sub_dag_under_different_parents_is_reported_once() { - use asap_types::pre_asap::expr_ir::ScalarValue; + use asap_types::ir::scalar::ScalarValue; let shared = agg(vec![2], AggIntent::Sum { col: None }, metric_scan(&["job"])); let root_a = @@ -822,12 +822,12 @@ mod tests { fn rank_candidates( &self, _intent: &AggIntent, - candidates: &[asap_types::post_asap::SketchAlgorithm], - ) -> Vec { + candidates: &[asap_types::ir::schema::SketchAlgorithm], + ) -> Vec { let mut v = candidates.to_vec(); if let Some(pos) = v .iter() - .position(|k| *k == asap_types::post_asap::SketchAlgorithm::DDSketch) + .position(|k| *k == asap_types::ir::schema::SketchAlgorithm::DDSketch) { let dd = v.remove(pos); v.insert(0, dd); diff --git a/crates/asap-aware-mapping/src/function_rules.rs b/crates/asap-aware-mapping/src/function_rules.rs index 0b96e0184..3c83f2e2c 100644 --- a/crates/asap-aware-mapping/src/function_rules.rs +++ b/crates/asap-aware-mapping/src/function_rules.rs @@ -1,7 +1,8 @@ //! Function facts shared by value-operation propagation and accumulator realization. //! Runtime support remains a deployment decision in `CostModel`. -use asap_types::post_asap::{CompositionOperator, ExactKind, ExactParams}; -use asap_types::pre_asap::AggIntent; +use asap_types::ir::operator::AggIntent; +use asap_types::ir::properties::CompositionOperator; +use asap_types::ir::schema::{ExactKind, ExactParams}; pub(crate) struct FunctionRules { pub accuracy: CompositionOperator, diff --git a/crates/asap-aware-mapping/src/grouping.rs b/crates/asap-aware-mapping/src/grouping.rs index bbbaad37f..e0c243e96 100644 --- a/crates/asap-aware-mapping/src/grouping.rs +++ b/crates/asap-aware-mapping/src/grouping.rs @@ -3,7 +3,7 @@ //! per `by` subpopulation (today's only, implicit behavior) or as one //! shared Hydra-family structure serving all of them — orthogonal to //! *which* summary family/kind answers the intent, the same way -//! [`asap_types::post_asap::GroupingStrategy`]'s own doc explains. +//! [`asap_types::ir::schema::GroupingStrategy`]'s own doc explains. //! //! ## Placement: planning metadata and edge-state type //! @@ -26,7 +26,7 @@ //! with no grouping concept at all) has nothing for a //! shared-multi-subpopulation structure to multiplex across. //! - **The family has a Hydra variant** -//! ([`asap_types::post_asap::hydra_kind_for`]): `Cms` and `CountSketch` +//! ([`asap_types::ir::schema::hydra_kind_for`]): `Cms` and `CountSketch` //! have structural Hydra mappings. `HydraKll` remains an explicit //! experimental IR value, but the paper excludes quantiles and search //! therefore never emits it. The shared-grid term is represented @@ -71,14 +71,17 @@ use std::rc::Rc; -use asap_types::ir::operator_properties::Reduction; -use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}; -use asap_types::post_asap::{ - default_hydra_params, hydra_kind_for, AccuracyError, BoundExpr, CompositionOperator, - FieldDataType, GroupingStrategy, GuaranteeSource, HydraKind, ProbabilityExpr, ResultGuarantee, +use asap_types::ir::operator::agg_intent::AggIntent; +use asap_types::ir::operator::operator_properties::Reduction; +use asap_types::ir::properties::{ + AccuracyError, BoundExpr, CompositionOperator, GuaranteeSource, ProbabilityExpr, + ResultGuarantee, +}; +use asap_types::ir::schema::{ + default_hydra_params, hydra_kind_for, FieldDataType, GroupingStrategy, HydraKind, SketchAlgorithm, SketchParams, }; -use asap_types::pre_asap::agg_intent::AggIntent; +use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}; use crate::accuracy::{ AccuracyBudgetAllocator, AccuracyEvidenceProvider, AccuracyModel, PropagationStats, @@ -303,7 +306,7 @@ impl<'a> HydraGroupingStrategy<'a> { serving every subpopulation of this grouped aggregate, instead of one \ {sketch_kind:?} instance per distinct `by` key — legal because this \ aggregate has a non-empty subpopulation concept and {sketch_kind:?} has a \ - modeled Hydra variant (asap_types::post_asap::hydra_kind_for); whether it's \ + modeled Hydra variant (asap_types::ir::schema::hydra_kind_for); whether it's \ *worth* the shared/independent trade-off for the actual subpopulation \ cardinality is a CostModel's call, not this strategy's", describe_intent(intent) @@ -498,8 +501,8 @@ mod tests { use super::*; use crate::accuracy::{DefaultAccuracyModel, EqualSplitAllocator}; use crate::test_support::{agg, agg_per_entity, metric_scan}; - use asap_types::post_asap::ErrorMetric; - use asap_types::pre_asap::agg_intent::{default_cardinality, default_quantile}; + use asap_types::ir::operator::agg_intent::{default_cardinality, default_quantile}; + use asap_types::ir::properties::ErrorMetric; use asap_types::types::AccuracyTarget; // ── has_subpopulations ──────────────────────────────────────────────── @@ -521,7 +524,7 @@ mod tests { #[test] fn without_grouping_has_a_subpopulation_concept_even_when_empty() { - use asap_types::ir::operator_properties::GroupKeys; + use asap_types::ir::operator::operator_properties::GroupKeys; // `without([])` groups by every remaining label — a real // subpopulation concept, unlike `by([])`'s genuine full reduction. assert!(has_subpopulations(&Reduction::Reduce(GroupKeys::without( @@ -635,7 +638,7 @@ mod tests { &self, _op: &CompositionOperator, _family: &FieldDataType, - _query: Option<&asap_types::post_asap::SketchStatistic>, + _query: Option<&asap_types::ir::schema::SketchStatistic>, ) -> PropagationStats { PropagationStats { hydra_shared_grid_collision_bound: Some(0.0), @@ -679,7 +682,7 @@ mod tests { &self, _op: &CompositionOperator, _family: &FieldDataType, - _query: Option<&asap_types::post_asap::SketchStatistic>, + _query: Option<&asap_types::ir::schema::SketchStatistic>, ) -> PropagationStats { PropagationStats { hydra_shared_grid_failure_probability: Some(1.5), @@ -725,7 +728,7 @@ mod tests { &self, _op: &CompositionOperator, _family: &FieldDataType, - _query: Option<&asap_types::post_asap::SketchStatistic>, + _query: Option<&asap_types::ir::schema::SketchStatistic>, ) -> PropagationStats { PropagationStats { hydra_shared_grid_collision_bound: Some(0.1), diff --git a/crates/asap-aware-mapping/src/lib.rs b/crates/asap-aware-mapping/src/lib.rs index b7a6322ca..7ef134e5c 100644 --- a/crates/asap-aware-mapping/src/lib.rs +++ b/crates/asap-aware-mapping/src/lib.rs @@ -138,7 +138,7 @@ //! - [`accuracy`] — the [`AccuracyModel`](accuracy::AccuracyModel) / //! [`AccuracyBudgetAllocator`](accuracy::AccuracyBudgetAllocator) //! extension points (issue #172): the planning-time algebra that derives -//! a machine-readable [`ResultGuarantee`](asap_types::post_asap::ResultGuarantee) +//! a machine-readable [`ResultGuarantee`](asap_types::ir::properties::ResultGuarantee) //! for every finalized post-ASAP value, propagates it through //! approximate-over-approximate compositions under conservative rules //! (no independence assumptions, unknown statistics stay unknown), and diff --git a/crates/asap-aware-mapping/src/logical_candidates.rs b/crates/asap-aware-mapping/src/logical_candidates.rs index 8060a6a5c..2a9e00a23 100644 --- a/crates/asap-aware-mapping/src/logical_candidates.rs +++ b/crates/asap-aware-mapping/src/logical_candidates.rs @@ -7,14 +7,15 @@ use std::collections::{HashMap, HashSet}; use std::rc::Rc; -use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, QueryRoot, SchemaDerivationError}; -use asap_types::post_asap::{ +use asap_types::ir::operator::{AggIntent, Reduction}; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::Schema; +use asap_types::ir::schema::{ EntityIdentity, ExactKind, ExactParams, FieldDataType, GroupingStrategy, NonNegativeWeightProof, SketchAlgorithm, SketchKind, SketchStatistic, SummaryInputExpr, SummaryUpdate, WeightDomain, }; -use asap_types::pre_asap::expr_ir::ColumnRef; -use asap_types::pre_asap::{AggIntent, Reduction, Schema}; +use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, QueryRoot, SchemaDerivationError}; use asap_types::types::AccuracyTarget; use thiserror::Error; @@ -303,7 +304,7 @@ fn summary_update( // the item form the runtime builds keyed summaries from. let item = if child.has_promql_series_identity() { SummaryInputExpr::Column(ColumnRef::Named( - asap_types::pre_asap::schema::PROMQL_SERIES_IDENTITY.into(), + asap_types::ir::schema::PROMQL_SERIES_IDENTITY.into(), )) } else { SummaryInputExpr::EntityIdentity(EntityIdentity::PromqlLabelSet { excluding }) @@ -371,6 +372,6 @@ mod tests { .. } ))); - assert!(choices.iter().any(|choice| matches!(choice, Realization::Sketch(kind) if *kind.algorithm() == asap_types::post_asap::SketchAlgorithm::UnivMon))); + assert!(choices.iter().any(|choice| matches!(choice, Realization::Sketch(kind) if *kind.algorithm() == asap_types::ir::schema::SketchAlgorithm::UnivMon))); } } diff --git a/crates/asap-aware-mapping/src/maintained_population.rs b/crates/asap-aware-mapping/src/maintained_population.rs index 80a0ee76f..329d1219f 100644 --- a/crates/asap-aware-mapping/src/maintained_population.rs +++ b/crates/asap-aware-mapping/src/maintained_population.rs @@ -2,10 +2,13 @@ use crate::replacement::{ Replacement, ReplacementProvenance, ReplacementStrategy, ReplacementSubDAG, TargetSubDAG, }; -use asap_types::ir::non_asap::any_measure_filtered; +use asap_types::ir::operator::maintained_population::*; +use asap_types::ir::operator::non_asap::any_measure_filtered; +use asap_types::ir::operator::{AggIntent, Reduction, Source}; +use asap_types::ir::properties::ResultGuarantee; +use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; +use asap_types::ir::schema::DataType; use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, ScalarExpr}; -use asap_types::post_asap::{maintained_population::*, ResultGuarantee}; -use asap_types::pre_asap::{AggIntent, CompareOpKind, DataType, Reduction, ScalarValue, Source}; use std::rc::Rc; fn strip_projection(mut root: &OperatorNode) -> &OperatorNode { @@ -331,9 +334,7 @@ mod tests { use crate::test_support::lower_promql; use asap_types::ir::cse::share_common_sub_dags; use asap_types::ir::physical_export::compile_physical_asap_dag as export_timed; - use asap_types::ir::timing::{ - apply_materialization_timings, MaterializationAssignment, TimingMemo, - }; + use asap_types::ir::{apply_materialization_timings, MaterializationAssignment, TimingMemo}; /// Time `root` under the default materialization assignment (which runs the /// data-state / population-contract validation) and export it. @@ -475,7 +476,7 @@ mod tests { let candidate = MaintainedPopulationStrategy::new(std::slice::from_ref(&root)) .candidate(&root) .unwrap(); - use asap_types::post_asap::ExecutionTiming; + use asap_types::ir::properties::ExecutionTiming; let with_timings = |population: ExecutionTiming, evaluation: ExecutionTiming| { let mut node = (*candidate).clone(); node.timing = Some(evaluation); diff --git a/crates/asap-aware-mapping/src/pass/mod.rs b/crates/asap-aware-mapping/src/pass/mod.rs index 808856965..1a632730b 100644 --- a/crates/asap-aware-mapping/src/pass/mod.rs +++ b/crates/asap-aware-mapping/src/pass/mod.rs @@ -18,12 +18,10 @@ use std::collections::BTreeMap; use std::rc::Rc; use asap_types::ir::physical_export::compile_physical_asap_workload; -use asap_types::ir::timing::{ - apply_materialization_timings, MaterializationAssignment, TimingMemo, -}; +use asap_types::ir::properties::ExecutionDataStateError; use asap_types::ir::OperatorNode; -use asap_types::parsed_workload::ParsedWorkload; -use asap_types::post_asap::ExecutionDataStateError; +use asap_types::ir::{apply_materialization_timings, MaterializationAssignment, TimingMemo}; +use asap_types::workload::parsed_workload::ParsedWorkload; use asap_types::workload::WorkloadError; use crate::accuracy::{ diff --git a/crates/asap-aware-mapping/src/physical_candidates.rs b/crates/asap-aware-mapping/src/physical_candidates.rs index 494127d6e..74d39ebb8 100644 --- a/crates/asap-aware-mapping/src/physical_candidates.rs +++ b/crates/asap-aware-mapping/src/physical_candidates.rs @@ -11,17 +11,17 @@ use std::collections::HashMap; use std::rc::Rc; +use asap_types::ir::operator::{AggIntent, Reduction}; use asap_types::ir::physical_export::{ compile_physical_asap_workload_with_node_ids, PhysicalASAPDAG, }; +use asap_types::ir::properties::ExecutionDataStateError; +use asap_types::ir::scalar::resolve_column_ref; +use asap_types::ir::scalar::ColumnRef; use asap_types::ir::{ apply_materialization_timings, ASAPOp, MaterializationAssignment, NonASAPOp, Operator, OperatorNode, ScalarExpr, SchemaDerivationError, SortKey, TimingMemo, }; -use asap_types::post_asap::ExecutionDataStateError; -use asap_types::pre_asap::column_resolution::resolve_column_ref; -use asap_types::pre_asap::expr_ir::ColumnRef; -use asap_types::pre_asap::{AggIntent, Reduction}; use thiserror::Error; /// One Stage 2 candidate, derived from exactly one Stage 1 candidate. @@ -158,8 +158,8 @@ mod tests { use crate::test_support::lower_promql; use asap_types::ir::physical_export::PhysicalASAPNodeId; use asap_types::ir::physical_export::PhysicalASAPOperatorPayload as Payload; + use asap_types::ir::properties::ExecutionTiming; use asap_types::ir::QueryRoot; - use asap_types::post_asap::ExecutionTiming; use asap_types::types::AccuracyTarget; /// Exact `topk by (job)` becomes Limit(Sort) partitioned by `job`, and a diff --git a/crates/asap-aware-mapping/src/physical_handoff_cost.rs b/crates/asap-aware-mapping/src/physical_handoff_cost.rs index 207d812f1..f99e03f26 100644 --- a/crates/asap-aware-mapping/src/physical_handoff_cost.rs +++ b/crates/asap-aware-mapping/src/physical_handoff_cost.rs @@ -5,7 +5,7 @@ use crate::analytical_cost::{ PhysicalDAGNode, }; use crate::physical_operator_statistics::{ComparisonScope, OperatorStatistics}; -pub use asap_types::resources::{PhysicalHandoffBytes, PhysicalHandoffKind}; +pub use asap_types::workload::resources::{PhysicalHandoffBytes, PhysicalHandoffKind}; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; diff --git a/crates/asap-aware-mapping/src/physical_operator_statistics.rs b/crates/asap-aware-mapping/src/physical_operator_statistics.rs index 1d2b9ebb0..14317081e 100644 --- a/crates/asap-aware-mapping/src/physical_operator_statistics.rs +++ b/crates/asap-aware-mapping/src/physical_operator_statistics.rs @@ -6,7 +6,7 @@ use std::collections::HashMap; -use asap_types::ir::operator_properties::{InfoMatcher, Source}; +use asap_types::ir::operator::operator_properties::{InfoMatcher, Source}; use asap_types::ir::Predicate; use asap_types::workload::{ diff --git a/crates/asap-aware-mapping/src/physical_plan_cost_model.rs b/crates/asap-aware-mapping/src/physical_plan_cost_model.rs index d846f907b..85a4f8508 100644 --- a/crates/asap-aware-mapping/src/physical_plan_cost_model.rs +++ b/crates/asap-aware-mapping/src/physical_plan_cost_model.rs @@ -2,10 +2,10 @@ use std::{cell::RefCell, rc::Rc}; +use asap_types::ir::operator::AggIntent; +use asap_types::ir::schema::SketchAlgorithm; use asap_types::ir::OperatorNode; -use asap_types::post_asap::SketchAlgorithm; -use asap_types::pre_asap::AggIntent; -use asap_types::resources::CacheProfile; +use asap_types::workload::resources::CacheProfile; use crate::analytical_cost::{ estimate_physical_dag_comparison, AnalyticalCostError, @@ -359,8 +359,9 @@ mod tests { use std::cell::Cell; use std::collections::HashMap; + use asap_types::ir::operator::{Reduction, Source}; + use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{NonASAPOp, OperatorNode}; - use asap_types::pre_asap::{DataType, Field, Reduction, Schema, Source}; use asap_types::types::AccuracyTarget; use asap_types::workload::{ DataArrival, DurationMs, QueryRecurrence, QueryTimeScope, TimeSelection, TimestampMs, diff --git a/crates/asap-aware-mapping/src/plan_selection.rs b/crates/asap-aware-mapping/src/plan_selection.rs index bf680e2f4..f4e6f70c3 100644 --- a/crates/asap-aware-mapping/src/plan_selection.rs +++ b/crates/asap-aware-mapping/src/plan_selection.rs @@ -15,14 +15,15 @@ use asap_types::ir::NonASAPOp; use std::collections::{BTreeMap, HashMap}; +use asap_types::ir::operator::Reduction; use asap_types::ir::physical_export::{ PhysicalASAPDAG, PhysicalASAPNodeId, PhysicalASAPOperatorPayload as Payload, }; -use asap_types::ir::{ASAPOp, Operator, OperatorNode}; -use asap_types::post_asap::{ +use asap_types::ir::schema::{DataType, Schema}; +use asap_types::ir::schema::{ FieldDataType, SketchAlgorithm, SketchParams, SketchStatistic, WeightDomain, }; -use asap_types::pre_asap::{DataType, Reduction, Schema}; +use asap_types::ir::{ASAPOp, Operator, OperatorNode}; use asap_types::types::AccuracyTarget; use asap_types::workload::DataWorkload; use thiserror::Error; diff --git a/crates/asap-aware-mapping/src/query_physical_lowering.rs b/crates/asap-aware-mapping/src/query_physical_lowering.rs index 055d19c79..848bf0fd4 100644 --- a/crates/asap-aware-mapping/src/query_physical_lowering.rs +++ b/crates/asap-aware-mapping/src/query_physical_lowering.rs @@ -54,7 +54,7 @@ pub fn lower_query_physical_dag( ) -> Result { use std::collections::HashMap; - use asap_types::pre_asap::{GroupKeys, RelationalSetOpKind}; + use asap_types::ir::operator::{GroupKeys, RelationalSetOpKind}; scope.validate()?; @@ -194,7 +194,7 @@ pub fn lower_query_physical_dag( expr: &ScalarExpr, ) -> Result { match expr { - ScalarExpr::Literal(asap_types::pre_asap::ScalarValue::Float64(_)) + ScalarExpr::Literal(asap_types::ir::scalar::ScalarValue::Float64(_)) | ScalarExpr::EvalTimestamp => self.lower_promql_scalar_leaf(query, occurrence), ScalarExpr::PromqlScalarFromVector(vector) => self.lower_promql_unary( query, @@ -327,12 +327,12 @@ pub fn lower_query_physical_dag( .. } => { if having.is_some() - || asap_types::ir::non_asap::any_measure_filtered(filters) + || asap_types::ir::operator::non_asap::any_measure_filtered(filters) || measures.is_empty() { return Err(AnalyticalCostError::UnsupportedQueryOperator); } - if matches!(reduction, asap_types::pre_asap::Reduction::PerEntity) { + if matches!(reduction, asap_types::ir::operator::Reduction::PerEntity) { if measures.len() != 1 { return Err(AnalyticalCostError::UnsupportedQueryOperator); } @@ -358,7 +358,7 @@ pub fn lower_query_physical_dag( }; return self.lower_promql_unary(query, occurrence, operator, child); } - let asap_types::pre_asap::Reduction::Reduce(grouping) = reduction else { + let asap_types::ir::operator::Reduction::Reduce(grouping) = reduction else { unreachable!("per-entity reduction returned above") }; if grouping.is_without() || !supports_hash_aggregate(reduction, measures) { @@ -499,9 +499,9 @@ pub fn lower_query_physical_dag( if order_by.is_empty() || !matches!( func, - asap_types::pre_asap::WindowFuncKind::RowNumber - | asap_types::pre_asap::WindowFuncKind::Rank - | asap_types::pre_asap::WindowFuncKind::DenseRank + asap_types::ir::operator::WindowFuncKind::RowNumber + | asap_types::ir::operator::WindowFuncKind::Rank + | asap_types::ir::operator::WindowFuncKind::DenseRank ) { return Err(AnalyticalCostError::UnsupportedQueryOperator); @@ -575,21 +575,21 @@ pub fn lower_query_physical_dag( return Err(AnalyticalCostError::UnsupportedQueryOperator); } let kind = match kind { - asap_types::pre_asap::SampleKind::LimitK(k) => { + asap_types::ir::operator::SampleKind::LimitK(k) => { let k = u64::try_from(*k).map_err(|_| AnalyticalCostError::Overflow)?; if k == 0 { return Err(AnalyticalCostError::MissingOrZero("limitk")); } PromqlSeriesSampleKind::LimitK { k } } - asap_types::pre_asap::SampleKind::LimitRatio(ratio) + asap_types::ir::operator::SampleKind::LimitRatio(ratio) if ratio.is_finite() && (-1.0..=1.0).contains(ratio) => { PromqlSeriesSampleKind::LimitRatio { ratio_bits: ratio.to_bits(), } } - asap_types::pre_asap::SampleKind::LimitRatio(_) => { + asap_types::ir::operator::SampleKind::LimitRatio(_) => { return Err(AnalyticalCostError::UnsupportedQueryOperator) } }; @@ -737,7 +737,7 @@ pub fn lower_query_physical_dag( right, } => { let equality_key_count = - if matches!(kind, asap_types::pre_asap::JoinKind::Cross) { + if matches!(kind, asap_types::ir::operator::JoinKind::Cross) { None } else { hash_join_key_count(&pred.0, left, right) @@ -972,7 +972,7 @@ fn require_operator_statistics( fn bind_scan_coverage( node_id: &str, - source: &asap_types::pre_asap::Source, + source: &asap_types::ir::operator::Source, predicates: &[asap_types::ir::Predicate], scope: &ComparisonScope, ) -> Result { @@ -995,10 +995,11 @@ fn bind_scan_coverage( fn bind_info_coverage( node_id: &str, - selector: &[asap_types::pre_asap::InfoMatcher], + selector: &[asap_types::ir::operator::InfoMatcher], scope: &ComparisonScope, ) -> Result { - use asap_types::pre_asap::{CompareOpKind, Source}; + use asap_types::ir::operator::Source; + use asap_types::ir::scalar::CompareOpKind; let mut metric: Option<&str> = None; for matcher in selector @@ -1042,9 +1043,9 @@ fn duration_millis( } fn promql_binary_operation( - operation: &asap_types::pre_asap::BinaryOpKind, + operation: &asap_types::ir::operator::BinaryOpKind, ) -> PromqlBinaryOperation { - use asap_types::pre_asap::{BinaryOpKind, PromQLVectorSetOpKind}; + use asap_types::ir::operator::{BinaryOpKind, PromQLVectorSetOpKind}; match operation { BinaryOpKind::Set(PromQLVectorSetOpKind::And) => PromqlBinaryOperation::And, BinaryOpKind::Set(PromQLVectorSetOpKind::Or) => PromqlBinaryOperation::Or, @@ -1056,9 +1057,9 @@ fn promql_binary_operation( } fn promql_vector_cardinality( - vector_match: Option<&asap_types::pre_asap::VectorMatch>, + vector_match: Option<&asap_types::ir::operator::VectorMatch>, ) -> PromqlVectorCardinality { - use asap_types::pre_asap::GroupSide; + use asap_types::ir::operator::GroupSide; match vector_match.and_then(|matching| matching.grouping.as_ref()) { Some(grouping) if grouping.side == GroupSide::Left => PromqlVectorCardinality::ManyToOne, Some(_) => PromqlVectorCardinality::OneToMany, @@ -1071,7 +1072,7 @@ fn hash_join_key_count( left: &OperatorNode, right: &OperatorNode, ) -> Option { - use asap_types::pre_asap::CompareOpKind; + use asap_types::ir::scalar::CompareOpKind; let left_width = left.schema.fields.len(); let total_width = left_width.saturating_add(right.schema.fields.len()); @@ -1183,10 +1184,10 @@ fn scalar_operation_count(expr: &ScalarExpr) -> Result } fn supports_hash_aggregate( - reduction: &asap_types::pre_asap::Reduction, - measures: &[asap_types::pre_asap::AggIntent], + reduction: &asap_types::ir::operator::Reduction, + measures: &[asap_types::ir::operator::AggIntent], ) -> bool { - use asap_types::pre_asap::{AggIntent, Reduction}; + use asap_types::ir::operator::{AggIntent, Reduction}; matches!(reduction, Reduction::Reduce(_)) && !measures.is_empty() @@ -1207,19 +1208,20 @@ fn supports_hash_aggregate( }) } -fn presence_intent(intent: &asap_types::pre_asap::AggIntent) -> bool { +fn presence_intent(intent: &asap_types::ir::operator::AggIntent) -> bool { matches!( intent, - asap_types::pre_asap::AggIntent::Absent | asap_types::pre_asap::AggIntent::AbsentOverTime + asap_types::ir::operator::AggIntent::Absent + | asap_types::ir::operator::AggIntent::AbsentOverTime ) } -fn present_over_time_intent(intent: &asap_types::pre_asap::AggIntent) -> bool { - matches!(intent, asap_types::pre_asap::AggIntent::PresentOverTime) +fn present_over_time_intent(intent: &asap_types::ir::operator::AggIntent) -> bool { + matches!(intent, asap_types::ir::operator::AggIntent::PresentOverTime) } -fn fixed_state_per_series_intent(intent: &asap_types::pre_asap::AggIntent) -> bool { - use asap_types::pre_asap::AggIntent; +fn fixed_state_per_series_intent(intent: &asap_types::ir::operator::AggIntent) -> bool { + use asap_types::ir::operator::AggIntent; matches!( intent, AggIntent::Rate @@ -1401,7 +1403,10 @@ mod tests { } } - fn coverage(source: asap_types::pre_asap::Source, predicates: Vec) -> ScanSelection { + fn coverage( + source: asap_types::ir::operator::Source, + predicates: Vec, + ) -> ScanSelection { ScanSelection { source, source_snapshot_id: "snapshot-1".into(), @@ -1412,7 +1417,8 @@ mod tests { #[test] fn info_scan_selection_includes_symbolic_selector_matchers() { - use asap_types::pre_asap::{CompareOpKind, InfoMatcher, Source}; + use asap_types::ir::operator::{InfoMatcher, Source}; + use asap_types::ir::scalar::CompareOpKind; let selector = vec![InfoMatcher { label: "cluster".into(), @@ -1448,7 +1454,8 @@ mod tests { // Correlation can be costed as an exact hash aggregate using provider-supplied state size. #[test] fn correlation_lowers_to_physical_hash_aggregate() { - use asap_types::pre_asap::{AggIntent, DataType, Field, Reduction, Schema, Source}; + use asap_types::ir::operator::{AggIntent, Reduction, Source}; + use asap_types::ir::schema::{DataType, Field, Schema}; let source = Source::Table { table_ref: "pairs".into(), }; @@ -1501,8 +1508,8 @@ mod tests { #[test] fn query_lowering_recurses_and_fuses_global_sort_limit() { - use asap_types::pre_asap::{AggIntent, GroupKeys, Reduction, Source}; - use asap_types::pre_asap::{DataType, Field, Schema}; + use asap_types::ir::operator::{AggIntent, GroupKeys, Reduction, Source}; + use asap_types::ir::schema::{DataType, Field, Schema}; use std::rc::Rc; let scan = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Scan { @@ -1510,7 +1517,7 @@ mod tests { table_ref: "events".into(), }, predicates: vec![Predicate(ScalarExpr::Literal( - asap_types::pre_asap::ScalarValue::Boolean(true), + asap_types::ir::scalar::ScalarValue::Boolean(true), ))], schema: Schema::new(vec![ Field::plain("service", DataType::Utf8, false), @@ -1551,7 +1558,7 @@ mod tests { table_ref: "events".into(), }, vec![Predicate(ScalarExpr::Literal( - asap_types::pre_asap::ScalarValue::Boolean(true), + asap_types::ir::scalar::ScalarValue::Boolean(true), ))], ); let scope = scope(vec![scan_coverage]); @@ -1643,8 +1650,9 @@ mod tests { #[test] fn query_lowering_shares_only_provider_identified_physical_nodes() { - use asap_types::pre_asap::{CompareOpKind, DataType, Field, Schema}; - use asap_types::pre_asap::{JoinKind, Source}; + use asap_types::ir::operator::{JoinKind, Source}; + use asap_types::ir::scalar::CompareOpKind; + use asap_types::ir::schema::{DataType, Field, Schema}; use std::rc::Rc; let shared = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Scan { @@ -1811,8 +1819,9 @@ mod tests { #[test] fn query_lowering_covers_relational_unary_operators() { - use asap_types::pre_asap::{DataType, Field, ScalarValue, Schema}; - use asap_types::pre_asap::{GroupKeys, Source, TimeShift, WindowFuncKind}; + use asap_types::ir::operator::{GroupKeys, Source, TimeShift, WindowFuncKind}; + use asap_types::ir::scalar::ScalarValue; + use asap_types::ir::schema::{DataType, Field, Schema}; let scan = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Scan { source: Source::Table { @@ -1996,8 +2005,8 @@ mod tests { #[test] fn query_lowering_maps_concat_and_union_all_but_rejects_distinct_set_ops() { - use asap_types::pre_asap::{DataType, Field, Schema}; - use asap_types::pre_asap::{RelationalSetOpKind, Source}; + use asap_types::ir::operator::{RelationalSetOpKind, Source}; + use asap_types::ir::schema::{DataType, Field, Schema}; let scan = |name: &str| { OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Scan { @@ -2084,8 +2093,8 @@ mod tests { #[test] fn query_lowering_fails_closed_for_missing_or_inconsistent_statistics() { - use asap_types::pre_asap::Source; - use asap_types::pre_asap::{DataType, Field, Schema}; + use asap_types::ir::operator::Source; + use asap_types::ir::schema::{DataType, Field, Schema}; let scan = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Scan { source: Source::Table { @@ -2202,8 +2211,9 @@ mod tests { #[test] fn query_lowering_accepts_a_consistently_empty_edge() { - use asap_types::pre_asap::{DataType, Field, ScalarValue, Schema}; - use asap_types::pre_asap::{GroupKeys, Source}; + use asap_types::ir::operator::{GroupKeys, Source}; + use asap_types::ir::scalar::ScalarValue; + use asap_types::ir::schema::{DataType, Field, Schema}; let scan = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Scan { source: Source::Table { @@ -2266,8 +2276,8 @@ mod tests { #[test] fn query_lowering_rejects_aggregates_without_a_hash_implementation() { - use asap_types::pre_asap::{AggIntent, GroupKeys, Reduction, Source, WindowFuncKind}; - use asap_types::pre_asap::{DataType, Field, Schema}; + use asap_types::ir::operator::{AggIntent, GroupKeys, Reduction, Source, WindowFuncKind}; + use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; let scan = || { @@ -2323,7 +2333,7 @@ mod tests { .unwrap(); let shifted = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::TimeShift { - shift: asap_types::pre_asap::TimeShift { + shift: asap_types::ir::operator::TimeShift { offset_ms: 60_000, at: None, }, @@ -2352,7 +2362,7 @@ mod tests { #[test] fn scalar_work_counts_every_local_predicate_operation() { - use asap_types::pre_asap::{CompareOpKind, ScalarValue}; + use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; let comparison = || ScalarExpr::Compare { left: Box::new(ScalarExpr::Column(0)), @@ -2367,7 +2377,8 @@ mod tests { #[test] fn promql_presence_is_lowered_with_a_per_step_output_bound() { - use asap_types::pre_asap::{AggIntent, DataType, Field, Reduction, Schema, Source}; + use asap_types::ir::operator::{AggIntent, Reduction, Source}; + use asap_types::ir::schema::{DataType, Field, Schema}; let source = Source::TimeSeries { metric: "missing".into(), @@ -2436,7 +2447,8 @@ mod tests { #[test] fn promql_range_and_subquery_preserve_internal_steps() { - use asap_types::pre_asap::{DataType, Field, Schema, Source}; + use asap_types::ir::operator::Source; + use asap_types::ir::schema::{DataType, Field, Schema}; use std::time::Duration; let source = Source::TimeSeries { metric: "m".into() }; @@ -2517,10 +2529,11 @@ mod tests { #[test] fn promql_binary_lowering_keeps_operation_and_matching_cardinality() { - use asap_types::pre_asap::{ - ArithmeticOpKind, BinaryOpKind, DataType, Field, GroupSide, Schema, Source, - VectorGrouping, VectorMatch, VectorMatchKind, + use asap_types::ir::operator::{ + BinaryOpKind, GroupSide, Source, VectorGrouping, VectorMatch, VectorMatchKind, }; + use asap_types::ir::scalar::ArithmeticOpKind; + use asap_types::ir::schema::{DataType, Field, Schema}; let left_source = Source::TimeSeries { metric: "a".into() }; let right_source = Source::TimeSeries { metric: "b".into() }; @@ -2608,10 +2621,9 @@ mod tests { #[test] fn promql_relabel_sample_and_per_series_lower_as_a_complete_chain() { - use asap_types::pre_asap::{ - AggIntent, DataType, Field, GroupKeys, Reduction, SampleKind, ScalarValue, Schema, - Source, - }; + use asap_types::ir::operator::{AggIntent, GroupKeys, Reduction, SampleKind, Source}; + use asap_types::ir::scalar::ScalarValue; + use asap_types::ir::schema::{DataType, Field, Schema}; let source = Source::TimeSeries { metric: "requests".into(), diff --git a/crates/asap-aware-mapping/src/recurrence.rs b/crates/asap-aware-mapping/src/recurrence.rs index 835a35a65..f6b4501d4 100644 --- a/crates/asap-aware-mapping/src/recurrence.rs +++ b/crates/asap-aware-mapping/src/recurrence.rs @@ -779,15 +779,16 @@ mod tests { // ── decide (structural fallback) ───────────────────────────────────── use crate::cost_model::CseCandidate; - use asap_types::ir::operator_properties::{Reduction, Source}; + use asap_types::ir::operator::operator_properties::{Reduction, Source}; + use asap_types::ir::properties::ResultGuarantee; + use asap_types::ir::scalar::ColumnRef; + use asap_types::ir::schema::DataType; + use asap_types::ir::schema::{ + ExactKind, ExactParams, Field, FieldDataType, GroupingStrategy, Schema, + }; use asap_types::ir::{ ASAPOp, BinaryOperator, ExprSemantics, NonASAPOp, OperatorNode, Predicate, ScalarExpr, }; - use asap_types::post_asap::{ - ExactKind, ExactParams, Field, FieldDataType, GroupingStrategy, ResultGuarantee, Schema, - }; - use asap_types::pre_asap::expr_ir::ColumnRef; - use asap_types::pre_asap::schema::DataType; use std::rc::Rc; @@ -820,7 +821,7 @@ mod tests { asap_types::ir::Operator::ASAP(ASAPOp::SummaryAgg { child: kept, family: family.clone(), - input: asap_types::post_asap::SummaryUpdate::column(ColumnRef::Named( + input: asap_types::ir::schema::SummaryUpdate::column(ColumnRef::Named( "value".into(), )), reduction: Reduction::by(vec![]), @@ -916,9 +917,9 @@ mod tests { fn rank_candidates( &self, - _intent: &asap_types::pre_asap::agg_intent::AggIntent, - candidates: &[asap_types::post_asap::SketchAlgorithm], - ) -> Vec { + _intent: &asap_types::ir::operator::agg_intent::AggIntent, + candidates: &[asap_types::ir::schema::SketchAlgorithm], + ) -> Vec { candidates.to_vec() } fn maintenance_cost_per_update(&self, _candidate: &CseCandidate) -> Cost { @@ -1129,14 +1130,14 @@ mod tests { // ── multiple roots sharing a sub-DAG, via CandidateLogicalASAPDAGs ────────────────── use crate::replacement::search_workload; - use asap_types::ir::operator_properties::Reduction as QueryReduction; - use asap_types::pre_asap::agg_intent::AggIntent; - use asap_types::pre_asap::expr_ir::{CompareOpKind, ScalarValue}; + use asap_types::ir::operator::agg_intent::AggIntent; + use asap_types::ir::operator::operator_properties::Reduction as QueryReduction; + use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; /// Like `scan()`, plus a "job" label column to group by — CSE's /// sharing legality gate requires a provable unique key /// (`Schema::has_unique_key`), and an *ungrouped* aggregate's empty - /// `by` reports none (see `asap_types::pre_asap::cse`'s own "Legality" + /// `by` reports none (see `asap_types::ir::cse`'s own "Legality" /// module docs); grouping by a label column gives `sum_agg()` below a /// real one, matching the pattern /// `replacement.rs`'s own CSE fixtures already use (`metric_scan`/`agg` @@ -1437,7 +1438,7 @@ mod tests { /// Issue #287 review (lower-priority item): a parent referencing the /// same shared child twice (`BinaryOp{lhs: X, rhs: X}`, the same shape - /// `pre_asap::cse`'s own within-one-query sharing collapses onto one + /// `ir::cse`'s own within-one-query sharing collapses onto one /// `Rc`) must credit that child with 2 contributions per repeating /// root, matching how `TargetSubDAGCandidates::consumer_count` already counts that /// exact structural occurrence twice — not 1, which a plain @@ -1449,7 +1450,7 @@ mod tests { operator: BinaryOperator { checked_relative_division: false, checked_finite_division: false, - kind: asap_types::ir::operator_properties::BinaryOpKind::Compare( + kind: asap_types::ir::operator::operator_properties::BinaryOpKind::Compare( CompareOpKind::Eq, ), vector_match: None, diff --git a/crates/asap-aware-mapping/src/replacement.rs b/crates/asap-aware-mapping/src/replacement.rs index 9cc918e12..d2dcb8b9d 100644 --- a/crates/asap-aware-mapping/src/replacement.rs +++ b/crates/asap-aware-mapping/src/replacement.rs @@ -152,7 +152,7 @@ //! sharing every other node in the workload by construction (they *are* //! the same `Rc`s — nothing was copied to make a second "plan"). //! 2. **Dedup by structural hash + `PartialEq`, reusing `pre_asap::cse`'s own -//! discipline.** [`asap_types::pre_asap::cse::structural_hash`] (made +//! discipline.** [`asap_types::ir::cse::structural_hash`] (made //! `pub` for exactly this reuse) is only ever a candidate-narrowing //! filter; [`TargetSubDAGCandidates::add_candidate`]'s actual duplicate check is //! `OperatorNode`'s derived `PartialEq` — the same "hash is a filter, @@ -343,30 +343,33 @@ use crate::accuracy::estimators::{ cms::{cms_depth, cms_width}, saturating_ceil, }; -use asap_types::ir::non_asap::any_measure_filtered; -use asap_types::pre_asap::resolve_column_ref; +use asap_types::ir::operator::non_asap::any_measure_filtered; +use asap_types::ir::scalar::resolve_column_ref; use std::cell::RefCell; use std::collections::{HashMap, HashSet, VecDeque}; use asap_types::ir::cse::{share_common_sub_dags, structural_hash, HashCache}; -use asap_types::ir::operator_properties::{BinaryOpKind, JoinKind, Reduction}; -use asap_types::ir::timing::validate_maintained; +use asap_types::ir::operator::{agg_is_mergeable, AggIntent}; +use asap_types::ir::operator::{BinaryOpKind, JoinKind, Reduction}; +use asap_types::ir::properties::{ + AccuracyError, CompositionOperator, GuaranteeSource, ResultGuarantee, +}; +use asap_types::ir::properties::{ExecutionDataStateError, ExecutionTiming}; +use asap_types::ir::scalar::{ArithmeticOpKind, ColumnRef}; +use asap_types::ir::schema::ColumnId; +use asap_types::ir::schema::{ + EntityIdentity, ExactKind, ExactParams, Field, FieldDataType, GroupingStrategy, + NonNegativeWeightProof, SamplingKind, SamplingParams, Schema, SketchAlgorithm, SketchKind, + SketchParams, SketchStatistic as PostAsapSketchStatistic, StatModelKind, StatModelParams, + SummaryInputExpr, SummaryUpdate, WaveletKind, WaveletParams, WeightDomain, +}; +use asap_types::ir::validate_maintained; use asap_types::ir::SchemaDerivationError; use asap_types::ir::{ ASAPOp, BinaryOperator, NonASAPOp, Operator, OperatorNode, Predicate, ProjectItem, ScalarExpr, SortKey, }; -use asap_types::post_asap::{AccuracyError, CompositionOperator, GuaranteeSource, ResultGuarantee}; -use asap_types::post_asap::{ - EntityIdentity, ExactKind, ExactOperationSchemaError, ExactParams, ExecutionDataStateError, - ExecutionTiming, Field, FieldDataType, GroupingStrategy, NonNegativeWeightProof, SamplingKind, - SamplingParams, Schema, SketchAlgorithm, SketchKind, SketchParams, - SketchStatistic as PostAsapSketchStatistic, StatModelKind, StatModelParams, SummaryInputExpr, - SummaryUpdate, WaveletKind, WaveletParams, WeightDomain, -}; -use asap_types::pre_asap::agg_intent::{agg_is_mergeable, AggIntent}; -use asap_types::pre_asap::expr_ir::{ArithmeticOpKind, ColumnRef}; -use asap_types::pre_asap::schema::ColumnId; +use asap_types::physical::ExactOperationSchemaError; use asap_types::types::AccuracyTarget; use asap_types::workload::{DataWorkload, QueryRecurrence, QueryWorkload, RepeatedDemand}; use std::rc::{Rc, Weak}; @@ -1400,10 +1403,10 @@ impl<'a> ASAPStrategies<'a> { } // Legal only if the candidate stays executable with its states maintained. let timed = |node: &Rc| { - asap_types::ir::timing::apply_materialization_timings( + asap_types::ir::apply_materialization_timings( node, - &asap_types::ir::timing::MaterializationAssignment::all_ingestion_time(), - &mut asap_types::ir::timing::TimingMemo::new(), + &asap_types::ir::MaterializationAssignment::all_ingestion_time(), + &mut asap_types::ir::TimingMemo::new(), ) .ok() .and_then(|timed| { @@ -2741,7 +2744,7 @@ fn is_current_series_source(child: &OperatorNode) -> bool { _ => child, }; matches!(source.non_asap(), Some(NonASAPOp::Scan { - source: asap_types::pre_asap::Source::TimeSeries { .. }, schema, .. + source: asap_types::ir::operator::Source::TimeSeries { .. }, schema, .. }) if schema.has_promql_series_identity()) } @@ -3150,7 +3153,7 @@ fn construct_summary_agg( )?; if snapshot_weighted { - use asap_types::post_asap::{BoundExpr, ProbabilityExpr}; + use asap_types::ir::properties::{BoundExpr, ProbabilityExpr}; let target = accuracy_target(intent).expect("TopK target"); guarantee = if let Some(mut score) = estimator.local_guarantee(&family, query.as_ref().unwrap()) @@ -3328,7 +3331,7 @@ fn keyed_heap_evaluation_schema( source, &mut refs, )?; - let mut fields = Vec::::new(); + let mut fields = Vec::::new(); for reference in refs { let matches: Vec<_> = source .fields @@ -3366,7 +3369,7 @@ fn keyed_heap_evaluation_schema( } fields.push(Field::new( "__asap_estimate", - FieldDataType::Plain(asap_types::pre_asap::DataType::Float64), + FieldDataType::Plain(asap_types::ir::schema::DataType::Float64), false, )); Ok(Schema::lifted(fields, None)) @@ -3379,7 +3382,8 @@ fn ranking_score_index(logical: &OperatorNode, values: &Schema) -> Result Result Option { let ScalarExpr::Compare { left, - op: asap_types::pre_asap::CompareOpKind::Eq, + op: asap_types::ir::scalar::CompareOpKind::Eq, right, semantics, } = &pred.0 @@ -5132,7 +5137,7 @@ fn normalize_cross_input_equi_predicate( }; Some(Predicate(ScalarExpr::Compare { left: Box::new(ScalarExpr::Column(left_id)), - op: asap_types::pre_asap::CompareOpKind::Eq, + op: asap_types::ir::scalar::CompareOpKind::Eq, right: Box::new(ScalarExpr::Column(right_id)), semantics: *semantics, })) @@ -6466,12 +6471,12 @@ pub fn search_workload_with_targets<'s, Id>( ) }) .unwrap_or(( - asap_types::post_asap::ErrorMetric::AbsoluteValue, + asap_types::ir::properties::ErrorMetric::AbsoluteValue, None, None, )), Replacement::ExactComposition(_) => ( - asap_types::post_asap::ErrorMetric::AbsoluteValue, + asap_types::ir::properties::ErrorMetric::AbsoluteValue, None, None, ), @@ -6875,12 +6880,12 @@ mod tests { use crate::accuracy::PropagationStats; use crate::cost_model::Cost; use crate::test_support::{agg, agg_per_entity, lower_promql, maintained, metric_scan, timed}; - use asap_types::ir::operator_properties::{Reduction as ReductionTy, Source}; - use asap_types::ir::TimeRangeKind; - use asap_types::pre_asap::agg_intent::{ + use asap_types::ir::operator::{ agg_is_exact, default_cardinality, default_quantile, MathFunc, TimeFunc, }; - use asap_types::pre_asap::schema::{DataType, Field, Schema as SchemaTy}; + use asap_types::ir::operator::{Reduction as ReductionTy, Source}; + use asap_types::ir::schema::{DataType, Field, Schema as SchemaTy}; + use asap_types::ir::TimeRangeKind; use asap_types::types::AccuracyTarget; use std::collections::HashMap; @@ -7099,7 +7104,7 @@ mod tests { fn equi_pred(left: ColumnId, right: ColumnId) -> Predicate { Predicate(ScalarExpr::Compare { left: Box::new(ScalarExpr::Column(left)), - op: asap_types::pre_asap::CompareOpKind::Eq, + op: asap_types::ir::scalar::CompareOpKind::Eq, right: Box::new(ScalarExpr::Column(right)), semantics: asap_types::ir::ExprSemantics::Sql, }) @@ -7282,7 +7287,7 @@ mod tests { crate::test_support::scan("n", metric_scan(&["job"]).schema.clone()), ); OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Join { - kind: asap_types::ir::operator_properties::JoinKind::Inner, + kind: asap_types::ir::operator::JoinKind::Inner, pred: equi_pred(0, 2), left, right, @@ -7913,7 +7918,7 @@ mod tests { vec![default_quantile(0.99)], vec![], Some(asap_types::ir::Predicate(ScalarExpr::Literal( - asap_types::pre_asap::expr_ir::ScalarValue::Boolean(true), + asap_types::ir::scalar::ScalarValue::Boolean(true), ))), metric_scan(&["job"]), ); @@ -8158,7 +8163,7 @@ mod tests { summary_family_algorithm(summary_input) } Operator::ASAP(ASAPOp::SummaryAgg { family, .. }) => match family { - asap_types::post_asap::FieldDataType::Sketch(kind, _) => kind.algorithm().clone(), + asap_types::ir::schema::FieldDataType::Sketch(kind, _) => kind.algorithm().clone(), other => panic!("expected a Sketch family, got {other:?}"), }, other => panic!("expected SummaryAgg/SummaryEstimate, got {other:?}"), @@ -8488,8 +8493,8 @@ mod tests { // walking the whole DAG, not just root-level pointer identity // (a naive whole-root-only consumer-count pass would miss this; // this module's discover_targets must not). + use asap_types::ir::scalar::ScalarValue; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::ScalarValue; let shared = agg(vec![2], AggIntent::Sum { col: None }, metric_scan(&["job"])); // Different predicates so the two Filter *parents* stay distinct @@ -9055,8 +9060,8 @@ mod tests { // which flips its own decision to Share. Only global_selection, // which folds `a`'s decision into `c`'s effective_consumer_count // before deciding `c`, gets this right. + use asap_types::ir::scalar::ScalarValue; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::ScalarValue; let c = || { OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Dedup { @@ -9205,8 +9210,8 @@ mod tests { #[test] fn effective_repetition_materializes_a_cse_choice_for_a_single_edge_child() { + use asap_types::ir::scalar::ScalarValue; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::ScalarValue; let c = || { OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Dedup { @@ -9239,8 +9244,8 @@ mod tests { #[test] fn shared_ancestor_keeps_a_single_use_cse_descendant_selected() { + use asap_types::ir::scalar::ScalarValue; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::ScalarValue; struct AlwaysShare; impl CostModel for AlwaysShare { @@ -9303,8 +9308,8 @@ mod tests { #[test] fn global_selection_propagates_uses_through_the_selected_rewrite() { + use asap_types::ir::scalar::ScalarValue; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::ScalarValue; struct ReplaceFilterChild; impl ReplacementStrategy for ReplaceFilterChild { @@ -9542,8 +9547,8 @@ mod tests { // discover_targets's own order" DP would see root_b's child edge // after already processing `shared` — topological_order must not // make that mistake. + use asap_types::ir::scalar::ScalarValue; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::ScalarValue; let shared = agg(vec![2], AggIntent::Sum { col: None }, metric_scan(&["job"])); let root_a = @@ -9646,8 +9651,8 @@ mod tests { fn replacements(&self, target: &TargetSubDAG<'_>) -> Vec { let n = self.next.get(); self.next.set(n + 1); + use asap_types::ir::scalar::ScalarValue; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::ScalarValue; let fresh_inner_layer = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Filter { pred: Predicate(ScalarExpr::Literal(ScalarValue::Int64(n))), @@ -10157,8 +10162,8 @@ mod tests { // Filter over a bindable quantile: a kept non-ASAP sub-DAG has no // summary children, so the conservative fallback keeps the whole sub-DAG // logical. + use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::{CompareOpKind, ScalarValue}; let q = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Filter { pred: Predicate(ScalarExpr::Compare { left: Box::new(ScalarExpr::Column(0)), @@ -10178,8 +10183,8 @@ mod tests { #[test] fn having_and_multi_intent_stay_logical() { + use asap_types::ir::scalar::ScalarValue; use asap_types::ir::Predicate; - use asap_types::pre_asap::expr_ir::ScalarValue; let q = crate::test_support::aggregate( ReductionTy::by(vec![2]), vec![default_quantile(0.99)], @@ -10206,7 +10211,7 @@ mod tests { // aggregate is retained exactly rather than bound to a summary. #[test] fn filtered_measure_stays_logical() { - use asap_types::pre_asap::expr_ir::ScalarValue; + use asap_types::ir::scalar::ScalarValue; let mut q = agg(vec![2], default_quantile(0.99), metric_scan(&["job"])); if let Operator::NonASAP(NonASAPOp::Aggregate { filters, .. }) = &mut Rc::make_mut(&mut q).operator @@ -10656,7 +10661,7 @@ mod tests { // ── Accuracy guarantees and fail-closed composition (issue #172) ───── - use asap_types::post_asap::ErrorMetric; + use asap_types::ir::properties::ErrorMetric; /// A test-only `AccuracyModel` that *registers* a rule the default /// deliberately lacks — a sketch over rank-bounded inputs composes diff --git a/crates/asap-aware-mapping/src/rewrite.rs b/crates/asap-aware-mapping/src/rewrite.rs index ca752a971..621a6a700 100644 --- a/crates/asap-aware-mapping/src/rewrite.rs +++ b/crates/asap-aware-mapping/src/rewrite.rs @@ -57,14 +57,14 @@ //! the rewritten form is actually worth picking, by letting the original //! and rewritten forms compete on cost — not this strategy. -use asap_types::ir::non_asap::any_measure_filtered; +use asap_types::ir::operator::non_asap::any_measure_filtered; use std::rc::Rc; -use asap_types::ir::operator_properties::{BinaryOpKind, Reduction}; +use asap_types::ir::operator::agg_intent::AggIntent; +use asap_types::ir::operator::operator_properties::{BinaryOpKind, Reduction}; +use asap_types::ir::scalar::ArithmeticOpKind; +use asap_types::ir::schema::{ColumnId, DataType}; use asap_types::ir::{BinaryOperator, NonASAPOp, OperatorNode, ProjectItem, ScalarExpr}; -use asap_types::pre_asap::agg_intent::AggIntent; -use asap_types::pre_asap::expr_ir::ArithmeticOpKind; -use asap_types::pre_asap::schema::{ColumnId, DataType}; use asap_types::types::AccuracyTarget; @@ -434,8 +434,8 @@ impl ReplacementStrategy for SemanticEquivalentRewriteStrategy { mod tests { use super::*; use crate::test_support::lower_promql; - use asap_types::ir::operator_properties::Source; - use asap_types::pre_asap::schema::{Field, Schema}; + use asap_types::ir::operator::operator_properties::Source; + use asap_types::ir::schema::{Field, Schema}; use asap_types::types::AccuracyTarget; use std::time::Duration; @@ -523,7 +523,7 @@ mod tests { None, vec![], Some(asap_types::ir::Predicate(ScalarExpr::Literal( - asap_types::pre_asap::expr_ir::ScalarValue::Boolean(true), + asap_types::ir::scalar::ScalarValue::Boolean(true), ))), metric_scan(&["job"]), ); @@ -563,9 +563,9 @@ mod tests { #[test] fn does_not_match_a_without_grouped_avg_aggregate() { let q = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Aggregate { - reduction: Reduction::Reduce(asap_types::ir::operator_properties::GroupKeys::without( - vec![2], - )), + reduction: Reduction::Reduce( + asap_types::ir::operator::operator_properties::GroupKeys::without(vec![2]), + ), measures: vec![AggIntent::Avg { col: None }], output_names: vec![], filters: vec![], diff --git a/crates/asap-aware-mapping/src/rollup.rs b/crates/asap-aware-mapping/src/rollup.rs index 572d2c60a..1c60628c6 100644 --- a/crates/asap-aware-mapping/src/rollup.rs +++ b/crates/asap-aware-mapping/src/rollup.rs @@ -66,7 +66,7 @@ //! //! ## `ColumnId` comparability — only sound for identical child IR //! -//! A `ColumnId` is a *position* into a specific `Schema` (`crates/types/src/pre_asap/schema.rs`'s +//! A `ColumnId` is a *position* into a specific `Schema` (`crates/types/src/ir/schema/mod.rs`'s //! own doc: "the same edge, the same schema, the same positional numbering"). //! Comparing the coarser aggregate's `by` positions against the finer //! aggregate's `by` positions is only meaningful when both aggregates have @@ -97,14 +97,14 @@ //! against a superset/subset relationship at all; [`is_legal_rollup_source`] //! declines both directions. -use asap_types::ir::non_asap::any_measure_filtered; +use asap_types::ir::operator::non_asap::any_measure_filtered; use std::collections::HashSet; use std::rc::Rc; -use asap_types::ir::operator_properties::{GroupKeys, Reduction}; +use asap_types::ir::operator::agg_intent::AggIntent; +use asap_types::ir::operator::operator_properties::{GroupKeys, Reduction}; +use asap_types::ir::schema::{ColumnId, Schema}; use asap_types::ir::{NonASAPOp, OperatorNode}; -use asap_types::pre_asap::agg_intent::AggIntent; -use asap_types::pre_asap::schema::{ColumnId, Schema}; use asap_types::types::AccuracyTarget; @@ -396,8 +396,8 @@ fn build_rollup( #[cfg(test)] mod tests { use super::*; - use asap_types::ir::operator_properties::Source; - use asap_types::pre_asap::schema::{DataType, Field}; + use asap_types::ir::operator::operator_properties::Source; + use asap_types::ir::schema::{DataType, Field}; use asap_types::types::AccuracyTarget; /// `[ts(0), value(1), job(2), region(3)]`. diff --git a/crates/asap-aware-mapping/src/storage_io.rs b/crates/asap-aware-mapping/src/storage_io.rs index 125ec915b..5b2d37cae 100644 --- a/crates/asap-aware-mapping/src/storage_io.rs +++ b/crates/asap-aware-mapping/src/storage_io.rs @@ -5,7 +5,7 @@ use std::collections::{HashMap, HashSet}; use serde::{Deserialize, Serialize}; // Keep the original public import path while sharing the sole type definition. -pub use asap_types::resources::StorageResources; +pub use asap_types::workload::resources::StorageResources; use crate::analytical_cost::{ estimate_physical_dag, AnalyticalCostError, EvidenceBackedPhysicalDAG, ExecutionMultiplicity, diff --git a/crates/asap-aware-mapping/src/test_support.rs b/crates/asap-aware-mapping/src/test_support.rs index 739a943f4..a757119da 100644 --- a/crates/asap-aware-mapping/src/test_support.rs +++ b/crates/asap-aware-mapping/src/test_support.rs @@ -50,13 +50,11 @@ pub(crate) fn lower_promql(query: &str, accuracy: AccuracyTarget) -> Rc, ) -> Result< asap_types::ir::physical_export::PhysicalASAPDAG, - asap_types::post_asap::execution_data_state::ExecutionDataStateError, + asap_types::ir::properties::ExecutionDataStateError, > { let timed = apply_materialization_timings( root, diff --git a/crates/asap-aware-mapping/src/topk_reuse.rs b/crates/asap-aware-mapping/src/topk_reuse.rs index aec95292a..1a698af24 100644 --- a/crates/asap-aware-mapping/src/topk_reuse.rs +++ b/crates/asap-aware-mapping/src/topk_reuse.rs @@ -113,8 +113,8 @@ impl ReplacementStrategy for TopKLimitReuseStrategy { mod tests { use super::*; use crate::test_support::scan; - use asap_types::ir::operator_properties::GroupKeys; - use asap_types::pre_asap::Schema; + use asap_types::ir::operator::operator_properties::GroupKeys; + use asap_types::ir::schema::Schema; fn scan_named(metric: &str) -> Rc { scan(metric, Schema::with_time_index(vec![], 0, vec![])) diff --git a/crates/asap-aware-mapping/tests/logical_candidates.rs b/crates/asap-aware-mapping/tests/logical_candidates.rs index 0b0ca0778..ed9094e82 100644 --- a/crates/asap-aware-mapping/tests/logical_candidates.rs +++ b/crates/asap-aware-mapping/tests/logical_candidates.rs @@ -5,13 +5,11 @@ use asap_aware_mapping::{ }, Realization, }; -use asap_types::{ - ir::operator_properties::{Reduction, Source}, - ir::{NonASAPOp, Operator, OperatorNode, QueryRoot, ScalarExpr}, - post_asap::{ExactKind, SketchAlgorithm}, - pre_asap::{AggIntent, DataType, Field, Schema}, - types::AccuracyTarget, -}; +use asap_types::ir::operator::operator_properties::{Reduction, Source}; +use asap_types::ir::operator::AggIntent; +use asap_types::ir::schema::{DataType, ExactKind, Field, Schema, SketchAlgorithm}; +use asap_types::ir::{NonASAPOp, Operator, OperatorNode, QueryRoot, ScalarExpr}; +use asap_types::types::AccuracyTarget; use std::rc::Rc; fn approximate() -> AccuracyTarget { @@ -199,7 +197,7 @@ fn assigned_timing_and_invalid_accuracy_are_rejected() { accuracy: approximate(), })) .clone(); - producer.timing = Some(asap_types::post_asap::ExecutionTiming::QueryTime); + producer.timing = Some(asap_types::ir::properties::ExecutionTiming::QueryTime); assert!(matches!( enumerate_local_logical_candidates(vec![(0, QueryRoot::Operator(Rc::new(producer)))]), Err(LogicalCandidateError::AssignedTiming) diff --git a/crates/asap-aware-mapping/tests/physical_handoff_cost.rs b/crates/asap-aware-mapping/tests/physical_handoff_cost.rs index 141750f61..de7a6f44c 100644 --- a/crates/asap-aware-mapping/tests/physical_handoff_cost.rs +++ b/crates/asap-aware-mapping/tests/physical_handoff_cost.rs @@ -5,7 +5,7 @@ use asap_aware_mapping::analytical_cost::{ use asap_aware_mapping::physical_operator_statistics::{ ComparisonScope, EdgeStatistics, OperatorStatistics, ScanSelection, UnaryEdgeStatistics, }; -use asap_types::ir::operator_properties::Source; +use asap_types::ir::operator::operator_properties::Source; use asap_types::workload::{ DataArrival, DurationMs, QueryRecurrence, QueryTimeScope, TimeSelection, TimestampMs, }; @@ -141,7 +141,7 @@ use asap_aware_mapping::physical_handoff_cost::*; // Legacy mapping imports and the shared resource API are the very same Rust types. #[test] fn mapping_resource_reexports_are_wire_compatible_shared_types() { - let shared = asap_types::resources::PhysicalHandoffBytes { + let shared = asap_types::workload::resources::PhysicalHandoffBytes { network_bytes: 480, materialization_bytes: 40, }; @@ -150,7 +150,7 @@ fn mapping_resource_reexports_are_wire_compatible_shared_types() { serde_json::to_value(legacy).unwrap(), serde_json::json!({"network_bytes": 480, "materialization_bytes": 40}) ); - let shared_kind = asap_types::resources::PhysicalHandoffKind::Materialization; + let shared_kind = asap_types::workload::resources::PhysicalHandoffKind::Materialization; let mut handoff = transfer("persist", None); handoff.kind = shared_kind; let json = serde_json::to_value(&handoff).unwrap(); diff --git a/crates/asap-aware-mapping/tests/storage_io.rs b/crates/asap-aware-mapping/tests/storage_io.rs index 811328f6b..837391826 100644 --- a/crates/asap-aware-mapping/tests/storage_io.rs +++ b/crates/asap-aware-mapping/tests/storage_io.rs @@ -5,7 +5,7 @@ use asap_aware_mapping::analytical_cost::{ use asap_aware_mapping::physical_operator_statistics::{ ComparisonScope, EdgeStatistics, OperatorStatistics, ScanSelection, UnaryEdgeStatistics, }; -use asap_types::ir::operator_properties::Source; +use asap_types::ir::operator::operator_properties::Source; use asap_types::workload::{ DataArrival, DurationMs, QueryRecurrence, QueryTimeScope, TimeSelection, TimestampMs, }; @@ -143,7 +143,7 @@ use asap_aware_mapping::storage_io::*; fn storage_estimates_use_the_shared_resource_type_without_wire_changes() { let (dag, scope) = fixture(); let estimate = estimate_storage_io(&dag, &scope, &profile(&dag), "evidence-v1").unwrap(); - let shared: asap_types::resources::StorageResources = estimate.total; + let shared: asap_types::workload::resources::StorageResources = estimate.total; let legacy: asap_aware_mapping::storage_io::StorageResources = shared; assert_eq!(shared, legacy); let wire = serde_json::to_value(&estimate).unwrap(); diff --git a/crates/asap-physical-operators/README.md b/crates/asap-physical-operators/README.md index b15154b4a..3cae41aab 100644 --- a/crates/asap-physical-operators/README.md +++ b/crates/asap-physical-operators/README.md @@ -27,7 +27,7 @@ use asap_physical_operators::{ plan::PhysicalDAG, runtime::{Limits, RunContext, Scope}, }; -use asap_physical_operators::planner::pre_asap::DataType; +use asap_physical_operators::planner::ir::schema::DataType; use futures::{executor::block_on, StreamExt}; let source = Operator::scalar(Value::Int64(7), DataType::Int64)?; diff --git a/crates/asap-physical-operators/src/capability.rs b/crates/asap-physical-operators/src/capability.rs index 8bdb1891e..48c2395be 100644 --- a/crates/asap-physical-operators/src/capability.rs +++ b/crates/asap-physical-operators/src/capability.rs @@ -9,7 +9,7 @@ //! Stored-state encodings belong to deployments. Full plan acceptance is //! owned by `binding`, which also validates schemas, expressions and inputs. use crate::Error; -use planner_types::post_asap::{ +use planner_types::ir::schema::{ ExactKind, ExactParams, FieldDataType as SummaryFamilyType, GroupingStrategy, SketchAlgorithm, SketchParams, SketchStatistic, SummaryUpdate, }; @@ -122,12 +122,12 @@ fn valid_matrix(width: u32, depth: u32) -> bool { .is_some() } -pub(crate) fn is_unit_sample_frequency(update: &planner_types::post_asap::SummaryUpdate) -> bool { - use planner_types::post_asap::{NonNegativeWeightProof, SummaryInputExpr, WeightDomain}; +pub(crate) fn is_unit_sample_frequency(update: &planner_types::ir::schema::SummaryUpdate) -> bool { + use planner_types::ir::schema::{NonNegativeWeightProof, SummaryInputExpr, WeightDomain}; matches!( update.item, Some(SummaryInputExpr::Column( - planner_types::pre_asap::ColumnRef::SampleValue + planner_types::ir::scalar::ColumnRef::SampleValue )) ) && matches!(update.weight, SummaryInputExpr::Constant(1.0)) && matches!( @@ -139,7 +139,7 @@ pub(crate) fn is_unit_sample_frequency(update: &planner_types::post_asap::Summar } pub fn validate_native_family(family: &SummaryFamilyType) -> Result<(), Error> { - use planner_types::post_asap::SketchAlgorithm as A; + use planner_types::ir::schema::SketchAlgorithm as A; if let SummaryFamilyType::Sketch(kind, grouping) = family { // Plain Count-Min is native as stored state only: it merges and reads // its bare count, but the DAG does not build it from rows. @@ -176,8 +176,8 @@ pub fn validate_native_family(family: &SummaryFamilyType) -> Result<(), Error> { } crate::capability::validate_summary_kernel( family, - &planner_types::post_asap::SummaryUpdate::column( - planner_types::pre_asap::ColumnRef::SampleValue, + &planner_types::ir::schema::SummaryUpdate::column( + planner_types::ir::scalar::ColumnRef::SampleValue, ), &Default::default(), ) @@ -190,7 +190,7 @@ pub fn validate_sketch_evaluation( query: &SketchStatistic, ) -> Result<(), Error> { validate_native_family(family)?; - use planner_types::post_asap::SketchAlgorithm as A; + use planner_types::ir::schema::SketchAlgorithm as A; // A point count without an item value reads the total count. let bare_count = matches!(query, SketchStatistic::PointCount { value: None, .. }); let supported = match family { @@ -229,7 +229,7 @@ pub fn validate_exact_evaluation( ) -> Result<(), Error> { validate_native_family(family)?; use crate::Statistic as S; - use planner_types::post_asap::ExactKind as E; + use planner_types::ir::schema::ExactKind as E; let supported = matches!( (family, evaluation.statistic), (SummaryFamilyType::ExactAggregate(E::Sum, _), S::Sum) diff --git a/crates/asap-physical-operators/src/evaluation.rs b/crates/asap-physical-operators/src/evaluation.rs index 843145ce2..c0898e4f1 100644 --- a/crates/asap-physical-operators/src/evaluation.rs +++ b/crates/asap-physical-operators/src/evaluation.rs @@ -54,7 +54,7 @@ pub fn exact_evaluation( #[cfg(test)] mod counter_tests { use super::*; - use planner_types::post_asap::{ExactKind, ExactParams, FieldDataType as SummaryFamilyType}; + use planner_types::ir::schema::{ExactKind, ExactParams, FieldDataType as SummaryFamilyType}; fn counter(kind: ExactKind, params: ExactParams, keyed: bool) -> ExactAccumulator { ExactAccumulator::new(SummaryFamilyType::ExactAggregate(kind, params), keyed).unwrap() diff --git a/crates/asap-physical-operators/src/expressions/arithmetic.rs b/crates/asap-physical-operators/src/expressions/arithmetic.rs index 64dbb8301..99a912012 100644 --- a/crates/asap-physical-operators/src/expressions/arithmetic.rs +++ b/crates/asap-physical-operators/src/expressions/arithmetic.rs @@ -2,11 +2,11 @@ //! Preserve IEEE non-finite results; callers own their output policies. pub fn evaluate_float64_arithmetic( - operator: &planner_types::pre_asap::ArithmeticOpKind, + operator: &planner_types::ir::scalar::ArithmeticOpKind, left: f64, right: f64, ) -> f64 { - use planner_types::pre_asap::ArithmeticOpKind::*; + use planner_types::ir::scalar::ArithmeticOpKind::*; match operator { Add => left + right, Sub => left - right, @@ -26,7 +26,7 @@ pub fn evaluate_binary( ) -> Result { use crate::expressions::binary::BinaryOpKind; use crate::{values::Value, Error}; - use planner_types::pre_asap::ArithmeticOpKind; + use planner_types::ir::scalar::ArithmeticOpKind; let invalid = || Error::Invalid("unsupported binary operation or invalid checked-division domain".into()); if operator.vector_match.is_some() { @@ -63,8 +63,8 @@ pub fn evaluate_binary( } /// IEEE comparison, as Go's: NaN is unequal to everything, itself included. -fn compare(op: &planner_types::pre_asap::CompareOpKind, left: f64, right: f64) -> Option { - use planner_types::pre_asap::CompareOpKind; +fn compare(op: &planner_types::ir::scalar::CompareOpKind, left: f64, right: f64) -> Option { + use planner_types::ir::scalar::CompareOpKind; Some(match op { CompareOpKind::Eq => left == right, CompareOpKind::Ne => left != right, diff --git a/crates/asap-physical-operators/src/expressions/binary.rs b/crates/asap-physical-operators/src/expressions/binary.rs index 81c1c2656..5b027505e 100644 --- a/crates/asap-physical-operators/src/expressions/binary.rs +++ b/crates/asap-physical-operators/src/expressions/binary.rs @@ -1,7 +1,6 @@ //! Execution configuration for a binary kernel, including comparison evaluation mode. -use planner_types::pre_asap::{ - ArithmeticOpKind, CompareOpKind, PromQLVectorSetOpKind, VectorMatch, -}; +use planner_types::ir::operator::{PromQLVectorSetOpKind, VectorMatch}; +use planner_types::ir::scalar::{ArithmeticOpKind, CompareOpKind}; #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub enum BinaryOpKind { Arithmetic(ArithmeticOpKind), @@ -18,7 +17,7 @@ pub struct BinaryOperator { } impl BinaryOperator { pub fn from_logical(operator: &planner_types::ir::BinaryOperator, return_bool: bool) -> Self { - use planner_types::pre_asap::BinaryOpKind as L; + use planner_types::ir::operator::BinaryOpKind as L; Self { kind: match &operator.kind { L::Arithmetic(op) => BinaryOpKind::Arithmetic(op.clone()), diff --git a/crates/asap-physical-operators/src/expressions/mod.rs b/crates/asap-physical-operators/src/expressions/mod.rs index aad035516..b6e09c9cd 100644 --- a/crates/asap-physical-operators/src/expressions/mod.rs +++ b/crates/asap-physical-operators/src/expressions/mod.rs @@ -3,7 +3,8 @@ use crate::{ values::{plain, SchemaRef, Value}, Error, }; -use planner_types::pre_asap::{ArithmeticOpKind, DataType}; +use planner_types::ir::scalar::ArithmeticOpKind; +use planner_types::ir::schema::DataType; pub mod arithmetic; pub mod binary; mod planner; @@ -66,7 +67,7 @@ impl Expression { right, } => { use crate::expressions::binary::BinaryOpKind; - use planner_types::pre_asap::CompareOpKind; + use planner_types::ir::scalar::CompareOpKind; let (a, n) = left.dtype(input)?; let (b, m) = right.dtype(input)?; if a != DataType::Float64 || b != a || operator.vector_match.is_some() { diff --git a/crates/asap-physical-operators/src/expressions/planner.rs b/crates/asap-physical-operators/src/expressions/planner.rs index 99f4c2b89..f877ff890 100644 --- a/crates/asap-physical-operators/src/expressions/planner.rs +++ b/crates/asap-physical-operators/src/expressions/planner.rs @@ -3,7 +3,8 @@ use crate::{ values::{SchemaRef, Value}, Error, }; -use planner_types::pre_asap::{ArithmeticOpKind, CompareOpKind, DataType, ScalarValue}; +use planner_types::ir::scalar::{ArithmeticOpKind, CompareOpKind, ScalarValue}; +use planner_types::ir::schema::DataType; use planner_types::ir::ScalarExpr; use std::{cmp::Ordering, sync::Arc}; @@ -11,7 +12,7 @@ use std::{cmp::Ordering, sync::Arc}; pub(super) fn evaluate( expr: &ScalarExpr, row: &[Value], - schema: &planner_types::pre_asap::Schema, + schema: &planner_types::ir::schema::Schema, ) -> Result { match expr { ScalarExpr::Column(index) => row.get(*index).cloned().ok_or(Error::Invalid(format!( @@ -115,8 +116,8 @@ pub(super) fn evaluate( Value::Null ))), ScalarExpr::FunctionCall { name, args } => { - use planner_types::pre_asap::scalar_type_rules::MapScalarFunction; - if planner_types::pre_asap::scalar_type_rules::promql_function_arity(name).is_some() { + use planner_types::ir::scalar::scalar_type_rules::MapScalarFunction; + if planner_types::ir::scalar::scalar_type_rules::promql_function_arity(name).is_some() { let values = args .iter() .map(|arg| match evaluate(arg, row, schema)? { @@ -497,7 +498,7 @@ fn promql_function(name: &str, args: &[f64]) -> Result { #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] pub struct CompiledExpression { expression: ScalarExpr, - schema: planner_types::pre_asap::Schema, + schema: planner_types::ir::schema::Schema, output: (DataType, bool), } impl CompiledExpression { @@ -563,7 +564,7 @@ impl CompiledExpression { evaluate(&self.expression, row, &self.schema) } } -fn validate(expr: &ScalarExpr, schema: &planner_types::pre_asap::Schema) -> Result<(), Error> { +fn validate(expr: &ScalarExpr, schema: &planner_types::ir::schema::Schema) -> Result<(), Error> { let invalid = || Error::Invalid(format!("unsupported scalar expression: {expr:?}")); expr.scalar_type(schema) .map_err(|e| Error::Invalid(e.to_string()))?; @@ -646,10 +647,11 @@ fn validate(expr: &ScalarExpr, schema: &planner_types::pre_asap::Schema) -> Resu } ScalarExpr::FunctionCall { name, args } => { if name != "promql_drop_metric_name" - && planner_types::pre_asap::scalar_type_rules::promql_function_arity(name).is_none() + && planner_types::ir::scalar::scalar_type_rules::promql_function_arity(name) + .is_none() && name != "asap_struct_field" && name != "asap_element_access" - && planner_types::pre_asap::scalar_type_rules::MapScalarFunction::from_name(name) + && planner_types::ir::scalar::scalar_type_rules::MapScalarFunction::from_name(name) .is_none() { return Err(invalid()); diff --git a/crates/asap-physical-operators/src/operators/aggregate/mod.rs b/crates/asap-physical-operators/src/operators/aggregate/mod.rs index 7b51b3c66..94c2bb861 100644 --- a/crates/asap-physical-operators/src/operators/aggregate/mod.rs +++ b/crates/asap-physical-operators/src/operators/aggregate/mod.rs @@ -55,13 +55,13 @@ impl Operator { } pub fn window( input: SchemaRef, - intent: planner_types::pre_asap::AggIntent, + intent: planner_types::ir::operator::AggIntent, coordinate: usize, value: usize, groups: Vec, window: Option<(i64, i64)>, ) -> Result { - use planner_types::pre_asap::AggIntent; + use planner_types::ir::operator::AggIntent; validate_groups(&input, &groups)?; let histogram = matches!(intent, AggIntent::HistogramQuantile { .. }); if !matches!( diff --git a/crates/asap-physical-operators/src/operators/aggregate/temporal.rs b/crates/asap-physical-operators/src/operators/aggregate/temporal.rs index a289c5284..d5c084a59 100644 --- a/crates/asap-physical-operators/src/operators/aggregate/temporal.rs +++ b/crates/asap-physical-operators/src/operators/aggregate/temporal.rs @@ -10,7 +10,8 @@ use crate::{ values::{group_key, Value}, Error, }; -use planner_types::pre_asap::{AggIntent, ColumnRef}; +use planner_types::ir::operator::AggIntent; +use planner_types::ir::scalar::ColumnRef; use std::collections::BTreeMap; pub(in crate::operators) async fn reduce( @@ -307,11 +308,10 @@ mod tests { runtime::{batch_execution::evaluate_batch, Limits, RunContext, Scope}, values::Batch, }; - use planner_types::{ - post_asap::{Field as SummaryField, FieldDataType as SummaryFamilyType, Schema}, - pre_asap::DataType, - types::AccuracyTarget, + use planner_types::ir::schema::{ + DataType, Field as SummaryField, FieldDataType as SummaryFamilyType, Schema, }; + use planner_types::types::AccuracyTarget; use std::sync::Arc; // The same window operator must give the same answer in either engine phase. diff --git a/crates/asap-physical-operators/src/operators/joins/mod.rs b/crates/asap-physical-operators/src/operators/joins/mod.rs index 652fbcdcc..60e6d8c93 100644 --- a/crates/asap-physical-operators/src/operators/joins/mod.rs +++ b/crates/asap-physical-operators/src/operators/joins/mod.rs @@ -53,11 +53,11 @@ impl Operator { pub fn relational_join( left: SchemaRef, right: SchemaRef, - kind: planner_types::pre_asap::JoinKind, + kind: planner_types::ir::operator::JoinKind, predicate: &planner_types::ir::Predicate, output: SchemaRef, ) -> Result { - use planner_types::pre_asap::JoinKind; + use planner_types::ir::operator::JoinKind; let mut joined = left.fields.clone(); joined.extend(right.fields.clone()); let predicate = @@ -101,7 +101,7 @@ pub(super) fn execute<'a>( let right = inputs.pop().ok_or_else(|| invalid("right input missing"))?; let left = inputs.pop().ok_or_else(|| invalid("left input missing"))?; return Ok(futures::stream::once(async move { - use planner_types::pre_asap::JoinKind; + use planner_types::ir::operator::JoinKind; let ((left, _left_memory), (right, _right_memory)) = futures::try_join!(collect_rows(left, &context), collect_rows(right, &context))?; let mut workspace = Workspace::new(&context)?; diff --git a/crates/asap-physical-operators/src/operators/mod.rs b/crates/asap-physical-operators/src/operators/mod.rs index 517019118..94d44dae0 100644 --- a/crates/asap-physical-operators/src/operators/mod.rs +++ b/crates/asap-physical-operators/src/operators/mod.rs @@ -7,9 +7,9 @@ use crate::{ Error, }; use futures::StreamExt; -use planner_types::{ - post_asap::{Field as SummaryField, FieldDataType as SummaryFamilyType, Schema, SummaryUpdate}, - pre_asap::{ColumnRef, DataType}, +use planner_types::ir::scalar::ColumnRef; +use planner_types::ir::schema::{ + DataType, Field as SummaryField, FieldDataType as SummaryFamilyType, Schema, SummaryUpdate, }; use std::{collections::BTreeMap, sync::Arc}; pub(crate) mod common; @@ -67,11 +67,11 @@ enum Kind { operator: crate::expressions::binary::BinaryOperator, }, RangeWindow { - intent: Box>, + intent: Box>, }, HistogramQuantile, SeriesWindow { - function: Option>>, + function: Option>>, coordinate: usize, value: usize, range_ms: i64, @@ -79,12 +79,12 @@ enum Kind { at_ms: Option, steps: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - range_at: Option, + range_at: Option, #[serde(default, skip_serializing_if = "Option::is_none")] - steps_range_at: Option, + steps_range_at: Option, }, SeriesLabels { - kind: planner_types::pre_asap::VectorMatchKind, + kind: planner_types::ir::operator::VectorMatchKind, labels: Vec, unique: bool, }, @@ -114,7 +114,7 @@ enum Kind { groups: Vec, }, Window { - intent: Box>, + intent: Box>, coordinate: usize, value: usize, groups: Vec, @@ -129,7 +129,7 @@ enum Kind { require_complete_right: bool, }, Join { - kind: planner_types::pre_asap::JoinKind, + kind: planner_types::ir::operator::JoinKind, predicate: Box, }, SummaryBuild { diff --git a/crates/asap-physical-operators/src/operators/series_labels.rs b/crates/asap-physical-operators/src/operators/series_labels.rs index 3987c5142..a7d5259fd 100644 --- a/crates/asap-physical-operators/src/operators/series_labels.rs +++ b/crates/asap-physical-operators/src/operators/series_labels.rs @@ -3,7 +3,8 @@ use super::*; use crate::expressions::binary::BinaryOpKind; use crate::expressions::binary::BinaryOperator; -use planner_types::pre_asap::{schema::PROMQL_SERIES_IDENTITY, VectorMatchKind}; +use planner_types::ir::operator::VectorMatchKind; +use planner_types::ir::schema::PROMQL_SERIES_IDENTITY; type Labels = BTreeMap; @@ -194,7 +195,8 @@ impl Operator { operator: BinaryOperator, scalars: [bool; 2], ) -> Result { - use planner_types::pre_asap::{CompareOpKind::*, GroupSide, PromQLVectorSetOpKind}; + use planner_types::ir::operator::{GroupSide, PromQLVectorSetOpKind}; + use planner_types::ir::scalar::CompareOpKind::*; let vectors = scalars == [false, false]; let valid = match &operator.kind { BinaryOpKind::Arithmetic(_) => true, @@ -317,7 +319,7 @@ async fn series_binary( work: &mut Cooperative, workspace: &mut Workspace, ) -> Result>, Error> { - use planner_types::pre_asap::{GroupSide, PromQLVectorSetOpKind}; + use planner_types::ir::operator::{GroupSide, PromQLVectorSetOpKind}; let drops_name = matches!( binary.kind, BinaryOpKind::Arithmetic(_) | BinaryOpKind::CompareBool(_) diff --git a/crates/asap-physical-operators/src/operators/series_window.rs b/crates/asap-physical-operators/src/operators/series_window.rs index b22c8e0ac..7b18f78b0 100644 --- a/crates/asap-physical-operators/src/operators/series_window.rs +++ b/crates/asap-physical-operators/src/operators/series_window.rs @@ -1,6 +1,6 @@ //! PromQL per-series evaluation over the samples before an evaluation instant. use super::*; -use planner_types::pre_asap::{AggIntent, AtModifier}; +use planner_types::ir::operator::{AggIntent, AtModifier}; /// A PromQL subquery grid: every multiple of `step_ms` in /// `(T - offset_ms - range_ms, T - offset_ms]`. `T` is `at_ms` (the subquery's diff --git a/crates/asap-physical-operators/src/operators/summary/mod.rs b/crates/asap-physical-operators/src/operators/summary/mod.rs index 5dab8109f..dfec3e6d8 100644 --- a/crates/asap-physical-operators/src/operators/summary/mod.rs +++ b/crates/asap-physical-operators/src/operators/summary/mod.rs @@ -2,7 +2,7 @@ use super::*; /// A summary evaluation: a sketch query, or an exact evaluation with typed parameters. #[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub enum SummaryEvaluation { - Sketch(planner_types::post_asap::SketchStatistic), + Sketch(planner_types::ir::schema::SketchStatistic), Exact(crate::summary_kernels::exact::ExactEvaluation), } @@ -111,8 +111,8 @@ impl Operator { && matches!( family, SummaryFamilyType::ExactAggregate( - planner_types::post_asap::ExactKind::Rate - | planner_types::post_asap::ExactKind::Increase, + planner_types::ir::schema::ExactKind::Rate + | planner_types::ir::schema::ExactKind::Increase, _ ) ) @@ -185,7 +185,7 @@ impl Operator { let mut fields = input.fields.clone(); let result_type = if matches!( fields[state].dtype, - SummaryFamilyType::ExactAggregate(planner_types::post_asap::ExactKind::Count, _) + SummaryFamilyType::ExactAggregate(planner_types::ir::schema::ExactKind::Count, _) ) || integral_count(family, &query) { DataType::Int64 @@ -198,8 +198,8 @@ impl Operator { && matches!( fields[state].dtype, SummaryFamilyType::ExactAggregate( - planner_types::post_asap::ExactKind::Min - | planner_types::post_asap::ExactKind::Max, + planner_types::ir::schema::ExactKind::Min + | planner_types::ir::schema::ExactKind::Max, _ ) ); @@ -216,10 +216,10 @@ impl Operator { /// non-integral total rather than rounding it. fn integral_count(family: &SummaryFamilyType, query: &SummaryEvaluation) -> bool { matches!(family, SummaryFamilyType::Sketch(kind, _) - if kind.algorithm() == &planner_types::post_asap::SketchAlgorithm::Cms) + if kind.algorithm() == &planner_types::ir::schema::SketchAlgorithm::Cms) && matches!( query, - SummaryEvaluation::Sketch(planner_types::post_asap::SketchStatistic::PointCount { + SummaryEvaluation::Sketch(planner_types::ir::schema::SketchStatistic::PointCount { value: None, .. }) @@ -411,8 +411,8 @@ async fn build_summary( let ordered_time = matches!( family, SummaryFamilyType::ExactAggregate( - planner_types::post_asap::ExactKind::Rate - | planner_types::post_asap::ExactKind::Increase, + planner_types::ir::schema::ExactKind::Rate + | planner_types::ir::schema::ExactKind::Increase, _ ) ); diff --git a/crates/asap-physical-operators/src/operators/vector_window.rs b/crates/asap-physical-operators/src/operators/vector_window.rs index 6b21ff6a4..afd99c49c 100644 --- a/crates/asap-physical-operators/src/operators/vector_window.rs +++ b/crates/asap-physical-operators/src/operators/vector_window.rs @@ -1,6 +1,6 @@ //! Window bounds are typed input data; aggregation and histogram semantics stay native. use super::*; -use planner_types::pre_asap::AggIntent; +use planner_types::ir::operator::AggIntent; pub(crate) fn matrix_schema() -> SchemaRef { let mut fields = vector_binary::value_schema(false).fields.clone(); diff --git a/crates/asap-physical-operators/src/physical_planner/candidates.rs b/crates/asap-physical-operators/src/physical_planner/candidates.rs index 274f970aa..f7db4eba0 100644 --- a/crates/asap-physical-operators/src/physical_planner/candidates.rs +++ b/crates/asap-physical-operators/src/physical_planner/candidates.rs @@ -94,7 +94,7 @@ pub fn cut_candidate( /// aligns by value column) has the same timing at compile time as here. /// A query-time node feeding an ingestion-time node has no valid placement. pub fn frontier_from_timing(dag: &PhysicalASAPDAG) -> Result, Error> { - use planner_types::post_asap::ExecutionTiming::IngestionTime; + use planner_types::ir::properties::ExecutionTiming::IngestionTime; let timing = dag .nodes .iter() @@ -408,7 +408,7 @@ mod tests { fn with_timing( dag: &PhysicalASAPDAG, - timing: impl Fn(&PhysicalASAPDAGNode) -> planner_types::post_asap::ExecutionTiming, + timing: impl Fn(&PhysicalASAPDAGNode) -> planner_types::ir::properties::ExecutionTiming, ) -> PhysicalASAPDAG { let mut timed = dag.clone(); for node in &mut timed.nodes { @@ -443,7 +443,7 @@ mod tests { /// lowers each Planner node once and matches `compile_candidate`. #[test] fn timing_cuts_share_one_lowering() { - use planner_types::post_asap::ExecutionTiming::QueryTime; + use planner_types::ir::properties::ExecutionTiming::QueryTime; let (retained, _, root) = grouped_rate(); let ephemeral = with_timing(&retained, |_| QueryTime); let inputs = raw_input(&retained); @@ -473,7 +473,7 @@ mod tests { /// ingestion-time root is itself the frontier. #[test] fn frontier_from_timing_includes_ingestion_root() { - use planner_types::post_asap::ExecutionTiming::IngestionTime; + use planner_types::ir::properties::ExecutionTiming::IngestionTime; let (dag, _, root) = grouped_rate(); let timed = with_timing(&dag, |_| IngestionTime); assert_eq!(frontier_from_timing(&timed).unwrap(), [root]); @@ -482,7 +482,7 @@ mod tests { /// A query-time node feeding an ingestion-time node is rejected. #[test] fn frontier_from_timing_rejects_query_time_input_to_ingestion() { - use planner_types::post_asap::ExecutionTiming::{IngestionTime, QueryTime}; + use planner_types::ir::properties::ExecutionTiming::{IngestionTime, QueryTime}; let (dag, _, _) = grouped_rate(); let timed = with_timing(&dag, |node| { if node.id == dag.roots[0] { diff --git a/crates/asap-physical-operators/src/physical_planner/mod.rs b/crates/asap-physical-operators/src/physical_planner/mod.rs index 3deb01473..d307a6a56 100644 --- a/crates/asap-physical-operators/src/physical_planner/mod.rs +++ b/crates/asap-physical-operators/src/physical_planner/mod.rs @@ -8,17 +8,15 @@ use crate::{ values::{Batch, SchemaRef}, Error, }; +use planner_types::ir::operator::{AggIntent, GroupKeys, Reduction as PlannerReduction}; use planner_types::ir::physical_export::{ PhysicalASAPDAG, PhysicalASAPDAGNode, PhysicalASAPNodeId, PhysicalASAPOperatorPayload as Payload, }; +use planner_types::ir::scalar::{ColumnRef, CompareOpKind}; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::{FieldDataType, SketchStatistic, SummaryInputExpr}; use planner_types::ir::{ASAPOp, NonASAPOp, Operator as LogicalOperator, OperatorNode, ScalarExpr}; -use planner_types::{ - post_asap::{FieldDataType, SketchStatistic, SummaryInputExpr}, - pre_asap::{ - AggIntent, ColumnRef, CompareOpKind, DataType, GroupKeys, Reduction as PlannerReduction, - }, -}; mod logical; use std::{ collections::{BTreeMap, BTreeSet}, @@ -293,7 +291,7 @@ fn compile_internal( continue; } if let Payload::ASAP(ASAPOp::MaintainPopulation { population, .. }) = &node.payload { - use planner_types::post_asap::maintained_population::PopulationInput; + use planner_types::ir::operator::maintained_population::PopulationInput; let PopulationInput::CurrentSeries(spec) = &population.input else { return Err(invalid( "native maintained population requires a current-series input", @@ -326,7 +324,7 @@ fn compile_internal( continue; } if let Payload::ASAP(ASAPOp::EvaluatePopulation { evaluation, .. }) = &node.payload { - use planner_types::post_asap::maintained_population::{ + use planner_types::ir::operator::maintained_population::{ PopulationInput, PopulationStatistic, }; let [producer] = inputs.as_slice() else { @@ -456,7 +454,7 @@ fn compile_internal( *return_bool, ); let query_time = node.output_state.timing - == planner_types::post_asap::ExecutionTiming::QueryTime; + == planner_types::ir::properties::ExecutionTiming::QueryTime; if let Some(&(value, left)) = literals.get(&id) { let [input] = schemas.as_slice() else { return Err(invalid("scalar binary requires one row input")); @@ -633,7 +631,8 @@ fn bind_operation(node: &PhysicalASAPDAGNode, inputs: &[SchemaRef]) -> Result Result { let columns = schema .fields @@ -641,7 +640,7 @@ fn bind_operation(node: &PhysicalASAPDAGNode, inputs: &[SchemaRef]) -> Result>(); @@ -685,7 +684,7 @@ fn bind_operation(node: &PhysicalASAPDAGNode, inputs: &[SchemaRef]) -> Result Result Result { let state = summary_column(input)?; use crate::Statistic as S; - use planner_types::post_asap::ExactKind as E; + use planner_types::ir::schema::ExactKind as E; let statistic = match &input.fields[state].dtype { FieldDataType::ExactAggregate(kind, _) => match kind { E::Sum => S::Sum, @@ -872,10 +871,10 @@ fn bind_operation(node: &PhysicalASAPDAGNode, inputs: &[SchemaRef]) -> Result Result, Error> { let mut keys = Vec::new(); semi_join_keys(&pred.0, left.fields.len(), right.fields.len(), &mut keys)?; diff --git a/crates/asap-physical-operators/src/physical_planner/precompute.rs b/crates/asap-physical-operators/src/physical_planner/precompute.rs index 6ff9196aa..10c61bfb5 100644 --- a/crates/asap-physical-operators/src/physical_planner/precompute.rs +++ b/crates/asap-physical-operators/src/physical_planner/precompute.rs @@ -1,20 +1,19 @@ //! Compile immutable summary-input computation with explicit population and pane identity. use super::promql_rows::SERIES_IDENTITY_COLUMN as SERIES_IDENTITY; use super::*; +use planner_types::ir::properties::ExecutionTiming; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::FieldDataType as SummaryFamilyType; +use planner_types::ir::schema::{GroupingStrategy, Schema}; use planner_types::ir::ASAPOp; use planner_types::ir::NonASAPOp; -use planner_types::post_asap::FieldDataType as SummaryFamilyType; -use planner_types::{ - post_asap::{ExecutionTiming, GroupingStrategy, Schema}, - pre_asap::DataType, -}; /// Physical rows carry the population and pane coordinate alongside the logical value. /// These fields preserve identities which are implicit in a stored summary instance. pub fn population_schema(family: SummaryFamilyType) -> SchemaRef { Arc::new(Schema { fields: vec![ - planner_types::post_asap::Field { + planner_types::ir::schema::Field { name: "$population".into(), dtype: SummaryFamilyType::Plain(DataType::Map { key: Box::new(DataType::Utf8), @@ -24,13 +23,13 @@ pub fn population_schema(family: SummaryFamilyType) -> SchemaRef { nullable: false, table: None, }, - planner_types::post_asap::Field { + planner_types::ir::schema::Field { name: "$window_end".into(), dtype: SummaryFamilyType::Plain(DataType::Timestamp), nullable: false, table: None, }, - planner_types::post_asap::Field { + planner_types::ir::schema::Field { name: "value".into(), dtype: family, nullable: false, @@ -90,7 +89,7 @@ pub fn boundary_schema(node: &PhysicalASAPDAGNode) -> Result { &node.payload, Payload::NonASAP( NonASAPOp::Scan { - source: planner_types::pre_asap::Source::TimeSeries { .. }, + source: planner_types::ir::operator::Source::TimeSeries { .. }, .. } | NonASAPOp::TimeRange { .. } ) @@ -264,7 +263,7 @@ fn validate_value_output(node: &PhysicalASAPDAGNode) -> Result<(), Error> { let schema = &node.output_schema; // Physical population rows already carry the complete identity in `$population`. // Typed logical plans may expose its opaque series-identity column as metadata. - let identity = planner_types::pre_asap::schema::PROMQL_SERIES_IDENTITY; + let identity = planner_types::ir::schema::PROMQL_SERIES_IDENTITY; let identities = schema .fields .iter() @@ -353,11 +352,11 @@ fn fragment( }; validate_value_output(node)?; let statistic = match &input.fields[2].dtype { - SummaryFamilyType::ExactAggregate(planner_types::post_asap::ExactKind::Sum, _) => { + SummaryFamilyType::ExactAggregate(planner_types::ir::schema::ExactKind::Sum, _) => { crate::Statistic::Sum } SummaryFamilyType::ExactAggregate( - planner_types::post_asap::ExactKind::Count, + planner_types::ir::schema::ExactKind::Count, _, ) => crate::Statistic::Count, _ => { @@ -416,10 +415,10 @@ fn fragment( && crate::capability::is_unit_sample_frequency(update) && matches!(family, SummaryFamilyType::Sketch(kind, _) if !matches!( kind.algorithm(), - planner_types::post_asap::SketchAlgorithm::Cms - | planner_types::post_asap::SketchAlgorithm::CountSketch - | planner_types::post_asap::SketchAlgorithm::CmsWithHeap - | planner_types::post_asap::SketchAlgorithm::CountSketchWithHeap + planner_types::ir::schema::SketchAlgorithm::Cms + | planner_types::ir::schema::SketchAlgorithm::CountSketch + | planner_types::ir::schema::SketchAlgorithm::CmsWithHeap + | planner_types::ir::schema::SketchAlgorithm::CountSketchWithHeap )); let keyed = update.item.is_some() && !unit_frequency; if (keyed && !raw) || !matches!(grouping, GroupingStrategy::PerSubpopulationInstance) { @@ -432,8 +431,8 @@ fn fragment( if raw && matches!( update.weight_domain, - planner_types::post_asap::WeightDomain::NonNegative { - proof: planner_types::post_asap::NonNegativeWeightProof::ResetAwareCounterDerivative + planner_types::ir::schema::WeightDomain::NonNegative { + proof: planner_types::ir::schema::NonNegativeWeightProof::ResetAwareCounterDerivative } ) { @@ -442,10 +441,10 @@ fn fragment( )); } if keyed - && matches!(family, SummaryFamilyType::Sketch(kind, _) if kind.algorithm() == &planner_types::post_asap::SketchAlgorithm::CmsWithHeap) + && matches!(family, SummaryFamilyType::Sketch(kind, _) if kind.algorithm() == &planner_types::ir::schema::SketchAlgorithm::CmsWithHeap) && !matches!( update.weight_domain, - planner_types::post_asap::WeightDomain::NonNegative { .. } + planner_types::ir::schema::WeightDomain::NonNegative { .. } ) { return Err(invalid("CMS requires a nonnegative weight contract")); @@ -515,7 +514,7 @@ fn fragment( )?; for (index, (expression, dtype)) in items.into_iter().enumerate() { let name = format!("$item{index}"); - fields.push(planner_types::post_asap::Field { + fields.push(planner_types::ir::schema::Field { name: name.clone(), dtype: SummaryFamilyType::Plain(dtype), nullable: false, @@ -627,7 +626,7 @@ fn raw_items( DataType::Utf8, )), SummaryInputExpr::EntityIdentity( - planner_types::post_asap::EntityIdentity::PromqlLabelSet { excluding }, + planner_types::ir::schema::EntityIdentity::PromqlLabelSet { excluding }, ) => items.push(identity( excluding .iter() diff --git a/crates/asap-physical-operators/src/physical_planner/promql_fallback.rs b/crates/asap-physical-operators/src/physical_planner/promql_fallback.rs index fcd1382ab..354712a93 100644 --- a/crates/asap-physical-operators/src/physical_planner/promql_fallback.rs +++ b/crates/asap-physical-operators/src/physical_planner/promql_fallback.rs @@ -3,8 +3,8 @@ //! computes selection, range functions, subqueries, matching and aggregation. use super::*; use crate::operators::SubquerySteps; -use planner_types::post_asap::execution_data_state::lift_plain; -use planner_types::pre_asap::{AtModifier, VectorMatchKind}; +use planner_types::ir::operator::{AtModifier, VectorMatchKind}; +use planner_types::physical::execution_data_state::lift_plain; /// Input slot for the raw series read by the `selector`th selector (in /// [`raw_series`] order) of Fallback node `node`. The node's own ID names its @@ -92,7 +92,7 @@ fn millis(duration: &std::time::Duration) -> Result { } /// A fixed `@` time. `start()`/`end()` depend on the deployment's range query. -fn at(shift: &planner_types::pre_asap::TimeShift) -> Result, Error> { +fn at(shift: &planner_types::ir::operator::TimeShift) -> Result, Error> { match shift.at { None => Ok(None), Some(AtModifier::Timestamp(at)) => Ok(Some(at)), @@ -196,13 +196,13 @@ impl Lowering { let step = self.value(child)?; let input = self.schema(&step); let (replacement, source_regex) = match value { - ScalarExpr::Literal(planner_types::pre_asap::ScalarValue::Utf8(value)) => { + ScalarExpr::Literal(planner_types::ir::scalar::ScalarValue::Utf8(value)) => { (value.clone(), None) } ScalarExpr::FunctionCall { name, args } if name == "label_replace" => { - let [ScalarExpr::Column(source), ScalarExpr::Literal(planner_types::pre_asap::ScalarValue::Utf8( + let [ScalarExpr::Column(source), ScalarExpr::Literal(planner_types::ir::scalar::ScalarValue::Utf8( pattern, - )), ScalarExpr::Literal(planner_types::pre_asap::ScalarValue::Utf8( + )), ScalarExpr::Literal(planner_types::ir::scalar::ScalarValue::Utf8( replacement, ))] = args.as_slice() else { @@ -239,7 +239,7 @@ impl Lowering { ) } NonASAPOp::Aggregate { - reduction: planner_types::pre_asap::Reduction::PerEntity, + reduction: planner_types::ir::operator::Reduction::PerEntity, measures, having: None, child, @@ -258,7 +258,7 @@ impl Lowering { Ok(self.add(Operator::series_without_name(input)?, vec![step])) } NonASAPOp::Aggregate { - reduction: planner_types::pre_asap::Reduction::Reduce(keys), + reduction: planner_types::ir::operator::Reduction::Reduce(keys), measures, having: None, child, @@ -276,7 +276,7 @@ impl Lowering { child, qualifier, } => { - let value = planner_types::pre_asap::column_resolution::resolve_column_ref( + let value = planner_types::ir::scalar::column_resolution::resolve_column_ref( &ColumnRef::SampleValue, &child.schema, ) @@ -307,7 +307,7 @@ impl Lowering { computed = Some(col); } else { let expected = if !keep_name - && field.name == planner_types::pre_asap::schema::PROMQL_SERIES_IDENTITY + && field.name == planner_types::ir::schema::PROMQL_SERIES_IDENTITY { ScalarExpr::FunctionCall { name: "promql_drop_metric_name".into(), @@ -331,7 +331,7 @@ impl Lowering { self.sample_scalar_operation(&computed.expr, child, value, expression) } NonASAPOp::Filter { pred, child } => { - let value = planner_types::pre_asap::column_resolution::resolve_column_ref( + let value = planner_types::ir::scalar::column_resolution::resolve_column_ref( &ColumnRef::SampleValue, &child.schema, ) @@ -426,7 +426,8 @@ impl Lowering { continue; } if let ScalarExpr::FunctionCall { name, args } = &mut col.expr { - if planner_types::pre_asap::scalar_type_rules::promql_function_arity(name).is_none() + if planner_types::ir::scalar::scalar_type_rules::promql_function_arity(name) + .is_none() || args.first() != Some(&ScalarExpr::Column(value)) { return Err(invalid("unsupported pointwise function")); @@ -441,9 +442,9 @@ impl Lowering { let join = Operator::relational_join( left, right, - planner_types::pre_asap::JoinKind::Inner, + planner_types::ir::operator::JoinKind::Inner, &planner_types::ir::Predicate(ScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Boolean(true), + planner_types::ir::scalar::ScalarValue::Boolean(true), )), Arc::new(schema), )?; @@ -454,7 +455,7 @@ impl Lowering { let predicate = ScalarExpr::Not(Box::new(ScalarExpr::Compare { left: Box::new(args[1].clone()), right: Box::new(args[2].clone()), - op: planner_types::pre_asap::CompareOpKind::Gt, + op: planner_types::ir::scalar::CompareOpKind::Gt, semantics: planner_types::ir::ExprSemantics::Promql, })); let schema = self.schema(&input); @@ -530,7 +531,7 @@ impl Lowering { fn scalar_value(&mut self, expr: &ScalarExpr) -> Result { match expr { - ScalarExpr::Literal(planner_types::pre_asap::ScalarValue::Float64(value)) => Ok(self + ScalarExpr::Literal(planner_types::ir::scalar::ScalarValue::Float64(value)) => Ok(self .add( Operator::scalar(crate::values::Value::Float64(*value), DataType::Float64)?, vec![], @@ -559,7 +560,7 @@ impl Lowering { self.schema(&value), self.schema(&minus), kernel(crate::expressions::binary::BinaryOpKind::Arithmetic( - planner_types::pre_asap::ArithmeticOpKind::Mul, + planner_types::ir::scalar::ArithmeticOpKind::Mul, )), [true, true], )?; @@ -619,7 +620,7 @@ impl Lowering { // Each step evaluates a per-series selection or range function. let (inner, selected) = match child.expect_non_asap() { NonASAPOp::Aggregate { - reduction: planner_types::pre_asap::Reduction::PerEntity, + reduction: planner_types::ir::operator::Reduction::PerEntity, measures, having: None, child: selected, @@ -831,7 +832,7 @@ fn scalar_binary( operand: None, branches, else_expr, - } if matches!(else_expr.as_deref(), Some(ScalarExpr::Literal(planner_types::pre_asap::ScalarValue::Float64(v))) if *v == 0.0) => + } if matches!(else_expr.as_deref(), Some(ScalarExpr::Literal(planner_types::ir::scalar::ScalarValue::Float64(v))) if *v == 0.0) => { let [( ScalarExpr::Compare { @@ -840,7 +841,7 @@ fn scalar_binary( op, semantics: planner_types::ir::ExprSemantics::Promql, }, - ScalarExpr::Literal(planner_types::pre_asap::ScalarValue::Float64(v)), + ScalarExpr::Literal(planner_types::ir::scalar::ScalarValue::Float64(v)), )] = branches.as_slice() else { return Err(invalid("unsupported scalar case")); diff --git a/crates/asap-physical-operators/src/physical_planner/promql_rows.rs b/crates/asap-physical-operators/src/physical_planner/promql_rows.rs index c2da3811b..15e8e8115 100644 --- a/crates/asap-physical-operators/src/physical_planner/promql_rows.rs +++ b/crates/asap-physical-operators/src/physical_planner/promql_rows.rs @@ -4,14 +4,14 @@ use super::*; use planner_types::ir::physical_export::{ compile_physical_asap_dag, compile_physical_asap_dag_with_node_ids, }; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::FieldDataType as SummaryFamilyType; use planner_types::ir::ASAPOp; use planner_types::ir::NonASAPOp; -use planner_types::post_asap::FieldDataType as SummaryFamilyType; -use planner_types::pre_asap::DataType; use std::rc::Rc; /// Not a legal PromQL label name, so it cannot shadow a user label. -pub use planner_types::pre_asap::schema::PROMQL_SERIES_IDENTITY as SERIES_IDENTITY_COLUMN; +pub use planner_types::ir::schema::PROMQL_SERIES_IDENTITY as SERIES_IDENTITY_COLUMN; /// Canonical, reversible identity. JSON object encoding preserves label names, /// empty values and escaping; sorting makes ingestion order irrelevant. @@ -87,9 +87,8 @@ pub fn series_row( pub fn compile_current_series_evaluation( selected: &Rc, ) -> Result { - use planner_types::post_asap::{ - maintained_population::PopulationStatistic, Field as SummaryField, - }; + use planner_types::ir::operator::maintained_population::PopulationStatistic; + use planner_types::ir::schema::Field as SummaryField; // This compiler emits maintained precompute: every summary at ingestion time. let selected = planner_types::ir::apply_materialization_timings( selected, @@ -103,7 +102,7 @@ pub fn compile_current_series_evaluation( // Cut at the population output, preserving all selected heap/evaluation nodes. let populations = dag.nodes.iter().filter(|node| matches!(&node.payload, Payload::ASAP(ASAPOp::MaintainPopulation { population, .. }) - if matches!(population.input, planner_types::post_asap::maintained_population::PopulationInput::CurrentSeries(_)) + if matches!(population.input, planner_types::ir::operator::maintained_population::PopulationInput::CurrentSeries(_)) )).collect::>(); if let [population] = populations.as_slice() { if population @@ -193,12 +192,12 @@ pub fn compile_current_series_evaluation( pub fn compile_rate_ranking( selected: &Rc, ) -> Result<(Rc, CompiledPhysicalDAG), Error> { - use planner_types::post_asap::ExactKind; + use planner_types::ir::schema::ExactKind; fn frontier(node: &Rc) -> Option> { if matches!(&node.operator, LogicalOperator::ASAP(ASAPOp::FinalizeExactAccumulator { child }) if matches!(&child.operator, LogicalOperator::ASAP(ASAPOp::SummaryAgg { family: FieldDataType::ExactAggregate(ExactKind::Rate, _), - reduction: planner_types::pre_asap::Reduction::PerEntity, child: raw, .. + reduction: planner_types::ir::operator::Reduction::PerEntity, child: raw, .. }) if matches!(raw.non_asap(), Some(NonASAPOp::TimeRange { .. })))) { return Some(Rc::clone(node)); @@ -247,7 +246,8 @@ pub fn compile_rate_ranking( pub fn compile_fixed_window_rate_aggregation( dag: &planner_types::ir::physical_export::PhysicalASAPDAG, ) -> Result { - use planner_types::post_asap::{ExactKind, ExecutionTiming, SketchAlgorithm}; + use planner_types::ir::properties::ExecutionTiming; + use planner_types::ir::schema::{ExactKind, SketchAlgorithm}; let sources = dag .nodes .iter() @@ -256,7 +256,7 @@ pub fn compile_fixed_window_rate_aggregation( &n.payload, Payload::ASAP(ASAPOp::SummaryAgg { family: SummaryFamilyType::ExactAggregate(ExactKind::Rate, _), - reduction: planner_types::pre_asap::Reduction::PerEntity, + reduction: planner_types::ir::operator::Reduction::PerEntity, .. }) ) diff --git a/crates/asap-physical-operators/src/physical_planner/promql_values.rs b/crates/asap-physical-operators/src/physical_planner/promql_values.rs index a8a091249..43e5faec1 100644 --- a/crates/asap-physical-operators/src/physical_planner/promql_values.rs +++ b/crates/asap-physical-operators/src/physical_planner/promql_values.rs @@ -1,6 +1,6 @@ //! Physical scalar/vector contracts preserve complete label sets across native computation. use super::*; -use planner_types::post_asap::FieldDataType as SummaryFamilyType; +use planner_types::ir::schema::FieldDataType as SummaryFamilyType; pub fn scalar_schema() -> SchemaRef { crate::operators::vector_binary::value_schema(true) @@ -16,7 +16,7 @@ pub fn matrix_schema() -> SchemaRef { pub fn compile_scalar(value: f64) -> Result { let operator = Operator::scalar( crate::values::Value::Float64(value), - planner_types::pre_asap::DataType::Float64, + planner_types::ir::schema::DataType::Float64, )? .with_output_schema(scalar_schema())?; CompiledPhysicalDAG::from_operators( @@ -226,7 +226,7 @@ pub fn compile_exact_evaluation( lookback_ms: u64, preserve_metric_name: bool, ) -> Result { - use planner_types::post_asap::ExactKind; + use planner_types::ir::schema::ExactKind; let statistic = match &family { SummaryFamilyType::ExactAggregate(kind, _) => match kind { ExactKind::Sum => crate::Statistic::Sum, diff --git a/crates/asap-physical-operators/src/physical_planner/row_values.rs b/crates/asap-physical-operators/src/physical_planner/row_values.rs index 14f3d4813..4c67064a2 100644 --- a/crates/asap-physical-operators/src/physical_planner/row_values.rs +++ b/crates/asap-physical-operators/src/physical_planner/row_values.rs @@ -1,7 +1,7 @@ //! Query-time PromQL value computation over logical row schemas. use super::*; -use planner_types::post_asap::maintained_population::PopulationStatistic; -use planner_types::pre_asap::DataType; +use planner_types::ir::operator::maintained_population::PopulationStatistic; +use planner_types::ir::schema::DataType; /// Aggregate evaluations of a maintained current-series population, as a chain. pub(super) fn population_aggregate( diff --git a/crates/asap-physical-operators/src/runtime/batch_execution.rs b/crates/asap-physical-operators/src/runtime/batch_execution.rs index 733741022..50132f462 100644 --- a/crates/asap-physical-operators/src/runtime/batch_execution.rs +++ b/crates/asap-physical-operators/src/runtime/batch_execution.rs @@ -87,9 +87,8 @@ mod tests { runtime::{Limits, Scope}, values::Value, }; - use planner_types::{ - post_asap::{Field as SummaryField, FieldDataType as SummaryFamilyType, Schema}, - pre_asap::DataType, + use planner_types::ir::schema::{ + DataType, Field as SummaryField, FieldDataType as SummaryFamilyType, Schema, }; use std::sync::Arc; diff --git a/crates/asap-physical-operators/src/sources/mod.rs b/crates/asap-physical-operators/src/sources/mod.rs index 9713c2a6f..621fe692b 100644 --- a/crates/asap-physical-operators/src/sources/mod.rs +++ b/crates/asap-physical-operators/src/sources/mod.rs @@ -7,11 +7,9 @@ use crate::{ Error, }; use futures::{stream, StreamExt}; +use planner_types::ir::operator::Source; +use planner_types::ir::schema::{DataType, FieldDataType as SummaryFamilyType}; use planner_types::ir::{NonASAPOp, OperatorNode}; -use planner_types::{ - post_asap::FieldDataType as SummaryFamilyType, - pre_asap::{DataType, Source}, -}; use std::sync::Arc; /// A bound data source. Metadata must be stable for the lifetime of the binding. diff --git a/crates/asap-physical-operators/src/summary_kernels/count_min_sketch.rs b/crates/asap-physical-operators/src/summary_kernels/count_min_sketch.rs index af0815c25..20f49f092 100644 --- a/crates/asap-physical-operators/src/summary_kernels/count_min_sketch.rs +++ b/crates/asap-physical-operators/src/summary_kernels/count_min_sketch.rs @@ -1,7 +1,7 @@ //! Count-Min Sketch frequency summary over `asap_sketchlib::CountMinSketch`. use crate::{AggregateCore, KernelError, KeyByLabelValues}; use asap_sketchlib::CountMinSketch; -use planner_types::post_asap::SketchStatistic; +use planner_types::ir::schema::SketchStatistic; #[derive(Debug, Clone)] pub struct CountMinSketchAccumulator { @@ -87,7 +87,7 @@ mod tests { #[test] fn bare_count_reads_total_weight() { let bare_count = SketchStatistic::PointCount { - key: planner_types::pre_asap::ColumnRef::SampleValue, + key: planner_types::ir::scalar::ColumnRef::SampleValue, value: None, }; let mut state = CountMinSketchAccumulator::new(2, 1); diff --git a/crates/asap-physical-operators/src/summary_kernels/datasketches_kll.rs b/crates/asap-physical-operators/src/summary_kernels/datasketches_kll.rs index e4ecb56a0..d64607062 100644 --- a/crates/asap-physical-operators/src/summary_kernels/datasketches_kll.rs +++ b/crates/asap-physical-operators/src/summary_kernels/datasketches_kll.rs @@ -1,7 +1,7 @@ //! KLL quantile summary over `asap_sketchlib::KllSketch`. use crate::{AggregateCore, KernelError}; use asap_sketchlib::KllSketch; -use planner_types::post_asap::SketchStatistic; +use planner_types::ir::schema::SketchStatistic; #[derive(Clone)] pub struct DatasketchesKLLAccumulator { diff --git a/crates/asap-physical-operators/src/summary_kernels/dd_sketch.rs b/crates/asap-physical-operators/src/summary_kernels/dd_sketch.rs index e9cdf9d9c..72f786ef5 100644 --- a/crates/asap-physical-operators/src/summary_kernels/dd_sketch.rs +++ b/crates/asap-physical-operators/src/summary_kernels/dd_sketch.rs @@ -1,7 +1,7 @@ //! DDSketch quantile summary over `asap_sketchlib::DdSketch`. use crate::{AggregateCore, KernelError}; use asap_sketchlib::DdSketch; -use planner_types::post_asap::SketchStatistic; +use planner_types::ir::schema::SketchStatistic; #[derive(Debug, Clone)] pub struct DDSketchAccumulator { @@ -55,7 +55,7 @@ impl AggregateCore for DDSketchAccumulator { #[cfg(test)] mod tests { use super::*; - use planner_types::pre_asap::ColumnRef; + use planner_types::ir::scalar::ColumnRef; fn bare_count() -> SketchStatistic { SketchStatistic::PointCount { diff --git a/crates/asap-physical-operators/src/summary_kernels/exact.rs b/crates/asap-physical-operators/src/summary_kernels/exact.rs index d5375f9bf..38713be15 100644 --- a/crates/asap-physical-operators/src/summary_kernels/exact.rs +++ b/crates/asap-physical-operators/src/summary_kernels/exact.rs @@ -2,7 +2,7 @@ use super::increase::IncreaseAccumulator; use crate::Statistic; use crate::{AggregateCore, KeyByLabelValues, Measurement}; -use planner_types::post_asap::{ExactKind, ExactParams, FieldDataType as SummaryFamilyType}; +use planner_types::ir::schema::{ExactKind, ExactParams, FieldDataType as SummaryFamilyType}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/crates/asap-physical-operators/src/summary_kernels/factory.rs b/crates/asap-physical-operators/src/summary_kernels/factory.rs index be819f8a7..f6aca692a 100644 --- a/crates/asap-physical-operators/src/summary_kernels/factory.rs +++ b/crates/asap-physical-operators/src/summary_kernels/factory.rs @@ -6,7 +6,9 @@ use crate::summary_kernels::{ HydraKllSketchAccumulator, }; use crate::{AggregateCore, KeyByLabelValues}; -use planner_types::post_asap::{FieldDataType as SummaryFamilyType, SketchAlgorithm, SketchParams}; +use planner_types::ir::schema::{ + FieldDataType as SummaryFamilyType, SketchAlgorithm, SketchParams, +}; /// Generate the clone-based `AccumulatorUpdater` methods for updaters whose /// inner `acc` field implements `Clone + AggregateCore`. @@ -528,15 +530,15 @@ fn cms_heap_dims(params: &SketchParams) -> (usize, usize, usize) { /// tags participate in this dispatch and unsupported payloads are errors. pub fn create_planner_accumulator( family: &SummaryFamilyType, - input: &planner_types::post_asap::SummaryUpdate, - grouping: &planner_types::post_asap::GroupingStrategy, + input: &planner_types::ir::schema::SummaryUpdate, + grouping: &planner_types::ir::schema::GroupingStrategy, ) -> Result, String> { if input.item.is_some() && matches!( input.weight_domain, - planner_types::post_asap::WeightDomain::NonNegative { + planner_types::ir::schema::WeightDomain::NonNegative { proof: - planner_types::post_asap::NonNegativeWeightProof::ResetAwareCounterDerivative + planner_types::ir::schema::NonNegativeWeightProof::ResetAwareCounterDerivative } ) { @@ -544,7 +546,7 @@ pub fn create_planner_accumulator( } crate::capability::validate_summary_kernel(family, input, grouping)?; - use planner_types::post_asap::GroupingStrategy; + use planner_types::ir::schema::GroupingStrategy; if grouping != &GroupingStrategy::PerSubpopulationInstance { return Err("shared summary grouping requires a supported Planner Hydra kernel".into()); } @@ -711,7 +713,7 @@ impl AccumulatorUpdater for UnivMonUpdater { #[cfg(test)] mod planner_parameter_regression { use super::*; - use planner_types::post_asap::{SketchKind, SummaryInputExpr, SummaryUpdate}; + use planner_types::ir::schema::{SketchKind, SummaryInputExpr, SummaryUpdate}; // Planner width is the bucket count; depth is the independent hash-row count. #[test] @@ -754,7 +756,7 @@ mod planner_parameter_regression { ); let update = SummaryUpdate { item: Some(SummaryInputExpr::Column( - planner_types::pre_asap::ColumnRef::Named("host".into()), + planner_types::ir::scalar::ColumnRef::Named("host".into()), )), weight: SummaryInputExpr::Constant(1.0), weight_domain: Default::default(), diff --git a/crates/asap-physical-operators/src/summary_kernels/hll_sketch.rs b/crates/asap-physical-operators/src/summary_kernels/hll_sketch.rs index 993f9d9b6..166d8c2db 100644 --- a/crates/asap-physical-operators/src/summary_kernels/hll_sketch.rs +++ b/crates/asap-physical-operators/src/summary_kernels/hll_sketch.rs @@ -1,7 +1,7 @@ //! HyperLogLog distinct-count summary over `asap_sketchlib::HllSketch`. use crate::{AggregateCore, KernelError}; use asap_sketchlib::{HllSketch, HllVariant}; -use planner_types::post_asap::SketchStatistic; +use planner_types::ir::schema::SketchStatistic; #[derive(Debug, Clone)] pub struct HllSketchAccumulator { diff --git a/crates/asap-physical-operators/src/summary_kernels/traits.rs b/crates/asap-physical-operators/src/summary_kernels/traits.rs index 46e2c7f86..8fd0b52d1 100644 --- a/crates/asap-physical-operators/src/summary_kernels/traits.rs +++ b/crates/asap-physical-operators/src/summary_kernels/traits.rs @@ -1,4 +1,4 @@ -use planner_types::post_asap::SketchStatistic; +use planner_types::ir::schema::SketchStatistic; pub type KernelError = Box; @@ -53,7 +53,7 @@ mod tests { .unwrap(); dd.inner.update(3.0); let count = SketchStatistic::PointCount { - key: planner_types::pre_asap::ColumnRef::SampleValue, + key: planner_types::ir::scalar::ColumnRef::SampleValue, value: None, }; assert_eq!(state.estimate(&count).unwrap(), 1.0); diff --git a/crates/asap-physical-operators/src/summary_kernels/univmon.rs b/crates/asap-physical-operators/src/summary_kernels/univmon.rs index 23114ab1b..54904282e 100644 --- a/crates/asap-physical-operators/src/summary_kernels/univmon.rs +++ b/crates/asap-physical-operators/src/summary_kernels/univmon.rs @@ -2,7 +2,8 @@ use crate::AggregateCore; use asap_sketchlib::{DataInput, UnivMon}; -use planner_types::{post_asap::SketchStatistic, pre_asap::ColumnRef}; +use planner_types::ir::scalar::ColumnRef; +use planner_types::ir::schema::SketchStatistic; type Error = Box; diff --git a/crates/asap-physical-operators/src/summary_kernels/weighted_frequency.rs b/crates/asap-physical-operators/src/summary_kernels/weighted_frequency.rs index 7c1122305..8af54a37b 100644 --- a/crates/asap-physical-operators/src/summary_kernels/weighted_frequency.rs +++ b/crates/asap-physical-operators/src/summary_kernels/weighted_frequency.rs @@ -41,9 +41,9 @@ pub struct WeightedFrequency { } impl WeightedFrequency { pub(crate) fn configuration( - kind: &planner_types::post_asap::SketchKind, + kind: &planner_types::ir::schema::SketchKind, ) -> Result<(FrequencyAlgorithm, usize, usize, usize), Error> { - use planner_types::post_asap::{SketchAlgorithm as A, SketchParams as P}; + use planner_types::ir::schema::{SketchAlgorithm as A, SketchParams as P}; let (algorithm, width, depth, capacity) = match (kind.algorithm(), kind.params()) { ( A::CmsWithHeap, diff --git a/crates/asap-physical-operators/src/values.rs b/crates/asap-physical-operators/src/values.rs index 41640b7b6..9feb0fac3 100644 --- a/crates/asap-physical-operators/src/values.rs +++ b/crates/asap-physical-operators/src/values.rs @@ -1,9 +1,8 @@ //! Runtime values preserve Planner schemas; summary states are typed values too. use crate::AggregateCore; use crate::Error; -use planner_types::{ - post_asap::{Field as SummaryField, FieldDataType as SummaryFamilyType, Schema}, - pre_asap::DataType, +use planner_types::ir::schema::{ + DataType, Field as SummaryField, FieldDataType as SummaryFamilyType, Schema, }; use std::{cmp::Ordering, sync::Arc}; /// Shared ownership of schema metadata; the field model is identical at planning @@ -267,7 +266,7 @@ fn validate_state(family: &SummaryFamilyType, state: &dyn AggregateCore) -> Resu count_min_sketch::CountMinSketchAccumulator, datasketches_kll::DatasketchesKLLAccumulator, dd_sketch::DDSketchAccumulator, exact::ExactAccumulator, hll_sketch::HllSketchAccumulator, }; - use planner_types::post_asap::SketchParams; + use planner_types::ir::schema::SketchParams; validate_family(family)?; let valid = match family { SummaryFamilyType::Sketch(kind, _) @@ -364,7 +363,7 @@ pub(crate) fn plain(schema: &SchemaRef, column: usize) -> Result<(&DataType, boo mod weighted_state_tests { use super::*; use crate::summary_kernels::weighted_frequency::{FrequencyAlgorithm, WeightedFrequency}; - use planner_types::post_asap::{SketchAlgorithm, SketchKind, SketchParams}; + use planner_types::ir::schema::{SketchAlgorithm, SketchKind, SketchParams}; // A state cannot acquire a different family or shape merely by relabeling its batch. #[test] diff --git a/crates/asap-physical-operators/tests/blocking_resources.rs b/crates/asap-physical-operators/tests/blocking_resources.rs index 09cee7a4e..fd9091a79 100644 --- a/crates/asap-physical-operators/tests/blocking_resources.rs +++ b/crates/asap-physical-operators/tests/blocking_resources.rs @@ -7,16 +7,15 @@ use asap_physical_operators::{ Error, }; use futures::{executor::block_on, FutureExt, StreamExt}; +use planner_types::ir::operator::JoinKind; +use planner_types::ir::scalar::ScalarValue; +use planner_types::ir::schema::{DataType, Field, FieldDataType}; use planner_types::ir::Predicate; use planner_types::ir::ScalarExpr; -use planner_types::{ - post_asap::{Field, FieldDataType}, - pre_asap::{DataType, JoinKind, ScalarValue}, -}; use std::sync::Arc; fn schema(width: usize) -> SchemaRef { - Arc::new(planner_types::pre_asap::Schema { + Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: (0..width) @@ -188,9 +187,9 @@ fn cooperative_sort_preserves_ties_across_chunks() { // The integrated weighted-summary path obeys the same cooperative cancellation contract. #[test] fn weighted_summary_build_yields_within_a_batch() { - use planner_types::post_asap::{SketchAlgorithm, SketchKind, SketchParams}; + use planner_types::ir::schema::{SketchAlgorithm, SketchKind, SketchParams}; - let input = Arc::new(planner_types::pre_asap::Schema { + let input = Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![ diff --git a/crates/asap-physical-operators/tests/current_series_heap.rs b/crates/asap-physical-operators/tests/current_series_heap.rs index 1f5d5ab2d..19dab705e 100644 --- a/crates/asap-physical-operators/tests/current_series_heap.rs +++ b/crates/asap-physical-operators/tests/current_series_heap.rs @@ -12,11 +12,12 @@ use asap_physical_operators::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::physical_export::PhysicalASAPOperatorPayload; -use planner_types::{post_asap::*, pre_asap::DataType}; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::*; use std::{collections::BTreeMap, sync::Arc}; fn schema() -> Arc { - Arc::new(planner_types::pre_asap::Schema { + Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: [ @@ -171,7 +172,7 @@ fn spatial_heap_ranks_latest_values_in_independent_runs() { }; let family = FieldDataType::Sketch(SketchKind::new(algorithm, params), Default::default()); let build = Operator::keyed_summary_build(schema(), family, 1, vec![3], vec![2]).unwrap(); - let output = Arc::new(planner_types::pre_asap::Schema { + let output = Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![ diff --git a/crates/asap-physical-operators/tests/deployment.rs b/crates/asap-physical-operators/tests/deployment.rs index 72e0503f1..9b00522cd 100644 --- a/crates/asap-physical-operators/tests/deployment.rs +++ b/crates/asap-physical-operators/tests/deployment.rs @@ -1,9 +1,9 @@ //! Exercise the public library without a backend server, store, or scheduler. -use asap_physical_operators::planner::{ - post_asap::{ +use asap_physical_operators::planner::ir::{ + scalar::ColumnRef, + schema::{ FieldDataType, GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate, }, - pre_asap::ColumnRef, }; use asap_physical_operators::{factory::create_planner_accumulator, AggregateCore}; @@ -29,7 +29,7 @@ fn build(values: &[f64]) -> Box { fn read(state: &dyn AggregateCore) -> f64 { state .estimate( - &asap_physical_operators::planner::post_asap::SketchStatistic::Quantile { q: 0.5 }, + &asap_physical_operators::planner::ir::schema::SketchStatistic::Quantile { q: 0.5 }, ) .unwrap() } @@ -64,7 +64,7 @@ fn invalid_kll_parameters_are_rejected_at_binding() { // a packed-wire column-bit budget must not be imposed on this constructor. #[test] fn native_count_sketch_dimensions_are_not_packed_wire_dimensions() { - use asap_physical_operators::planner::post_asap::SummaryInputExpr; + use asap_physical_operators::planner::ir::schema::SummaryInputExpr; use asap_physical_operators::KeyByLabelValues; let family = FieldDataType::Sketch( SketchKind::new( diff --git a/crates/asap-physical-operators/tests/deployment_computation.rs b/crates/asap-physical-operators/tests/deployment_computation.rs index 2f8f98b17..6f48d4283 100644 --- a/crates/asap-physical-operators/tests/deployment_computation.rs +++ b/crates/asap-physical-operators/tests/deployment_computation.rs @@ -10,8 +10,9 @@ use asap_physical_operators::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::physical_export::{PhysicalASAPDAG, PhysicalASAPOperatorPayload}; +use planner_types::ir::schema::*; use planner_types::ir::ASAPOp; -use planner_types::{post_asap::*, types::AccuracyTarget, workload::*}; +use planner_types::{types::AccuracyTarget, workload::*}; use std::{collections::BTreeMap, rc::Rc, sync::Arc}; fn lower(query: &str) -> Rc { @@ -84,7 +85,7 @@ fn raw_inputs(dag: &PhysicalASAPDAG) -> Vec<(u64, Arc, String)> { let n = dag.nodes.iter().find(|n| n.id == id)?; if let PhysicalASAPOperatorPayload::NonASAP( planner_types::ir::NonASAPOp::Scan { - source: planner_types::pre_asap::Source::TimeSeries { metric }, + source: planner_types::ir::operator::Source::TimeSeries { metric }, .. }, ) = &n.payload @@ -331,7 +332,7 @@ fn exact_count_finalizes_to_declared_float_value() { /// `dag` with its Binary operator replaced by `kind`. fn with_kind( mut dag: PhysicalASAPDAG, - kind: planner_types::pre_asap::BinaryOpKind, + kind: planner_types::ir::operator::BinaryOpKind, bool_result: bool, ) -> PhysicalASAPDAG { for node in &mut dag.nodes { @@ -374,7 +375,8 @@ fn grouped_comparisons_filter_or_return_bool() { // drops the metric name; a filter keeps the surviving left value. #[test] fn per_series_comparisons_filter_or_return_bool() { - use planner_types::pre_asap::{BinaryOpKind::*, CompareOpKind::*}; + use planner_types::ir::operator::BinaryOpKind::*; + use planner_types::ir::scalar::CompareOpKind::*; let samples = counter("a", "api", 10., 10.) .chain(counter("a", "db", 10., 10.)) @@ -536,7 +538,7 @@ fn per_series_scalar_arithmetic_rejects_label_sets_equal_without_the_name() { fn with_vector_match( mut dag: PhysicalASAPDAG, - kind: planner_types::pre_asap::VectorMatchKind, + kind: planner_types::ir::operator::VectorMatchKind, labels: &[&str], ) -> PhysicalASAPDAG { for node in &mut dag.nodes { @@ -545,7 +547,7 @@ fn with_vector_match( .. }) = &mut node.payload { - operator.vector_match = Some(planner_types::pre_asap::VectorMatch { + operator.vector_match = Some(planner_types::ir::operator::VectorMatch { kind: kind.clone(), labels: labels.iter().map(|l| l.to_string()).collect(), grouping: None, @@ -559,7 +561,7 @@ fn with_vector_match( // the result's labels; a duplicate match group on either side is an error. #[test] fn per_series_vector_matching_follows_on_and_ignoring() { - use planner_types::pre_asap::VectorMatchKind; + use planner_types::ir::operator::VectorMatchKind; let samples = counter("a", "api", 10., 10.) .chain(counter("b", "api", 5., 5.)) .chain(counter("b", "db", 5., 5.)) diff --git a/crates/asap-physical-operators/tests/physical_dag.rs b/crates/asap-physical-operators/tests/physical_dag.rs index fdb6027e1..14a0ebfae 100644 --- a/crates/asap-physical-operators/tests/physical_dag.rs +++ b/crates/asap-physical-operators/tests/physical_dag.rs @@ -12,17 +12,15 @@ use planner_types::ir::physical_export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::{ExactKind, ExactParams, Field, FieldDataType}; use planner_types::ir::ASAPOp; use planner_types::ir::BinaryOperator; use planner_types::ir::NonASAPOp; use planner_types::ir::ScalarExpr; -use planner_types::{ - post_asap::{ExactKind, ExactParams, Field, FieldDataType}, - pre_asap::DataType, -}; use std::sync::Arc; fn schema(fields: &[(&str, DataType, bool)]) -> SchemaRef { - Arc::new(planner_types::pre_asap::Schema { + Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: fields @@ -307,7 +305,7 @@ fn binding_rejects_unsupported_operations() { sum.schema(), 0, asap_physical_operators::operators::SummaryEvaluation::Sketch( - planner_types::post_asap::SketchStatistic::Quantile { q: 0.5 } + planner_types::ir::schema::SketchStatistic::Quantile { q: 0.5 } ) ) .is_err()); @@ -317,7 +315,7 @@ fn binding_rejects_unsupported_operations() { // KLL is one family example: precomputation changes input sources, not operators. #[test] fn kll_raw_partial_and_precomputed_are_native_dags() { - use planner_types::post_asap::{GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams}; + use planner_types::ir::schema::{GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams}; let input = schema(&[("value", DataType::Float64, false)]); let family = FieldDataType::Sketch( @@ -409,7 +407,7 @@ fn kll_raw_partial_and_precomputed_are_native_dags() { state.clone(), 0, asap_physical_operators::operators::SummaryEvaluation::Sketch( - planner_types::post_asap::SketchStatistic::Quantile { q: 0.5 }, + planner_types::ir::schema::SketchStatistic::Quantile { q: 0.5 }, ), ) .unwrap(), @@ -432,7 +430,7 @@ fn exact_state_and_family_validation() { let family = FieldDataType::ExactAggregate(ExactKind::Sum, ExactParams::Sum); let mut acc = ExactAccumulator::new(family.clone(), false).unwrap(); acc.update(None, 7., 0); - let schema = Arc::new(planner_types::pre_asap::Schema { + let schema = Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![Field { @@ -494,10 +492,8 @@ fn exact_state_and_family_validation() { #[test] fn bind_post_asap_before_execution() { use asap_physical_operators::dag::planner::bind; - use planner_types::{ - post_asap::ExecutionDataState, - pre_asap::{ArithmeticOpKind, ScalarValue}, - }; + use planner_types::ir::properties::ExecutionDataState; + use planner_types::ir::scalar::{ArithmeticOpKind, ScalarValue}; use std::collections::BTreeMap; let schema = schema(&[("value", DataType::Float64, false)]); let node = |id, payload| PhysicalASAPDAGNode { @@ -513,7 +509,7 @@ fn bind_post_asap_before_execution() { 0, PhysicalASAPOperatorPayload::NonASAP(NonASAPOp::Values { rows: vec![vec![planner_types::ir::ScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Float64(1.), + planner_types::ir::scalar::ScalarValue::Float64(1.), )]], schema: (*schema).clone(), }), @@ -607,7 +603,7 @@ fn empty_exact_count_is_an_integer_state_evaluation() { #[test] fn source_batches_must_match_the_bound_schema() { use asap_physical_operators::dag::{self, PhysicalOperator}; - use planner_types::post_asap::ExecutionDataState; + use planner_types::ir::properties::ExecutionDataState; use std::{cell::Cell, collections::BTreeMap, rc::Rc}; struct WrongSource { schema: SchemaRef, @@ -645,7 +641,7 @@ fn source_batches_must_match_the_bound_schema() { id: 0, payload: PhysicalASAPOperatorPayload::NonASAP(NonASAPOp::Values { rows: vec![vec![planner_types::ir::ScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Float64(1.), + planner_types::ir::scalar::ScalarValue::Float64(1.), )]], schema: (*expected).clone(), }), @@ -713,10 +709,10 @@ fn extrema_preserve_numeric_values_in_the_presence_of_nan() { #[test] fn planner_semijoin_sort_limit_contract_at_both_phases() { use asap_physical_operators::dag::planner::{bind, Source}; - use planner_types::{ - post_asap::*, - pre_asap::{CompareOpKind, GroupKeys, JoinKind}, - }; + use planner_types::ir::operator::{GroupKeys, JoinKind}; + use planner_types::ir::properties::*; + use planner_types::ir::scalar::CompareOpKind; + use planner_types::ir::schema::*; use std::collections::BTreeMap; let rows_schema = schema(&[ ("group", DataType::Utf8, false), @@ -750,7 +746,7 @@ fn planner_semijoin_sort_limit_contract_at_both_phases() { 0, PhysicalASAPOperatorPayload::NonASAP(NonASAPOp::Values { rows: vec![vec![planner_types::ir::ScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Float64(0.), + planner_types::ir::scalar::ScalarValue::Float64(0.), )]], schema: (*rows_schema).clone(), }), @@ -760,7 +756,7 @@ fn planner_semijoin_sort_limit_contract_at_both_phases() { 1, PhysicalASAPOperatorPayload::NonASAP(NonASAPOp::Values { rows: vec![vec![planner_types::ir::ScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Float64(0.), + planner_types::ir::scalar::ScalarValue::Float64(0.), )]], schema: (*keys_schema).clone(), }), @@ -875,7 +871,7 @@ fn planner_semijoin_sort_limit_contract_at_both_phases() { #[test] fn planner_expressions_preserve_collection_and_nullable_types() { use asap_physical_operators::dag::expressions::CompiledExpression; - use planner_types::pre_asap::{CompareOpKind, ScalarValue}; + use planner_types::ir::scalar::{CompareOpKind, ScalarValue}; let input_schema = schema(&[( "items", @@ -951,8 +947,9 @@ fn planner_expressions_preserve_collection_and_nullable_types() { // Outer, semi and anti joins share Planner predicates and preserve SQL null behavior. #[test] fn native_relational_join_kinds_preserve_unmatched_rows() { + use planner_types::ir::operator::JoinKind; + use planner_types::ir::scalar::CompareOpKind; use planner_types::ir::Predicate; - use planner_types::pre_asap::{CompareOpKind, JoinKind}; let input = schema(&[("key", DataType::Int64, true)]); let predicate = Predicate(ScalarExpr::Compare { @@ -1033,7 +1030,7 @@ fn weighted_rate_topk_preserves_partitions_fractional_scores_and_evaluation_scop } } fn assert_weighted_rate_topk(count_sketch: bool) { - use planner_types::post_asap::{SketchAlgorithm, SketchKind, SketchParams}; + use planner_types::ir::schema::{SketchAlgorithm, SketchKind, SketchParams}; let raw = schema(&[ ("service", DataType::Utf8, false), @@ -1065,7 +1062,7 @@ fn assert_weighted_rate_topk(count_sketch: bool) { } let rates = Operator::window( raw.clone(), - planner_types::pre_asap::AggIntent::Rate, + planner_types::ir::operator::AggIntent::Rate, 3, 4, vec![0, 1, 2], @@ -1159,15 +1156,14 @@ fn grouped_temporal_schema_compiles_and_executes_topk() { compile_node, CompiledPhysicalDAG, InputContract, Source, }; use planner_types::ir::physical_export::{PhysicalASAPDAGNode, PhysicalASAPOperatorPayload}; - use planner_types::post_asap::ExecutionDataState; + use planner_types::ir::properties::ExecutionDataState; - use planner_types::pre_asap::{ - aggregate_output_schema, AggIntent, GroupKeys, Reduction as IrReduction, Schema as IrSchema, - }; + use planner_types::ir::operator::{AggIntent, GroupKeys, Reduction as IrReduction}; + use planner_types::ir::schema::{aggregate_output_schema, Schema as IrSchema}; let grouped = IrSchema::new(vec![ - planner_types::pre_asap::Field::plain("job", DataType::Utf8, false), - planner_types::pre_asap::Field::plain("sum", DataType::Float64, false), + planner_types::ir::schema::Field::plain("job", DataType::Utf8, false), + planner_types::ir::schema::Field::plain("sum", DataType::Float64, false), ]); let output = aggregate_output_schema( &grouped, @@ -1269,10 +1265,10 @@ fn certified_pruning_rejects_missing_authoritative_values_after_recovery() { use asap_physical_operators::physical_planner::{ compile_node, CompiledPhysicalDAG, InputContract, Source, }; - use planner_types::{ - post_asap::*, - pre_asap::{CompareOpKind, JoinKind}, - }; + use planner_types::ir::operator::JoinKind; + use planner_types::ir::properties::*; + use planner_types::ir::scalar::CompareOpKind; + use planner_types::ir::schema::*; use std::collections::BTreeMap; let schema = schema(&[("key", DataType::Utf8, false)]); for certified in [false, true] { @@ -1381,10 +1377,10 @@ fn compiled_ingestion_binary_preserves_alignment_and_rejects_missing_updates() { use asap_physical_operators::physical_planner::{ compile_node, CompiledPhysicalDAG, InputContract, Source, }; - use planner_types::{ - post_asap::*, - pre_asap::{ArithmeticOpKind, BinaryOpKind}, - }; + use planner_types::ir::operator::BinaryOpKind; + use planner_types::ir::properties::*; + use planner_types::ir::scalar::ArithmeticOpKind; + use planner_types::ir::schema::*; use std::collections::BTreeMap; let input = schema(&[ ("population", DataType::Utf8, false), diff --git a/crates/asap-physical-operators/tests/physical_plan_recovery.rs b/crates/asap-physical-operators/tests/physical_plan_recovery.rs index e755090e6..9dca664b9 100644 --- a/crates/asap-physical-operators/tests/physical_plan_recovery.rs +++ b/crates/asap-physical-operators/tests/physical_plan_recovery.rs @@ -4,14 +4,11 @@ use asap_physical_operators::{ operators::{Operator, SortKey}, physical_planner::{CompiledPhysicalDAG, InputContract}, }; -use planner_types::{ - post_asap::{Field, FieldDataType}, - pre_asap::DataType, -}; +use planner_types::ir::schema::{DataType, Field, FieldDataType}; use std::{collections::BTreeMap, sync::Arc}; fn sorted() -> CompiledPhysicalDAG { - let schema = Arc::new(planner_types::pre_asap::Schema { + let schema = Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![Field { diff --git a/crates/asap-physical-operators/tests/physical_semantics.rs b/crates/asap-physical-operators/tests/physical_semantics.rs index 20f02f76e..be2017cc1 100644 --- a/crates/asap-physical-operators/tests/physical_semantics.rs +++ b/crates/asap-physical-operators/tests/physical_semantics.rs @@ -9,18 +9,18 @@ use asap_physical_operators::{ values::{Batch, SchemaRef, Value}, }; use futures::{executor::block_on, StreamExt}; +use planner_types::ir::operator::JoinKind; use planner_types::ir::physical_export::{PhysicalASAPDAGNode, PhysicalASAPOperatorPayload}; +use planner_types::ir::scalar::CompareOpKind; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::{Field, FieldDataType}; use planner_types::ir::NonASAPOp; use planner_types::ir::Predicate; use planner_types::ir::ScalarExpr; -use planner_types::{ - post_asap::{Field, FieldDataType}, - pre_asap::{CompareOpKind, DataType, JoinKind}, -}; use std::sync::Arc; fn schema(fields: &[(&str, DataType, bool)]) -> SchemaRef { - Arc::new(planner_types::pre_asap::Schema { + Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: fields @@ -348,22 +348,21 @@ fn projection_rejects_expression_bound_to_another_schema() { #[test] fn global_extrema_bind_with_planner_derived_schema() { use asap_physical_operators::physical_planner::compile_node; - use planner_types::{ - post_asap::*, - pre_asap::{AggIntent, GroupKeys, Reduction as PlanReduction}, - }; + use planner_types::ir::operator::{AggIntent, GroupKeys, Reduction as PlanReduction}; + use planner_types::ir::properties::*; + use planner_types::ir::schema::*; let input = schema(&[("v", DataType::Int64, false)]); for measure in [ AggIntent::Min { col: Some(0) }, AggIntent::Max { col: Some(0) }, ] { let planner_input = - planner_types::pre_asap::Schema::new(vec![planner_types::pre_asap::Field::plain( + planner_types::ir::schema::Schema::new(vec![planner_types::ir::schema::Field::plain( "v", DataType::Int64, false, )]); - let derived = planner_types::pre_asap::aggregate_output_schema( + let derived = planner_types::ir::schema::aggregate_output_schema( &planner_input, &PlanReduction::Reduce(GroupKeys::by(vec![])), std::slice::from_ref(&measure), @@ -554,7 +553,7 @@ fn boolean_truth_tables_agree_between_expression_paths() { // Partial/final execution must agree with one build for an uncompacted KLL population. #[test] fn kll_partial_merge_and_multiple_evaluations_preserve_population() { - use planner_types::post_asap::{SketchAlgorithm, SketchKind, SketchParams}; + use planner_types::ir::schema::{SketchAlgorithm, SketchKind, SketchParams}; let input = schema(&[("v", DataType::Float64, false)]); let family = FieldDataType::Sketch( @@ -603,7 +602,7 @@ fn kll_partial_merge_and_multiple_evaluations_preserve_population() { state.clone(), 0, asap_physical_operators::operators::SummaryEvaluation::Sketch( - planner_types::post_asap::SketchStatistic::Quantile { q }, + planner_types::ir::schema::SketchStatistic::Quantile { q }, ), ) .unwrap(), @@ -672,7 +671,7 @@ fn zero_column_output_obeys_memory_limit() { #[test] fn empty_exact_summary_extrema_agree_with_ordinary_aggregation() { use asap_physical_operators::Statistic; - use planner_types::post_asap::{ExactKind, ExactParams}; + use planner_types::ir::schema::{ExactKind, ExactParams}; let input = schema(&[("v", DataType::Float64, false)]); for (kind, params, statistic) in [ diff --git a/crates/asap-physical-operators/tests/plan_properties.rs b/crates/asap-physical-operators/tests/plan_properties.rs index ab488162d..fd16f96d1 100644 --- a/crates/asap-physical-operators/tests/plan_properties.rs +++ b/crates/asap-physical-operators/tests/plan_properties.rs @@ -7,10 +7,8 @@ use asap_physical_operators::{ values::{Batch, SchemaRef}, Error, }; -use planner_types::{ - post_asap::{Field, FieldDataType}, - pre_asap::{DataType, Schema, Source}, -}; +use planner_types::ir::operator::Source; +use planner_types::ir::schema::{DataType, Field, FieldDataType, Schema}; use std::sync::{ atomic::{AtomicUsize, Ordering}, Arc, @@ -35,7 +33,7 @@ impl RawSource for DeclaredSource { // A blocking parent must reject unknown and unbounded Scan inputs without opening a reader. #[test] fn blocking_inputs_require_an_explicit_finite_source() { - let schema = Arc::new(planner_types::pre_asap::Schema { + let schema = Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![Field { @@ -71,7 +69,7 @@ fn blocking_inputs_require_an_explicit_finite_source() { &planner_types::ir::OperatorNode::new_shared(planner_types::ir::Operator::NonASAP( planner_types::ir::NonASAPOp::Scan { source: identity, - schema: Schema::new(vec![planner_types::pre_asap::Field::plain( + schema: Schema::new(vec![planner_types::ir::schema::Field::plain( "v", DataType::Int64, false, @@ -126,11 +124,11 @@ fn blocking_inputs_require_an_explicit_finite_source() { fn summary_capability_levels_are_distinct() { use asap_physical_operators::{ capability::{validate_native_family, validate_sketch_evaluation, validate_summary_kernel}, - planner::post_asap::SketchStatistic, + planner::ir::schema::SketchStatistic, }; - use planner_types::{ - post_asap::{GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate}, - pre_asap::ColumnRef, + use planner_types::ir::scalar::ColumnRef; + use planner_types::ir::schema::{ + GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate, }; let grouping = GroupingStrategy::default(); let cms = FieldDataType::Sketch( @@ -144,10 +142,10 @@ fn summary_capability_levels_are_distinct() { grouping.clone(), ); let update = SummaryUpdate { - item: Some(planner_types::post_asap::SummaryInputExpr::Column( + item: Some(planner_types::ir::schema::SummaryInputExpr::Column( ColumnRef::Named("host".into()), )), - weight: planner_types::post_asap::SummaryInputExpr::Constant(1.0), + weight: planner_types::ir::schema::SummaryInputExpr::Constant(1.0), weight_domain: Default::default(), }; assert!(validate_summary_kernel(&cms, &update, &grouping).is_ok()); diff --git a/crates/asap-physical-operators/tests/planspace_series_identity_heap.rs b/crates/asap-physical-operators/tests/planspace_series_identity_heap.rs index e33de530f..0b616a725 100644 --- a/crates/asap-physical-operators/tests/planspace_series_identity_heap.rs +++ b/crates/asap-physical-operators/tests/planspace_series_identity_heap.rs @@ -16,7 +16,8 @@ use asap_physical_operators::physical_planner::promql_rows::{ compile_current_series_evaluation, SERIES_IDENTITY_COLUMN, }; use planner_types::{ - post_asap::*, + ir::properties::*, + ir::schema::*, types::AccuracyTarget, workload::{ AccuracyRequirement, BatchEntry, DataWorkload, DurationMs, Evidence as WorkloadEvidence, diff --git a/crates/asap-physical-operators/tests/precompute_candidates.rs b/crates/asap-physical-operators/tests/precompute_candidates.rs index b30de08a8..0f5897dff 100644 --- a/crates/asap-physical-operators/tests/precompute_candidates.rs +++ b/crates/asap-physical-operators/tests/precompute_candidates.rs @@ -15,8 +15,10 @@ use asap_physical_operators::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::physical_export::{PhysicalASAPDAG, PhysicalASAPOperatorPayload}; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::*; use planner_types::ir::ASAPOp; -use planner_types::{post_asap::*, pre_asap::DataType, types::AccuracyTarget, workload::*}; +use planner_types::{types::AccuracyTarget, workload::*}; use std::{collections::BTreeMap, sync::Arc}; fn grouped_rate_space() -> asap_aware_mapping::CandidateLogicalASAPDAGs<&'static str> { diff --git a/crates/asap-physical-operators/tests/precompute_population.rs b/crates/asap-physical-operators/tests/precompute_population.rs index f156d6407..1065d595c 100644 --- a/crates/asap-physical-operators/tests/precompute_population.rs +++ b/crates/asap-physical-operators/tests/precompute_population.rs @@ -8,23 +8,24 @@ use asap_physical_operators::{ Statistic, }; use futures::{executor::block_on, StreamExt}; +use planner_types::ir::operator::{BinaryOpKind, GroupKeys, Reduction}; use planner_types::ir::physical_export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::properties::*; +use planner_types::ir::scalar::{ArithmeticOpKind, ColumnRef}; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::*; use planner_types::ir::ASAPOp; use planner_types::ir::BinaryOperator; -use planner_types::{ - post_asap::*, - pre_asap::{ArithmeticOpKind, BinaryOpKind, ColumnRef, DataType, GroupKeys, Reduction}, -}; use std::{collections::BTreeMap, sync::Arc}; // Typed series identity survives finalization and derived precompute through population metadata. #[test] fn finalized_shared_panes_rebuild_one_global_summary_after_recovery() { let family = FieldDataType::ExactAggregate(ExactKind::Sum, ExactParams::Sum); - let schema = |dtype| planner_types::pre_asap::Schema { + let schema = |dtype| planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![Field { @@ -46,7 +47,7 @@ fn finalized_shared_panes_rebuild_one_global_summary_after_recovery() { value_schema.time_index = Some(1); value_schema.fields.push(Field { table: None, - name: planner_types::pre_asap::schema::PROMQL_SERIES_IDENTITY.into(), + name: planner_types::ir::schema::PROMQL_SERIES_IDENTITY.into(), dtype: FieldDataType::Plain(DataType::Utf8), nullable: false, }); @@ -234,7 +235,7 @@ fn finalized_shared_panes_rebuild_one_global_summary_after_recovery() { } fn logical_schema(family: FieldDataType) -> Schema { - planner_types::pre_asap::Schema { + planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![Field { @@ -364,9 +365,9 @@ fn ingestion_context(limits: Limits) -> RunContext { } fn sum_state(value: f64) -> Arc { let mut state = asap_physical_operators::summary_kernels::exact::ExactAccumulator::new( - planner_types::post_asap::FieldDataType::ExactAggregate( - planner_types::post_asap::ExactKind::Sum, - planner_types::post_asap::ExactParams::Sum, + planner_types::ir::schema::FieldDataType::ExactAggregate( + planner_types::ir::schema::ExactKind::Sum, + planner_types::ir::schema::ExactParams::Sum, ), false, ) diff --git a/crates/asap-physical-operators/tests/promql_binary.rs b/crates/asap-physical-operators/tests/promql_binary.rs index 41d8802fc..92cc58540 100644 --- a/crates/asap-physical-operators/tests/promql_binary.rs +++ b/crates/asap-physical-operators/tests/promql_binary.rs @@ -6,20 +6,21 @@ use asap_physical_operators::{ values::{Batch, SchemaRef, Value}, }; use futures::{executor::block_on, StreamExt}; +use planner_types::ir::operator::BinaryOpKind; use planner_types::ir::physical_export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::properties::ExecutionDataState; +use planner_types::ir::scalar::ArithmeticOpKind; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::{Field, FieldDataType}; use planner_types::ir::ASAPOp; use planner_types::ir::BinaryOperator; -use planner_types::{ - post_asap::{ExecutionDataState, Field, FieldDataType}, - pre_asap::{ArithmeticOpKind, BinaryOpKind, DataType}, -}; use std::{collections::BTreeMap, sync::Arc}; fn schema() -> SchemaRef { - Arc::new(planner_types::pre_asap::Schema { + Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![ @@ -164,7 +165,7 @@ fn duplicate_matching_identity_is_rejected() { #[test] fn scalar_broadcast_and_bool_comparison_are_distinct() { use asap_physical_operators::physical_planner::promql_values; - use planner_types::pre_asap::CompareOpKind; + use planner_types::ir::scalar::CompareOpKind; for return_bool in [false, true] { let physical_dag = promql_values::compile_binary( &asap_physical_operators::expressions::binary::BinaryOperator::from_logical( @@ -301,7 +302,7 @@ fn binary_obeys_memory_and_cancellation() { fn label_map_bool_comparison_drops_the_name() { let program = program_for_bool( BinaryOperator { - kind: BinaryOpKind::Compare(planner_types::pre_asap::CompareOpKind::Gt), + kind: BinaryOpKind::Compare(planner_types::ir::scalar::CompareOpKind::Gt), vector_match: None, checked_relative_division: false, checked_finite_division: false, @@ -332,17 +333,18 @@ fn stored_series_evaluations_support_filters_and_sets() { use asap_physical_operators::{ physical_planner::compile, summary_kernels::exact::ExactAccumulator, }; - use planner_types::post_asap::*; - use planner_types::pre_asap::{ - schema::PROMQL_SERIES_IDENTITY, CompareOpKind, PromQLVectorSetOpKind, - }; + use planner_types::ir::operator::PromQLVectorSetOpKind; + use planner_types::ir::properties::*; + use planner_types::ir::scalar::CompareOpKind; + use planner_types::ir::schema::PROMQL_SERIES_IDENTITY; + use planner_types::ir::schema::*; for (exact_kind, params) in [ (ExactKind::Sum, ExactParams::Sum), (ExactKind::Count, ExactParams::Count), ] { let family = FieldDataType::ExactAggregate(exact_kind.clone(), params); - let state_schema = Arc::new(planner_types::pre_asap::Schema { + let state_schema = Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![ diff --git a/crates/asap-physical-operators/tests/promql_fallback.rs b/crates/asap-physical-operators/tests/promql_fallback.rs index 49a8a31f8..f7899f46c 100644 --- a/crates/asap-physical-operators/tests/promql_fallback.rs +++ b/crates/asap-physical-operators/tests/promql_fallback.rs @@ -11,9 +11,8 @@ use asap_physical_operators::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::physical_export::PhysicalASAPDAG; -use planner_types::{ - post_asap::execution_data_state::lift_plain, types::AccuracyTarget, workload::*, -}; +use planner_types::physical::lift_plain; +use planner_types::{types::AccuracyTarget, workload::*}; use std::{collections::BTreeMap, rc::Rc}; /// Bare selectors look back one ingestion interval: 60s. @@ -86,7 +85,7 @@ fn labels(spec: &str) -> BTreeMap { fn metric(selector: &planner_types::ir::OperatorNode) -> String { match selector.expect_non_asap() { planner_types::ir::NonASAPOp::Scan { - source: planner_types::pre_asap::Source::TimeSeries { metric }, + source: planner_types::ir::operator::Source::TimeSeries { metric }, .. } => metric.clone(), planner_types::ir::NonASAPOp::TimeRange { child, .. } diff --git a/crates/asap-physical-operators/tests/promql_values.rs b/crates/asap-physical-operators/tests/promql_values.rs index 35b9f2c0b..1174ab5e1 100644 --- a/crates/asap-physical-operators/tests/promql_values.rs +++ b/crates/asap-physical-operators/tests/promql_values.rs @@ -8,7 +8,8 @@ use asap_physical_operators::{ values::{Batch, Value}, }; use futures::{executor::block_on, StreamExt}; -use planner_types::pre_asap::{AggIntent, ColumnRef, GroupKeys}; +use planner_types::ir::operator::{AggIntent, GroupKeys}; +use planner_types::ir::scalar::ColumnRef; use std::collections::BTreeMap; @@ -216,7 +217,7 @@ fn composed_ensemble_shares_a_producer_across_roots() { runtime::{Input, OutputStream}, values::SchemaRef, }; - use planner_types::pre_asap::ArithmeticOpKind; + use planner_types::ir::scalar::ArithmeticOpKind; struct Counted { source: Operator, starts: std::rc::Rc>, @@ -325,7 +326,7 @@ fn compiled_constant_needs_no_deployment_source() { // arithmetic or bool comparisons remove the metric name. #[test] fn scalar_broadcast_rejects_colliding_result_labels_after_recovery() { - use planner_types::pre_asap::{ArithmeticOpKind, CompareOpKind}; + use planner_types::ir::scalar::{ArithmeticOpKind, CompareOpKind}; for left_scalar in [false, true] { for names in [["a", "a"], ["a", "b"]] { for (kind, return_bool) in [ @@ -400,7 +401,7 @@ fn scalar_broadcast_rejects_colliding_result_labels_after_recovery() { #[test] fn exact_state_evaluations_recover_and_finalize_panes() { use asap_physical_operators::factory::create_planner_accumulator; - use planner_types::post_asap::*; + use planner_types::ir::schema::*; use std::sync::Arc; for (kind, params, expected) in [ (ExactKind::Sum, ExactParams::Sum, 12.), @@ -450,7 +451,7 @@ fn exact_state_evaluations_recover_and_finalize_panes() { #[test] fn recovered_exact_counter_uses_window_and_omits_insufficient_samples() { use asap_physical_operators::factory::create_planner_accumulator; - use planner_types::post_asap::*; + use planner_types::ir::schema::*; use std::sync::Arc; for (kind, params, expected) in [ (ExactKind::Rate, ExactParams::Rate, 1.), diff --git a/crates/asap-physical-operators/tests/raw_scan.rs b/crates/asap-physical-operators/tests/raw_scan.rs index 41f222312..3878f908c 100644 --- a/crates/asap-physical-operators/tests/raw_scan.rs +++ b/crates/asap-physical-operators/tests/raw_scan.rs @@ -6,16 +6,16 @@ use asap_physical_operators::dag::{ Error, Limits, OutputStream, RunContext, Scope, }; use futures::{executor::block_on, stream, StreamExt}; +use planner_types::ir::operator::{GroupKeys, Source}; use planner_types::ir::physical_export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::properties::*; +use planner_types::ir::schema::*; +use planner_types::ir::schema::{DataType, Field}; use planner_types::ir::NonASAPOp; use planner_types::ir::Predicate; -use planner_types::{ - post_asap::*, - pre_asap::{DataType, Field, GroupKeys, Source}, -}; use std::{ collections::BTreeMap, sync::{ @@ -25,12 +25,13 @@ use std::{ }; fn fixture() -> (planner_types::ir::NonASAPOp, SchemaRef, Vec) { - let schema = planner_types::pre_asap::Schema::new(vec![planner_types::pre_asap::Field::plain( - "value", - DataType::Int64, - true, - )]); - let output = Arc::new(planner_types::pre_asap::Schema { + let schema = + planner_types::ir::schema::Schema::new(vec![planner_types::ir::schema::Field::plain( + "value", + DataType::Int64, + true, + )]); + let output = Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![Field { @@ -320,7 +321,7 @@ fn schema_drift_and_memory_limits_fail_the_scan() { // An empty table is a valid empty scan; nullable comparisons retain only TRUE. #[test] fn empty_sources_and_three_valued_predicates() { - use planner_types::pre_asap::{CompareOpKind, ScalarValue}; + use planner_types::ir::scalar::{CompareOpKind, ScalarValue}; let (mut scan, schema, batches) = fixture(); if let planner_types::ir::NonASAPOp::Scan { diff --git a/crates/asap-physical-operators/tests/summary_projection.rs b/crates/asap-physical-operators/tests/summary_projection.rs index 65acba34a..0362d9542 100644 --- a/crates/asap-physical-operators/tests/summary_projection.rs +++ b/crates/asap-physical-operators/tests/summary_projection.rs @@ -12,12 +12,12 @@ use planner_types::ir::physical_export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::properties::*; +use planner_types::ir::scalar::ColumnRef; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::*; use planner_types::ir::ASAPOp; use planner_types::ir::NonASAPOp; -use planner_types::{ - post_asap::*, - pre_asap::{ColumnRef, DataType}, -}; use std::{collections::BTreeMap, sync::Arc}; // A Post-ASAP projection may reorder/rename summary columns; recovery must retain @@ -25,7 +25,7 @@ use std::{collections::BTreeMap, sync::Arc}; #[test] fn post_asap_summary_projection_survives_recovery() { let family = FieldDataType::ExactAggregate(ExactKind::Sum, ExactParams::Sum); - let schema = Arc::new(planner_types::pre_asap::Schema { + let schema = Arc::new(planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![ @@ -44,7 +44,7 @@ fn post_asap_summary_projection_survives_recovery() { ], time_index: None, }); - let output = planner_types::pre_asap::Schema { + let output = planner_types::ir::schema::Schema { unique_keys: vec![], closed: false, fields: vec![ diff --git a/crates/asap-physical-operators/tests/weighted_topk_binding.rs b/crates/asap-physical-operators/tests/weighted_topk_binding.rs index 2b473f7c7..c2f2e319d 100644 --- a/crates/asap-physical-operators/tests/weighted_topk_binding.rs +++ b/crates/asap-physical-operators/tests/weighted_topk_binding.rs @@ -16,8 +16,11 @@ use asap_physical_operators::dag::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::physical_export::{PhysicalASAPDAG, PhysicalASAPOperatorPayload}; +use planner_types::ir::properties::*; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::*; use planner_types::ir::ASAPOp; -use planner_types::{post_asap::*, pre_asap::DataType, types::AccuracyTarget}; +use planner_types::types::AccuracyTarget; use std::{collections::BTreeMap, rc::Rc, sync::Arc}; struct Evidence; impl AccuracyEvidenceProvider for Evidence { @@ -246,9 +249,9 @@ fn rate_updates_cannot_enter_integer_heap_factory() { ); let input = SummaryUpdate { item: Some(SummaryInputExpr::Column( - planner_types::pre_asap::ColumnRef::Named("service".into()), + planner_types::ir::scalar::ColumnRef::Named("service".into()), )), - weight: SummaryInputExpr::Column(planner_types::pre_asap::ColumnRef::SampleValue), + weight: SummaryInputExpr::Column(planner_types::ir::scalar::ColumnRef::SampleValue), weight_domain: WeightDomain::NonNegative { proof: NonNegativeWeightProof::ResetAwareCounterDerivative, }, @@ -293,13 +296,11 @@ fn check_direct_rate_topk(dynamic: bool) { .. }) => { schema.closed = true; - schema - .fields - .push(planner_types::pre_asap::schema::Field::plain( - "service", - DataType::Utf8, - false, - )); + schema.fields.push(planner_types::ir::schema::Field::plain( + "service", + DataType::Utf8, + false, + )); } _ => panic!("unexpected input shape: {node:?}"), } diff --git a/crates/devtools/examples/canonical_examples.rs b/crates/devtools/examples/canonical_examples.rs index fd4b703a1..8e2de95ca 100644 --- a/crates/devtools/examples/canonical_examples.rs +++ b/crates/devtools/examples/canonical_examples.rs @@ -5,7 +5,7 @@ use asap_devtools::lower_promql_with_data_ingestion_interval; use asap_frontend_sql::{lower_sql_dialect, SqlCatalog}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; diff --git a/crates/devtools/examples/topk_ir.rs b/crates/devtools/examples/topk_ir.rs index 21dcefb4b..6f251e22d 100644 --- a/crates/devtools/examples/topk_ir.rs +++ b/crates/devtools/examples/topk_ir.rs @@ -4,7 +4,7 @@ // resulting pre-ASAP IR. Used for interactive exploration; not a test. use asap_devtools::{lower_promql_with_data_ingestion_interval, lower_sql, SqlCatalog}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; fn col(name: &str, dtype: DataType) -> Field { diff --git a/crates/devtools/src/bin/analyze_corpora.rs b/crates/devtools/src/bin/analyze_corpora.rs index 0eebe1381..0b3f799a1 100644 --- a/crates/devtools/src/bin/analyze_corpora.rs +++ b/crates/devtools/src/bin/analyze_corpora.rs @@ -6,7 +6,7 @@ use asap_devtools::{lower_promql_with_data_ingestion_interval, SqlCatalog}; use asap_frontend_sql::lower_sql_dialect; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; use serde::Serialize; diff --git a/crates/devtools/src/bin/dag_export.rs b/crates/devtools/src/bin/dag_export.rs index 5f2be890a..d2d5e0729 100644 --- a/crates/devtools/src/bin/dag_export.rs +++ b/crates/devtools/src/bin/dag_export.rs @@ -98,11 +98,12 @@ use asap_types::dag_export::{ TargetReplacement, TargetReplacementAfter, WorkloadDAG, }; use asap_types::ir::cse::{structural_hash, HashCache}; +use asap_types::ir::properties::CompositionOperator; +use asap_types::ir::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{FieldDataType, SketchStatistic}; use asap_types::ir::OperatorNode; -use asap_types::post_asap::{CompositionOperator, FieldDataType, SketchStatistic}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; -use asap_types::resources::CacheProfile; use asap_types::types::AccuracyTarget; +use asap_types::workload::resources::CacheProfile; #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[serde(deny_unknown_fields)] @@ -659,9 +660,9 @@ impl CostModel for ExportPlannerCostModel<'_> { fn rank_candidates( &self, - _intent: &asap_types::pre_asap::AggIntent, - candidates: &[asap_types::post_asap::SketchAlgorithm], - ) -> Vec { + _intent: &asap_types::ir::operator::AggIntent, + candidates: &[asap_types::ir::schema::SketchAlgorithm], + ) -> Vec { // Candidate generation must not reintroduce the legacy structural // cost model before complete physical alternatives are compared. candidates.to_vec() @@ -1705,8 +1706,9 @@ mod tests { }; use asap_aware_mapping::query_physical_lowering::lower_query_physical_dag; use asap_devtools::PromqlError; + use asap_types::ir::operator::{Reduction, Source}; + use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::NonASAPOp; - use asap_types::pre_asap::{DataType, Field, Reduction, Schema, Source}; fn lower_promql( query: &str, @@ -1726,7 +1728,7 @@ mod tests { .expect("scan leaf derives its schema"); OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Aggregate { reduction: Reduction::by(vec![]), - measures: vec![asap_types::pre_asap::AggIntent::Count { + measures: vec![asap_types::ir::operator::AggIntent::Count { accuracy: AccuracyTarget::Epsilon(0.1), }], output_names: vec![], diff --git a/crates/devtools/src/bin/show_post_asap_ir.rs b/crates/devtools/src/bin/show_post_asap_ir.rs index 51123cfdb..8baf0b1e4 100644 --- a/crates/devtools/src/bin/show_post_asap_ir.rs +++ b/crates/devtools/src/bin/show_post_asap_ir.rs @@ -26,8 +26,8 @@ use asap_aware_mapping::{ ASAPStrategies, Replacement, ReplacementStrategy, ReplacementSubDAG, TargetSubDAG, }; use asap_devtools::{lower_promql_with_data_ingestion_interval, lower_sql, SqlCatalog}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::OperatorNode; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use std::io::Read; use std::rc::Rc; @@ -176,10 +176,10 @@ mod tests { candidates[0].guarantee.is_none(), "missing evidence must not claim a certified ratio bound" ); - let timed = asap_types::ir::timing::apply_materialization_timings( + let timed = asap_types::ir::properties::timing::apply_materialization_timings( &candidates[0], - &asap_types::ir::timing::MaterializationAssignment::all_query_time(), - &mut asap_types::ir::timing::TimingMemo::new(), + &asap_types::ir::properties::timing::MaterializationAssignment::all_query_time(), + &mut asap_types::ir::properties::timing::TimingMemo::new(), ) .expect("the demo candidate has a legal default timing"); asap_types::ir::physical_export::compile_physical_asap_dag(&timed) diff --git a/crates/devtools/src/bin/show_pre_asap_ir.rs b/crates/devtools/src/bin/show_pre_asap_ir.rs index bde7cfb3c..1b3a3f724 100644 --- a/crates/devtools/src/bin/show_pre_asap_ir.rs +++ b/crates/devtools/src/bin/show_pre_asap_ir.rs @@ -18,7 +18,7 @@ // bytes)` catalog — the same table used in cross_language.rs and topk_ir.rs. use asap_devtools::{lower_promql_with_data_ingestion_interval, lower_sql, SqlCatalog}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use std::io::Read; diff --git a/crates/devtools/src/bin/sketch_coverage.rs b/crates/devtools/src/bin/sketch_coverage.rs index 290bc88dc..9ac97e066 100644 --- a/crates/devtools/src/bin/sketch_coverage.rs +++ b/crates/devtools/src/bin/sketch_coverage.rs @@ -28,8 +28,8 @@ use asap_aware_mapping::{explain_replacements, ExplanationKind}; use asap_devtools::lower_promql_with_data_ingestion_interval; use asap_frontend_sql::{lower_sql_dialect, SqlCatalog}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::OperatorNode; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; use std::collections::BTreeSet; diff --git a/crates/devtools/src/bin/stage_pipeline.rs b/crates/devtools/src/bin/stage_pipeline.rs index 6f6d9d10f..fb315e299 100644 --- a/crates/devtools/src/bin/stage_pipeline.rs +++ b/crates/devtools/src/bin/stage_pipeline.rs @@ -27,9 +27,9 @@ use asap_aware_mapping::physical_candidates::stage2_physical; use asap_aware_mapping::plan_selection::{stage3_select, Selection}; use asap_aware_mapping::{PlanningModels, Realization}; use asap_types::ir::flat::{flatten, FlatDag}; +use asap_types::ir::schema::SketchAlgorithm; use asap_types::ir::schema_support::with_promql_series_identity; use asap_types::ir::{OperatorNode, QueryRoot}; -use asap_types::post_asap::SketchAlgorithm; use asap_types::types::AccuracyTarget; use asap_types::workload::{ AccuracyRequirement, BatchEntry, DataArrival, DataDistribution, DataWorkload, DurationMs, diff --git a/crates/devtools/src/bin/variant_coverage.rs b/crates/devtools/src/bin/variant_coverage.rs index 83d797005..444ad0e49 100644 --- a/crates/devtools/src/bin/variant_coverage.rs +++ b/crates/devtools/src/bin/variant_coverage.rs @@ -8,8 +8,8 @@ use asap_devtools::lower_promql_with_data_ingestion_interval; use asap_frontend_sql::{lower_sql_dialect, SqlCatalog}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{OperatorNode, ScalarExpr}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; use std::collections::BTreeSet; diff --git a/crates/devtools/tests/cross_language.rs b/crates/devtools/tests/cross_language.rs index 597362e99..441e97f1a 100644 --- a/crates/devtools/tests/cross_language.rs +++ b/crates/devtools/tests/cross_language.rs @@ -14,9 +14,9 @@ //! explicit inner `Aggregate([Count])`. use asap_devtools::{lower_promql_with_data_ingestion_interval, lower_sql, SqlCatalog}; +use asap_types::ir::operator::{AggIntent, GroupKeys}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{NonASAPOp, OperatorNode}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; -use asap_types::pre_asap::{AggIntent, GroupKeys}; use asap_types::types::AccuracyTarget; use std::rc::Rc; diff --git a/crates/frontend-common/src/lib.rs b/crates/frontend-common/src/lib.rs index f756bc46a..47684f668 100644 --- a/crates/frontend-common/src/lib.rs +++ b/crates/frontend-common/src/lib.rs @@ -2,7 +2,7 @@ //! and its resolver into the unified IR. //! //! A front end builds an [`UnresolvedOp`] tree (column references are -//! name-based [`ColumnRef`](asap_types::pre_asap::ColumnRef)s) during its +//! name-based [`ColumnRef`](asap_types::ir::scalar::ColumnRef)s) during its //! own `interpret` step and calls [`resolve_root`], which binds every //! reference to a positional `ColumnId` and returns the //! [`OperatorNode`](asap_types::ir::OperatorNode) DAG. diff --git a/crates/frontend-common/src/resolve.rs b/crates/frontend-common/src/resolve.rs index dc204527f..388203b8b 100644 --- a/crates/frontend-common/src/resolve.rs +++ b/crates/frontend-common/src/resolve.rs @@ -15,18 +15,17 @@ //! label names its enclosing scope references (issue #52): the `job` in //! `sum by (job)(a or b)` appears in neither side's own matchers. -use asap_types::ir::aggregate_schema::aggregate_output_schema; +use asap_types::ir::schema::aggregate_schema::aggregate_output_schema; use std::rc::Rc; use thiserror::Error; -use asap_types::ir::operator_properties::ConcatDiscriminatorKey; +use asap_types::ir::operator::operator_properties::ConcatDiscriminatorKey; +use asap_types::ir::operator::{AggIntent, GroupKeys, Reduction}; +use asap_types::ir::scalar::column_resolution::resolve_group_keys_promql; +use asap_types::ir::scalar::{resolve_column_ref, resolve_column_refs, ColumnRef, ResolveError}; +use asap_types::ir::schema::{ColumnId, Schema, SchemaDerivationError}; use asap_types::ir::{NonASAPOp, OperatorNode, Predicate, ProjectItem, ScalarExpr, SortKey}; -use asap_types::pre_asap::column_resolution::resolve_group_keys_promql; -use asap_types::pre_asap::{ - resolve_column_ref, resolve_column_refs, AggIntent, ColumnId, ColumnRef, GroupKeys, Reduction, - ResolveError, Schema, SchemaDerivationError, -}; use crate::schema_resolver::{collect_referenced_columns, SchemaResolver}; use crate::unresolved::{UnresolvedOp, UnresolvedScalar, UnresolvedSortKey}; @@ -726,12 +725,14 @@ pub fn resolve_scalar_root(tree: &UnresolvedScalar) -> Result, scalar: ScalarExpr, - op: &asap_types::pre_asap::BinaryOpKind, + op: &asap_types::ir::operator::BinaryOpKind, scalar_left: bool, return_bool: bool, ) -> Result, ResolveDAGError> { + use asap_types::ir::operator::BinaryOpKind; + use asap_types::ir::scalar::ScalarValue; + use asap_types::ir::schema::DataType; use asap_types::ir::ExprSemantics; - use asap_types::pre_asap::{BinaryOpKind, DataType, ScalarValue}; let value = child .schema .column_id("value") @@ -800,7 +801,7 @@ fn project_sample( computed: ScalarExpr, drop_metric_name: bool, ) -> Result, ResolveDAGError> { - let value = asap_types::pre_asap::column_resolution::resolve_column_ref( + let value = asap_types::ir::scalar::column_resolution::resolve_column_ref( &ColumnRef::SampleValue, &child.schema, )?; @@ -813,9 +814,7 @@ fn project_sample( .map(|(i, f)| { let expr = if i == value { computed.clone() - } else if drop_metric_name - && f.name == asap_types::pre_asap::schema::PROMQL_SERIES_IDENTITY - { + } else if drop_metric_name && f.name == asap_types::ir::schema::PROMQL_SERIES_IDENTITY { ScalarExpr::FunctionCall { name: "promql_drop_metric_name".into(), args: vec![ScalarExpr::Column(i)], @@ -840,12 +839,13 @@ fn project_sample( mod tests { use super::*; use crate::unresolved::UnresolvedPredicate; + use asap_types::ir::operator::{ + BinaryOpKind, JoinKind, PromQLVectorSetOpKind, Source, VectorMatch, + }; + use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; + use asap_types::ir::schema::{DataType, Field}; use asap_types::ir::BinaryOperator; use asap_types::ir::ExprSemantics; - use asap_types::pre_asap::{ - BinaryOpKind, CompareOpKind, DataType, Field, JoinKind, PromQLVectorSetOpKind, ScalarValue, - Source, VectorMatch, - }; use asap_types::types::AccuracyTarget; fn scan(metric: &str) -> UnresolvedOp { @@ -1127,7 +1127,7 @@ mod tests { let unresolved = UnresolvedOp::PromqlScalarOp { child: Rc::new(scan("m")), scalar: UnresolvedScalar::PromqlScalarFromVector(Rc::new(x)), - op: BinaryOpKind::Arithmetic(asap_types::pre_asap::ArithmeticOpKind::Mul), + op: BinaryOpKind::Arithmetic(asap_types::ir::scalar::ArithmeticOpKind::Mul), scalar_left: false, return_bool: false, }; diff --git a/crates/frontend-common/src/schema_resolver.rs b/crates/frontend-common/src/schema_resolver.rs index ad7605fe6..1f08542fb 100644 --- a/crates/frontend-common/src/schema_resolver.rs +++ b/crates/frontend-common/src/schema_resolver.rs @@ -9,7 +9,9 @@ //! observability domain (metric label sets are open-ended). A registry-backed //! `SchemaCatalog` is future work; only the catalog impl swaps when it lands. -use asap_types::pre_asap::{AggIntent, ColumnRef, DataType, Field, GroupKeys, Reduction, Schema}; +use asap_types::ir::operator::{AggIntent, GroupKeys, Reduction}; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{DataType, Field, Schema}; use crate::unresolved::{UnresolvedOp, UnresolvedScalar}; @@ -128,7 +130,7 @@ fn push_ref_name(c: &ColumnRef, out: &mut Vec) { /// (never the operators referenced from scalar positions: those are bound in /// their own scope). fn leftmost_scan_name(tree: &UnresolvedOp) -> Option<&str> { - use asap_types::pre_asap::Source; + use asap_types::ir::operator::Source; use UnresolvedOp as U; match tree { U::Scan { source, .. } => Some(match source { @@ -319,7 +321,7 @@ pub fn collect_referenced_columns(tree: &UnresolvedOp) -> Vec { mod tests { use std::rc::Rc; - use asap_types::pre_asap::{AggIntent, Reduction, Source}; + use asap_types::ir::operator::{AggIntent, Reduction, Source}; use super::*; use crate::unresolved::UnresolvedSortKey; diff --git a/crates/frontend-common/src/unresolved.rs b/crates/frontend-common/src/unresolved.rs index 0bca427cc..eb6ab3587 100644 --- a/crates/frontend-common/src/unresolved.rs +++ b/crates/frontend-common/src/unresolved.rs @@ -15,14 +15,15 @@ use std::time::Duration; use serde::{Deserialize, Serialize}; -use asap_types::ir::operator_properties::ConcatDiscriminatorKey; +use asap_types::ir::operator::operator_properties::ConcatDiscriminatorKey; +use asap_types::ir::operator::{ + AggIntent, GroupKeys, InfoMatcher, JoinKind, Reduction, RelationalSetOpKind, SampleKind, + Source, TimeShift, WindowFrame, WindowFuncKind, +}; +use asap_types::ir::scalar::{ArithmeticOpKind, ColumnRef, CompareOpKind, ScalarValue}; +use asap_types::ir::schema::{DataType, Schema}; use asap_types::ir::BinaryOperator; use asap_types::ir::{ExprSemantics, TimeRangeKind}; -use asap_types::pre_asap::{ - AggIntent, ArithmeticOpKind, ColumnRef, CompareOpKind, DataType, GroupKeys, InfoMatcher, - JoinKind, Reduction, RelationalSetOpKind, SampleKind, ScalarValue, Schema, Source, TimeShift, - WindowFrame, WindowFuncKind, -}; /// A row-level filter predicate (WHERE clause / PromQL label matcher). #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -221,7 +222,7 @@ pub enum UnresolvedOp { PromqlScalarOp { child: Rc, scalar: UnresolvedScalar, - op: asap_types::pre_asap::BinaryOpKind, + op: asap_types::ir::operator::BinaryOpKind, scalar_left: bool, return_bool: bool, }, diff --git a/crates/frontend-metricsql/src/lib.rs b/crates/frontend-metricsql/src/lib.rs index 3544a9801..2524cd150 100644 --- a/crates/frontend-metricsql/src/lib.rs +++ b/crates/frontend-metricsql/src/lib.rs @@ -5,11 +5,11 @@ use std::{rc::Rc, time::Duration}; use asap_frontend_common::{ resolve_root, UnresolvedOp as U, UnresolvedPredicate, UnresolvedScalar, }; -use asap_types::ir::{BinaryOperator, ExprSemantics, OperatorNode, TimeRangeKind}; -use asap_types::pre_asap::{ - AggIntent, ArithmeticOpKind, BinaryOpKind, ColumnRef, CompareOpKind, GroupKeys, - PromQLVectorSetOpKind, Reduction, ScalarValue, Source, +use asap_types::ir::operator::{ + AggIntent, BinaryOpKind, GroupKeys, PromQLVectorSetOpKind, Reduction, Source, }; +use asap_types::ir::scalar::{ArithmeticOpKind, ColumnRef, CompareOpKind, ScalarValue}; +use asap_types::ir::{BinaryOperator, ExprSemantics, OperatorNode, TimeRangeKind}; use asap_types::types::AccuracyTarget; use metricsql_parser::ast::{AggregateModifier, DurationExpr, Expr, MetricExpr, RollupExpr}; use metricsql_parser::functions::{AggregateFunction, BuiltinFunction, RollupFunction}; diff --git a/crates/frontend-metricsql/tests/lowering.rs b/crates/frontend-metricsql/tests/lowering.rs index ef828d04d..1c8b59d50 100644 --- a/crates/frontend-metricsql/tests/lowering.rs +++ b/crates/frontend-metricsql/tests/lowering.rs @@ -4,8 +4,8 @@ use std::time::Duration; use asap_frontend_metricsql::{ canonical_metricsql, lower_metricsql, parse_metricsql, MetricsqlError, }; +use asap_types::ir::operator::{AggIntent, Reduction, Source}; use asap_types::ir::{NonASAPOp, OperatorNode, TimeRangeKind}; -use asap_types::pre_asap::{AggIntent, Reduction, Source}; use asap_types::types::AccuracyTarget; fn lower(query: &str) -> Rc { diff --git a/crates/frontend-promql/src/promql.rs b/crates/frontend-promql/src/promql.rs index 42b39eb60..53ec79c86 100644 --- a/crates/frontend-promql/src/promql.rs +++ b/crates/frontend-promql/src/promql.rs @@ -69,16 +69,15 @@ use promql_parser::parser::{ use asap_frontend_common::{ UnresolvedOp as Unresolved, UnresolvedPredicate, UnresolvedScalar as Scalar, UnresolvedSortKey, }; -use asap_types::ir::operator_properties::{ +use asap_types::ir::operator::agg_intent::{topk, AggIntent, TimeFunc}; +use asap_types::ir::operator::operator_properties::{ AtModifier, BinaryOpKind, GroupKeys, GroupSide, PromQLVectorSetOpKind, Reduction, Source, TimeShift, VectorGrouping, VectorMatch, VectorMatchKind, }; use asap_types::ir::{BinaryOperator, ExprSemantics, TimeRangeKind}; -use asap_types::pre_asap::agg_intent::{topk, AggIntent, TimeFunc}; -use asap_types::pre_asap::{ - ArithmeticOpKind, ColumnRef, CompareOpKind, InfoMatcher, SampleKind, ScalarValue, -}; +use asap_types::ir::operator::{InfoMatcher, SampleKind}; +use asap_types::ir::scalar::{ArithmeticOpKind, ColumnRef, CompareOpKind, ScalarValue}; use asap_types::types::AccuracyTarget; /// Every scalar expression this front end builds follows PromQL's numeric rules. diff --git a/crates/frontend-promql/tests/count_planning.rs b/crates/frontend-promql/tests/count_planning.rs index 4609258bf..13dab50e6 100644 --- a/crates/frontend-promql/tests/count_planning.rs +++ b/crates/frontend-promql/tests/count_planning.rs @@ -7,11 +7,11 @@ use asap_aware_mapping::{ }; mod support; use asap_types::ir::physical_export::PhysicalASAPOperatorPayload; -use asap_types::ir::{ASAPOp, Operator}; -use asap_types::post_asap::{ +use asap_types::ir::schema::{ ExactKind, FieldDataType, NonNegativeWeightProof, SketchAlgorithm, SummaryInputExpr, WeightDomain, }; +use asap_types::ir::{ASAPOp, Operator}; use asap_types::types::AccuracyTarget; use support::{lower_promql, post_asap_dag}; @@ -136,8 +136,8 @@ fn frequency_count_candidates_use_unit_weights() { // This narrow test oracle interprets the emitted aggregate, not Prometheus ingestion, // staleness, or scrape scheduling. Unsupported plan shapes fail explicitly. fn aggregate_fixture(query: &str, series: &[Vec]) -> Vec { + use asap_types::ir::operator::{AggIntent, Reduction}; use asap_types::ir::NonASAPOp; - use asap_types::pre_asap::{AggIntent, Reduction}; let root = lower_promql(query, AccuracyTarget::Exact).unwrap(); let NonASAPOp::Aggregate { reduction, @@ -226,7 +226,7 @@ fn count_over_time_counts_scrapes_not_sample_values() { // This checks the planner's numerical update contract, not a sketch-library runtime. #[test] fn cms_count_updates_total_ten_for_zero_positive_and_negative_samples() { - use asap_types::pre_asap::ColumnRef; + use asap_types::ir::scalar::ColumnRef; let root = lower_promql("count_over_time(up[5m])", AccuracyTarget::Epsilon(0.02)).unwrap(); let candidates = ASAPStrategies::default_cost_model().replacements(&TargetSubDAG::new(&root)); let dag = candidates diff --git a/crates/frontend-promql/tests/histogram_metadata.rs b/crates/frontend-promql/tests/histogram_metadata.rs index aba373804..37f0d5e77 100644 --- a/crates/frontend-promql/tests/histogram_metadata.rs +++ b/crates/frontend-promql/tests/histogram_metadata.rs @@ -7,8 +7,8 @@ use asap_frontend_promql::{HistogramCatalog, HistogramKind}; mod support; +use asap_types::ir::operator::AggIntent; use asap_types::ir::{NonASAPOp, OperatorNode}; -use asap_types::pre_asap::AggIntent; use asap_types::types::AccuracyTarget; use support::{lower_promql, lower_promql_with_histograms}; diff --git a/crates/frontend-promql/tests/maintained_population_horizon.rs b/crates/frontend-promql/tests/maintained_population_horizon.rs index b4130bf86..cf98f2ebf 100644 --- a/crates/frontend-promql/tests/maintained_population_horizon.rs +++ b/crates/frontend-promql/tests/maintained_population_horizon.rs @@ -1,7 +1,7 @@ mod support; use asap_aware_mapping::maintained_population::MaintainedPopulationStrategy; +use asap_types::ir::operator::maintained_population::PopulationInput; use asap_types::ir::{ASAPOp, NonASAPOp, Operator}; -use asap_types::post_asap::maintained_population::PopulationInput; use asap_types::types::AccuracyTarget; // A population for a one-second selector must expire members after one second. diff --git a/crates/frontend-promql/tests/observability/awesome_prometheus_alerts.rs b/crates/frontend-promql/tests/observability/awesome_prometheus_alerts.rs index 5e78e261d..695be71f3 100644 --- a/crates/frontend-promql/tests/observability/awesome_prometheus_alerts.rs +++ b/crates/frontend-promql/tests/observability/awesome_prometheus_alerts.rs @@ -31,8 +31,9 @@ use asap_frontend_promql::PromqlError as LoweringError; mod support; use std::rc::Rc; +use asap_types::ir::operator::{AggIntent, BinaryOpKind, Reduction}; +use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; use asap_types::ir::{BinaryOperator, NonASAPOp, OperatorNode, ScalarExpr}; -use asap_types::pre_asap::{AggIntent, BinaryOpKind, CompareOpKind, Reduction, ScalarValue}; use asap_types::types::AccuracyTarget; use support::lower_promql; diff --git a/crates/frontend-promql/tests/promql_binding_regressions.rs b/crates/frontend-promql/tests/promql_binding_regressions.rs index 416b6680d..daa88a967 100644 --- a/crates/frontend-promql/tests/promql_binding_regressions.rs +++ b/crates/frontend-promql/tests/promql_binding_regressions.rs @@ -33,8 +33,8 @@ fn irate_and_rate_have_distinct_canonical_intents() { /// PromQL count counts series even when two sample values are equal. #[test] fn count_is_row_count_not_distinct_sample_value_count() { + use asap_types::ir::operator::AggIntent; use asap_types::ir::NonASAPOp; - use asap_types::pre_asap::AggIntent; let tree = lower_promql("count(smoke_gauge)", AccuracyTarget::Exact).unwrap(); let NonASAPOp::Aggregate { measures, .. } = tree.expect_non_asap() else { panic!("expected aggregate") diff --git a/crates/frontend-promql/tests/promql_conformance.rs b/crates/frontend-promql/tests/promql_conformance.rs index 2f3fa2bf8..eae9b710a 100644 --- a/crates/frontend-promql/tests/promql_conformance.rs +++ b/crates/frontend-promql/tests/promql_conformance.rs @@ -36,14 +36,15 @@ use std::time::Duration; use asap_frontend_promql::PromqlError as LoweringError; mod support; +use asap_types::ir::operator::{ + AggIntent, AtModifier, BinaryOpKind, PromQLVectorSetOpKind, Reduction, SampleKind, Source, + TimeFunc, +}; +use asap_types::ir::scalar::{ArithmeticOpKind, CompareOpKind, ScalarValue}; +use asap_types::ir::schema::DataType; use asap_types::ir::{ BinaryOperator, ExprSemantics, NonASAPOp, OperatorNode, ScalarExpr, TimeRangeKind, }; -use asap_types::pre_asap::schema::DataType; -use asap_types::pre_asap::{ - AggIntent, ArithmeticOpKind, AtModifier, BinaryOpKind, CompareOpKind, PromQLVectorSetOpKind, - Reduction, SampleKind, ScalarValue, Source, TimeFunc, -}; use asap_types::types::AccuracyTarget; use support::{lower_promql, promql_scalar}; diff --git a/crates/frontend-promql/tests/promql_lowering.rs b/crates/frontend-promql/tests/promql_lowering.rs index 540f426f5..81f471660 100644 --- a/crates/frontend-promql/tests/promql_lowering.rs +++ b/crates/frontend-promql/tests/promql_lowering.rs @@ -3,12 +3,11 @@ use std::rc::Rc; use std::time::Duration; +use asap_types::ir::operator::{AggIntent, BinaryOpKind, Reduction, Source}; +use asap_types::ir::scalar::{ArithmeticOpKind, CompareOpKind, ScalarValue}; use asap_types::ir::{ BinaryOperator, ExprSemantics, NonASAPOp, OperatorNode, ScalarExpr, TimeRangeKind, }; -use asap_types::pre_asap::{ - AggIntent, ArithmeticOpKind, BinaryOpKind, CompareOpKind, Reduction, ScalarValue, Source, -}; use asap_types::types::AccuracyTarget; use asap_types::workload::{ AccuracyRequirement, BatchEntry, DataWorkload, DurationMs, Evidence, PlanningWorkload, @@ -835,7 +834,7 @@ fn binary_op_with_on_grouping() { panic!("expected BinaryOp, got {qe:?}"); }; let vm = vector_match.as_ref().expect("vector_match present"); - use asap_types::pre_asap::VectorMatchKind; + use asap_types::ir::operator::VectorMatchKind; assert_eq!(vm.kind, VectorMatchKind::On); assert_eq!(vm.labels, vec!["host".to_string()]); } diff --git a/crates/frontend-promql/tests/scalar_design.rs b/crates/frontend-promql/tests/scalar_design.rs index e4f8038f8..ec853a1f7 100644 --- a/crates/frontend-promql/tests/scalar_design.rs +++ b/crates/frontend-promql/tests/scalar_design.rs @@ -1,7 +1,7 @@ //! Scalar expressions never become constant-wrapper operators. mod support; +use asap_types::ir::scalar::{ArithmeticOpKind, ScalarValue}; use asap_types::ir::{NonASAPOp, QueryRoot, ScalarExpr}; -use asap_types::pre_asap::{ArithmeticOpKind, ScalarValue}; use asap_types::types::AccuracyTarget; fn root(query: &str) -> QueryRoot { diff --git a/crates/frontend-promql/tests/support.rs b/crates/frontend-promql/tests/support.rs index 6b5418f9f..5549c13f2 100644 --- a/crates/frontend-promql/tests/support.rs +++ b/crates/frontend-promql/tests/support.rs @@ -3,8 +3,8 @@ use std::rc::Rc; use asap_frontend_promql::{ lower_promql_workload, lower_promql_workload_with_histograms, HistogramCatalog, PromqlError, }; +use asap_types::ir::scalar::ScalarValue; use asap_types::ir::{NonASAPOp, OperatorNode, ScalarExpr}; -use asap_types::pre_asap::ScalarValue; use asap_types::types::AccuracyTarget; use asap_types::workload::{ AccuracyRequirement, BatchEntry, DataWorkload, DurationMs, Evidence, PlanningWorkload, diff --git a/crates/frontend-promql/tests/univmon_candidates.rs b/crates/frontend-promql/tests/univmon_candidates.rs index 12a0a53b5..0a1709daf 100644 --- a/crates/frontend-promql/tests/univmon_candidates.rs +++ b/crates/frontend-promql/tests/univmon_candidates.rs @@ -8,11 +8,11 @@ use asap_aware_mapping::replacement::{default_strategies, search_workload_with_t use asap_aware_mapping::{ASAPStrategies, Replacement, ReplacementStrategy, TargetSubDAG}; mod support; use asap_types::ir::cse::share_common_sub_dags; -use asap_types::ir::{ASAPOp, Operator, OperatorNode}; -use asap_types::post_asap::{ - AccuracyError, BoundExpr, CompositionOperator, ErrorMetric, FieldDataType, ProbabilityExpr, - ResultGuarantee, SketchAlgorithm, SketchStatistic, SummaryInputExpr, +use asap_types::ir::properties::{ + AccuracyError, BoundExpr, CompositionOperator, ErrorMetric, ProbabilityExpr, ResultGuarantee, }; +use asap_types::ir::schema::{FieldDataType, SketchAlgorithm, SketchStatistic, SummaryInputExpr}; +use asap_types::ir::{ASAPOp, Operator, OperatorNode}; use asap_types::types::AccuracyTarget; use support::{lower_promql, post_asap_dag}; diff --git a/crates/frontend-sql/src/lib.rs b/crates/frontend-sql/src/lib.rs index 1747b09c8..4d9e6ea1f 100644 --- a/crates/frontend-sql/src/lib.rs +++ b/crates/frontend-sql/src/lib.rs @@ -3,7 +3,7 @@ //! (issue #179) → [`resolve_root`]. //! //! Emits the shared front-end tree (`UnresolvedOp` / `UnresolvedScalar`, -//! name-based [`ColumnRef`](asap_types::pre_asap::ColumnRef)s) directly, rather +//! name-based [`ColumnRef`](asap_types::ir::scalar::ColumnRef)s) directly, rather //! than a separate per-language relational tree; `resolve_root` binds it into //! the unified [`OperatorNode`] IR, deriving every schema on the way. //! Depends on DataFusion only — never on the PromQL parser. diff --git a/crates/frontend-sql/src/sql/collection_planning.rs b/crates/frontend-sql/src/sql/collection_planning.rs index 62bbbbb6d..39bf55b56 100644 --- a/crates/frontend-sql/src/sql/collection_planning.rs +++ b/crates/frontend-sql/src/sql/collection_planning.rs @@ -1,10 +1,10 @@ //! DataFusion planning adapters. Types come from the canonical signature rules; //! physical evaluation deliberately remains the query engine's responsibility. use super::types::{arrow_to_dtype, dtype_to_arrow, scalar_value_to_asap}; +use asap_types::ir::scalar::scalar_type_rules::MapScalarFunction; use asap_types::ir::scalar::{element_access_type, struct_field_type}; +use asap_types::ir::schema::{Field, Schema}; use asap_types::ir::ScalarExpr; -use asap_types::pre_asap::scalar_type_rules::MapScalarFunction; -use asap_types::pre_asap::{Field, Schema}; use datafusion::arrow::datatypes::{DataType, Field as ArrowField, FieldRef}; use datafusion::common::{DataFusionError, Result, ScalarValue as DfScalarValue}; use datafusion::logical_expr::{ diff --git a/crates/frontend-sql/src/sql/expr.rs b/crates/frontend-sql/src/sql/expr.rs index 42d38d93e..a7ea7bde1 100644 --- a/crates/frontend-sql/src/sql/expr.rs +++ b/crates/frontend-sql/src/sql/expr.rs @@ -3,8 +3,8 @@ use std::rc::Rc; use datafusion::logical_expr::{BinaryExpr, Expr, Operator}; use asap_frontend_common::UnresolvedScalar as Unresolved; +use asap_types::ir::scalar::{ArithmeticOpKind, ColumnRef, CompareOpKind, ScalarValue}; use asap_types::ir::ExprSemantics; -use asap_types::pre_asap::{ArithmeticOpKind, ColumnRef, CompareOpKind, ScalarValue}; use crate::error::SqlError as LoweringError; @@ -63,7 +63,7 @@ impl SqlLowerer<'_> { }; Ok(Unresolved::Cast { expr: Box::new(Unresolved::Literal(text)), - to: asap_types::pre_asap::schema::DataType::Date, + to: asap_types::ir::schema::DataType::Date, try_cast: false, }) } @@ -336,7 +336,7 @@ pub(super) fn split_disjuncts(expr: &Expr) -> Vec<&Expr> { mod tests { use super::*; use crate::sql::SqlCatalog; - use asap_types::pre_asap::schema::DataType; + use asap_types::ir::schema::DataType; use datafusion::common::ScalarValue as DfScalarValue; // Typed Arrow dates normalize to the same typed form as SQL date casts. diff --git a/crates/frontend-sql/src/sql/mod.rs b/crates/frontend-sql/src/sql/mod.rs index 78a067f53..81a3fac7e 100644 --- a/crates/frontend-sql/src/sql/mod.rs +++ b/crates/frontend-sql/src/sql/mod.rs @@ -57,18 +57,16 @@ use asap_frontend_common::{ UnresolvedProjectItem as ProjectItem, UnresolvedScalar as Scalar, UnresolvedSortKey as SortKey, }; use asap_sql_function_catalog::{AggSemantic, Arity, RewriteKind}; -use asap_types::ir::operator_properties::{ +use asap_types::ir::operator::agg_intent::AggIntent; +use asap_types::ir::operator::operator_properties::{ GroupKeys, Reduction, Source, WindowFrame, WindowFrameBound, WindowFrameOffset, WindowFrameUnits, }; +use asap_types::ir::schema::{DataType, FieldDataType, Schema}; use asap_types::ir::TimeRangeKind; -use asap_types::pre_asap::agg_intent::AggIntent; -use asap_types::pre_asap::schema::{DataType, FieldDataType, Schema}; -use asap_types::pre_asap::{ - resolve_column_ref, ColumnRef, CompareOpKind, JoinKind, RelationalSetOpKind, ScalarValue, - WindowFuncKind, -}; +use asap_types::ir::operator::{JoinKind, RelationalSetOpKind, WindowFuncKind}; +use asap_types::ir::scalar::{resolve_column_ref, ColumnRef, CompareOpKind, ScalarValue}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; @@ -510,7 +508,7 @@ impl<'a> SqlLowerer<'a> { .fields() .iter() .map(|f| { - Ok(asap_types::pre_asap::Field::plain( + Ok(asap_types::ir::schema::Field::plain( f.name().clone(), arrow_to_dtype(f.data_type())?, f.is_nullable(), diff --git a/crates/frontend-sql/src/sql/types.rs b/crates/frontend-sql/src/sql/types.rs index 1d178daf4..6dcaa60f0 100644 --- a/crates/frontend-sql/src/sql/types.rs +++ b/crates/frontend-sql/src/sql/types.rs @@ -9,8 +9,8 @@ use datafusion::arrow::datatypes::{ }; use datafusion::common::ScalarValue as DfScalarValue; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; -use asap_types::pre_asap::ScalarValue; +use asap_types::ir::scalar::ScalarValue; +use asap_types::ir::schema::{DataType, Field, Schema}; use crate::error::SqlError as LoweringError; @@ -364,9 +364,10 @@ mod bottom_map_tests { use super::*; #[test] fn empty_map_bottom_types_roundtrip_without_string_defaults() { - let (map, nullable) = asap_types::pre_asap::scalar_type_rules::MapScalarFunction::Construct - .output_type(&[]) - .unwrap(); + let (map, nullable) = + asap_types::ir::scalar::scalar_type_rules::MapScalarFunction::Construct + .output_type(&[]) + .unwrap(); assert!(!nullable); let arrow = dtype_to_arrow(&map); assert_eq!(arrow_to_dtype(&arrow).unwrap(), map); diff --git a/crates/frontend-sql/tests/bgp_analytics/bgp_analytics.rs b/crates/frontend-sql/tests/bgp_analytics/bgp_analytics.rs index cc24329cd..21cbbc6ef 100644 --- a/crates/frontend-sql/tests/bgp_analytics/bgp_analytics.rs +++ b/crates/frontend-sql/tests/bgp_analytics/bgp_analytics.rs @@ -38,9 +38,9 @@ use std::rc::Rc; use asap_frontend_sql::{lower_sql_dialect, SqlCatalog, SqlError as LoweringError}; +use asap_types::ir::operator::{AggIntent, GroupKeys}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{NonASAPOp, OperatorNode}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; -use asap_types::pre_asap::{AggIntent, GroupKeys}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; use datafusion::error::DataFusionError; diff --git a/crates/frontend-sql/tests/bgp_jan2024_workload/bgp_jan2024_workload.rs b/crates/frontend-sql/tests/bgp_jan2024_workload/bgp_jan2024_workload.rs index d7c750d7d..de77cd810 100644 --- a/crates/frontend-sql/tests/bgp_jan2024_workload/bgp_jan2024_workload.rs +++ b/crates/frontend-sql/tests/bgp_jan2024_workload/bgp_jan2024_workload.rs @@ -14,7 +14,7 @@ //! tally** by outcome category -- see the module doc on [`Category`] for why. use asap_frontend_sql::{lower_sql_dialect, SqlCatalog, SqlError}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; use datafusion::error::DataFusionError; diff --git a/crates/frontend-sql/tests/data_quality_check/synthetic_packet_trace.rs b/crates/frontend-sql/tests/data_quality_check/synthetic_packet_trace.rs index cce394a08..284107b51 100644 --- a/crates/frontend-sql/tests/data_quality_check/synthetic_packet_trace.rs +++ b/crates/frontend-sql/tests/data_quality_check/synthetic_packet_trace.rs @@ -22,9 +22,9 @@ use std::rc::Rc; use asap_frontend_sql::{lower_sql, SqlCatalog, SqlError as LoweringError}; +use asap_types::ir::operator::{AggIntent, GroupKeys}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{NonASAPOp, OperatorNode}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; -use asap_types::pre_asap::{AggIntent, GroupKeys}; use asap_types::types::AccuracyTarget; const CORPUS: &str = include_str!("data/synthetic_packet_trace_queries.sql"); diff --git a/crates/frontend-sql/tests/data_quality_check/tpch_deequ.rs b/crates/frontend-sql/tests/data_quality_check/tpch_deequ.rs index 83cff5ec9..85878c340 100644 --- a/crates/frontend-sql/tests/data_quality_check/tpch_deequ.rs +++ b/crates/frontend-sql/tests/data_quality_check/tpch_deequ.rs @@ -23,7 +23,7 @@ //! which is the same narrowing sidra's own catalog file makes. use asap_frontend_sql::{lower_sql, SqlCatalog, SqlError as LoweringError}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; const CORPUS: &str = include_str!("data/tpch_deequ_queries.sql"); diff --git a/crates/frontend-sql/tests/maintained_population.rs b/crates/frontend-sql/tests/maintained_population.rs index 56d4520a5..b9f78943e 100644 --- a/crates/frontend-sql/tests/maintained_population.rs +++ b/crates/frontend-sql/tests/maintained_population.rs @@ -1,14 +1,14 @@ //! SQL and PromQL use the same shared-state rule without sharing membership semantics. use asap_aware_mapping::maintained_population::MaintainedPopulationStrategy; use asap_frontend_sql::{lower_sql, SqlCatalog}; +use asap_types::ir::operator::maintained_population::{MaintainedPopulation, PopulationInput}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::{ ir::{ apply_materialization_timings, cse::share_common_sub_dags, physical_export::compile_physical_asap_dag, ASAPOp, MaterializationAssignment, NonASAPOp, Operator, OperatorNode, TimingMemo, }, - post_asap::maintained_population::{MaintainedPopulation, PopulationInput}, - pre_asap::{DataType, Field, Schema}, types::AccuracyTarget, }; use std::rc::Rc; diff --git a/crates/frontend-sql/tests/netflow/netflow.rs b/crates/frontend-sql/tests/netflow/netflow.rs index da680d664..9d06d46a6 100644 --- a/crates/frontend-sql/tests/netflow/netflow.rs +++ b/crates/frontend-sql/tests/netflow/netflow.rs @@ -7,9 +7,9 @@ use std::rc::Rc; use asap_frontend_sql::{lower_sql, SqlCatalog}; +use asap_types::ir::operator::{AggIntent, GroupKeys}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{NonASAPOp, OperatorNode}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; -use asap_types::pre_asap::{AggIntent, GroupKeys}; use asap_types::types::AccuracyTarget; const CORPUS: &str = include_str!("data/netflow.sql"); diff --git a/crates/frontend-sql/tests/pearson_corr.rs b/crates/frontend-sql/tests/pearson_corr.rs index 3604dce04..12f7856ff 100644 --- a/crates/frontend-sql/tests/pearson_corr.rs +++ b/crates/frontend-sql/tests/pearson_corr.rs @@ -2,11 +2,12 @@ use std::rc::Rc; use asap_frontend_sql::{lower_sql, SqlCatalog}; +use asap_types::ir::operator::AggIntent; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{ apply_materialization_timings, physical_export::compile_physical_asap_dag, MaterializationAssignment, NonASAPOp, OperatorNode, ScalarExpr, TimingMemo, }; -use asap_types::pre_asap::{AggIntent, DataType, Field, Schema}; use asap_types::types::AccuracyTarget; fn catalog() -> SqlCatalog { diff --git a/crates/frontend-sql/tests/sql_lowering.rs b/crates/frontend-sql/tests/sql_lowering.rs index 64888e13b..1ac7a9455 100644 --- a/crates/frontend-sql/tests/sql_lowering.rs +++ b/crates/frontend-sql/tests/sql_lowering.rs @@ -14,12 +14,13 @@ use asap_frontend_common::{UnresolvedOp, UnresolvedScalar}; use asap_frontend_sql::{ lower_sql, lower_sql_dialect, SqlCatalog, SqlError as LoweringError, SqlLowerer, }; -use asap_types::ir::{ExprSemantics, NonASAPOp, OperatorNode, ScalarExpr}; -use asap_types::pre_asap::schema::{DataType, Field, FieldDataType, Schema}; -use asap_types::pre_asap::{ - AggIntent, CompareOpKind, GroupKeys, JoinKind, Reduction, ScalarValue, Source, - WindowFrameBound, WindowFrameOffset, WindowFrameUnits, WindowFuncKind, +use asap_types::ir::operator::{ + AggIntent, GroupKeys, JoinKind, Reduction, Source, WindowFrameBound, WindowFrameOffset, + WindowFrameUnits, WindowFuncKind, }; +use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; +use asap_types::ir::schema::{DataType, Field, FieldDataType, Schema}; +use asap_types::ir::{ExprSemantics, NonASAPOp, OperatorNode, ScalarExpr}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; diff --git a/crates/frontend-sql/tests/temporal_types.rs b/crates/frontend-sql/tests/temporal_types.rs index 7e12c6f33..fb9f97607 100644 --- a/crates/frontend-sql/tests/temporal_types.rs +++ b/crates/frontend-sql/tests/temporal_types.rs @@ -1,8 +1,6 @@ use asap_frontend_sql::{lower_sql, SqlCatalog}; -use asap_types::{ - pre_asap::schema::{DataType, Field, Schema}, - types::AccuracyTarget, -}; +use asap_types::ir::schema::{DataType, Field, Schema}; +use asap_types::types::AccuracyTarget; fn catalog() -> SqlCatalog { SqlCatalog::new().with_table( "t", diff --git a/crates/integration-tests/src/lib.rs b/crates/integration-tests/src/lib.rs index 6102ca0ff..b60e0f9b8 100644 --- a/crates/integration-tests/src/lib.rs +++ b/crates/integration-tests/src/lib.rs @@ -13,8 +13,8 @@ pub mod fixtures { + use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::OperatorNode; - use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use asap_types::workload::{ AccuracyRequirement, BatchEntry, DataWorkload, DurationMs, Evidence, PlanningWorkload, diff --git a/crates/integration-tests/tests/aggregate.rs b/crates/integration-tests/tests/aggregate.rs index 13d2875b9..7010d0485 100644 --- a/crates/integration-tests/tests/aggregate.rs +++ b/crates/integration-tests/tests/aggregate.rs @@ -13,8 +13,8 @@ use std::time::Duration; use asap_integration_tests::fixtures::lower_promql; use asap_integration_tests::fixtures::metric_schema; +use asap_types::ir::operator::{AggIntent, Reduction, Source}; use asap_types::ir::{NonASAPOp, OperatorNode, TimeRangeKind}; -use asap_types::pre_asap::{AggIntent, Reduction, Source}; use asap_types::types::AccuracyTarget; fn lower(q: &str) -> Rc { diff --git a/crates/integration-tests/tests/binary_op.rs b/crates/integration-tests/tests/binary_op.rs index 284501080..7bd267e1a 100644 --- a/crates/integration-tests/tests/binary_op.rs +++ b/crates/integration-tests/tests/binary_op.rs @@ -11,11 +11,12 @@ use std::time::Duration; use asap_integration_tests::fixtures::lower_promql; use asap_integration_tests::fixtures::metric_schema; -use asap_types::ir::{BinaryOperator, NonASAPOp, OperatorNode, ScalarExpr, TimeRangeKind}; -use asap_types::pre_asap::{ - AggIntent, ArithmeticOpKind, BinaryOpKind, CompareOpKind, GroupSide, Reduction, Source, - VectorGrouping, VectorMatch, VectorMatchKind, +use asap_types::ir::operator::{ + AggIntent, BinaryOpKind, GroupSide, Reduction, Source, VectorGrouping, VectorMatch, + VectorMatchKind, }; +use asap_types::ir::scalar::{ArithmeticOpKind, CompareOpKind}; +use asap_types::ir::{BinaryOperator, NonASAPOp, OperatorNode, ScalarExpr, TimeRangeKind}; use asap_types::types::AccuracyTarget; fn lower(q: &str) -> Rc { diff --git a/crates/integration-tests/tests/exact_composition.rs b/crates/integration-tests/tests/exact_composition.rs index 3f924a0cc..b5470be5e 100644 --- a/crates/integration-tests/tests/exact_composition.rs +++ b/crates/integration-tests/tests/exact_composition.rs @@ -27,15 +27,14 @@ use asap_aware_mapping::{ use asap_integration_tests::fixtures::lower_promql; use asap_integration_tests::post_asap::{maintained, post_asap_dag, timed}; use asap_types::dag_export; -use asap_types::ir::operator_properties::{Reduction, Source}; +use asap_types::ir::data_state; +use asap_types::ir::operator::{default_quantile, AggIntent}; +use asap_types::ir::operator::{Reduction, Source}; use asap_types::ir::physical_export::PhysicalASAPOperatorPayload; -use asap_types::ir::timing::data_state; +use asap_types::ir::properties::{ExecutionDataState, ExecutionTiming}; +use asap_types::ir::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{ExactKind, FieldDataType, SketchAlgorithm, SummaryUpdate}; use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, TimeRangeKind}; -use asap_types::post_asap::{ - ExactKind, ExecutionDataState, ExecutionTiming, FieldDataType, SketchAlgorithm, SummaryUpdate, -}; -use asap_types::pre_asap::agg_intent::{default_quantile, AggIntent}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; @@ -105,9 +104,8 @@ struct StatsModel; #[test] fn custom_accuracy_rule_survives_root_target_and_materialization() { use asap_aware_mapping::{AccuracyModel, DefaultAccuracyModel, PropagationStats}; - use asap_types::post_asap::{ - AccuracyError, CompositionOperator, ResultGuarantee, SketchStatistic, - }; + use asap_types::ir::properties::{AccuracyError, CompositionOperator, ResultGuarantee}; + use asap_types::ir::schema::SketchStatistic; struct Model; impl AccuracyModel for Model { fn exact_operation_rule(&self, _: &ExactOperation) -> Option { @@ -708,9 +706,9 @@ fn summary_construction_follows_its_value_input_phase() { child: post, family: FieldDataType::ExactAggregate( ExactKind::Max, - asap_types::post_asap::ExactParams::Max, + asap_types::ir::schema::ExactParams::Max, ), - input: SummaryUpdate::column(asap_types::pre_asap::ColumnRef::SampleValue), + input: SummaryUpdate::column(asap_types::ir::scalar::ColumnRef::SampleValue), reduction: Reduction::by(vec![]), grouping: Default::default(), filter: None, diff --git a/crates/integration-tests/tests/frontend_timestamps.rs b/crates/integration-tests/tests/frontend_timestamps.rs index 300f0cee7..58de9ade9 100644 --- a/crates/integration-tests/tests/frontend_timestamps.rs +++ b/crates/integration-tests/tests/frontend_timestamps.rs @@ -2,8 +2,8 @@ use asap_frontend_sql::{lower_sql, SqlCatalog}; use asap_integration_tests::fixtures::lower_promql_root; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{NonASAPOp, ScalarExpr}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; /// PromQL exposes its evaluation time as Unix seconds, whereas SQL exposes diff --git a/crates/integration-tests/tests/kll_pane_execution.rs b/crates/integration-tests/tests/kll_pane_execution.rs index 4869d681b..99d589010 100644 --- a/crates/integration-tests/tests/kll_pane_execution.rs +++ b/crates/integration-tests/tests/kll_pane_execution.rs @@ -9,11 +9,9 @@ use asap_physical_operators::{ values::{Batch, SchemaRef, Value}, AggregateCore, Error, }; -use asap_types::{ - post_asap::{ - Field, FieldDataType, Schema, SketchAlgorithm, SketchKind, SketchParams, SketchStatistic, - }, - pre_asap::DataType, +use asap_types::ir::schema::{ + DataType, Field, FieldDataType, Schema, SketchAlgorithm, SketchKind, SketchParams, + SketchStatistic, }; use futures::{executor::block_on, StreamExt}; use std::{ @@ -165,15 +163,15 @@ fn five_panes_roundtrip_and_shared_merge_runs_once() { vec![6, 7, 8], ) .unwrap(); - let layout = asap_types::post_asap::PaneLayout { + let layout = asap_types::physical::PaneLayout { pane_width_ms: 60_000, pane_origin_ms: Some(0), }; assert!( - asap_types::post_asap::validate_pane_coverage( + asap_types::physical::validate_pane_coverage( &layout, Some(330_000), - &asap_types::post_asap::WindowEdgeCoverage::PaneAligned + &asap_types::physical::WindowEdgeCoverage::PaneAligned ) .is_err(), "moving window edges require residual computation" @@ -181,10 +179,10 @@ fn five_panes_roundtrip_and_shared_merge_runs_once() { for offset in [0, 1] { let restored = restore(schema.clone(), &panes[offset..offset + 5]); let evaluation_time_ms = (5 + offset as i64) * 60_000; - asap_types::post_asap::validate_pane_coverage( + asap_types::physical::validate_pane_coverage( &layout, Some(evaluation_time_ms), - &asap_types::post_asap::WindowEdgeCoverage::PaneAligned, + &asap_types::physical::WindowEdgeCoverage::PaneAligned, ) .unwrap(); let inputs: BTreeMap<_, _> = (0..5) diff --git a/crates/integration-tests/tests/nested.rs b/crates/integration-tests/tests/nested.rs index 26ac23a24..2bd8b8747 100644 --- a/crates/integration-tests/tests/nested.rs +++ b/crates/integration-tests/tests/nested.rs @@ -13,13 +13,14 @@ use std::time::Duration; use asap_integration_tests::fixtures::lower_promql; use asap_integration_tests::fixtures::metric_schema; +use asap_types::ir::operator::{ + AggIntent, AtModifier, BinaryOpKind, GroupKeys, PromQLVectorSetOpKind, Reduction, Source, + TimeShift, VectorMatch, VectorMatchKind, +}; +use asap_types::ir::scalar::{ArithmeticOpKind, CompareOpKind, ScalarValue}; use asap_types::ir::{ BinaryOperator, ExprSemantics, NonASAPOp, OperatorNode, Predicate, ScalarExpr, TimeRangeKind, }; -use asap_types::pre_asap::{ - AggIntent, ArithmeticOpKind, AtModifier, BinaryOpKind, CompareOpKind, GroupKeys, - PromQLVectorSetOpKind, Reduction, ScalarValue, Source, TimeShift, VectorMatch, VectorMatchKind, -}; use asap_types::types::AccuracyTarget; fn lower(q: &str) -> Rc { diff --git a/crates/integration-tests/tests/operator_design_examples.rs b/crates/integration-tests/tests/operator_design_examples.rs index dcd51088d..fb0ffe6ee 100644 --- a/crates/integration-tests/tests/operator_design_examples.rs +++ b/crates/integration-tests/tests/operator_design_examples.rs @@ -1,10 +1,12 @@ //! #511 examples: source text → unified dag → summary rewrite → flat export. use asap_frontend_sql::{lower_sql, SqlCatalog}; -use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, ScalarExpr}; -use asap_types::post_asap::{ +use asap_types::ir::operator::AggIntent; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{ ExactKind, ExactParams, FieldDataType, GroupingStrategy, SummaryUpdate, }; -use asap_types::pre_asap::{AggIntent, ColumnRef, DataType, Field, Schema}; +use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, ScalarExpr}; use asap_types::types::AccuracyTarget; use std::rc::Rc; mod physical_common; diff --git a/crates/integration-tests/tests/operator_sharing.rs b/crates/integration-tests/tests/operator_sharing.rs index 6a87a879a..5a102e4f8 100644 --- a/crates/integration-tests/tests/operator_sharing.rs +++ b/crates/integration-tests/tests/operator_sharing.rs @@ -12,8 +12,8 @@ use std::rc::Rc; use asap_aware_mapping::{search_workload, DefaultCostModel}; use asap_frontend_sql::{lower_sql, SqlCatalog}; use asap_integration_tests::post_asap::post_asap_dag; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; fn col(name: &str, dtype: DataType) -> Field { diff --git a/crates/integration-tests/tests/planner_layering_example1.rs b/crates/integration-tests/tests/planner_layering_example1.rs index 6fba769c1..1f3a88b55 100644 --- a/crates/integration-tests/tests/planner_layering_example1.rs +++ b/crates/integration-tests/tests/planner_layering_example1.rs @@ -15,9 +15,9 @@ use std::collections::{BTreeMap, BTreeSet, HashSet}; use asap_aware_mapping::PlanningModels; use asap_types::ir::flat::{flatten, FlatDag, NodeId}; +use asap_types::ir::schema::FieldDataType; +use asap_types::ir::schema::{GroupingStrategy, HydraKind, SketchAlgorithm}; use asap_types::ir::{ASAPOp, Operator}; -use asap_types::post_asap::sketch::{GroupingStrategy, HydraKind, SketchAlgorithm}; -use asap_types::pre_asap::schema::FieldDataType; use asap_types::types::AccuracyTarget; use asap_types::workload::{ AccuracyRequirement, DataArrival, DataDistribution, DataWorkload, DurationMs, Evidence, @@ -265,7 +265,7 @@ mod stages { .expect("node") .output_state .timing - == asap_types::post_asap::ExecutionTiming::IngestionTime + == asap_types::ir::properties::ExecutionTiming::IngestionTime } } diff --git a/crates/integration-tests/tests/precompute_raw_samples.rs b/crates/integration-tests/tests/precompute_raw_samples.rs index 9dc831097..f553f42de 100644 --- a/crates/integration-tests/tests/precompute_raw_samples.rs +++ b/crates/integration-tests/tests/precompute_raw_samples.rs @@ -22,11 +22,12 @@ use asap_physical_operators::{ values::{Batch, Value}, AggregateCore, KeyByLabelValues, Statistic, }; -use asap_types::post_asap::{ +use asap_types::ir::operator::Reduction; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{ EntityIdentity, ExactKind, FieldDataType, SketchAlgorithm, SketchStatistic, SummaryInputExpr, SummaryUpdate, }; -use asap_types::pre_asap::{expr_ir::ColumnRef, Reduction}; use asap_types::types::AccuracyTarget; use futures::{executor::block_on, StreamExt}; @@ -315,7 +316,7 @@ fn check( Reduction::PerEntity => vec![], }; let stored_only = matches!(family, FieldDataType::Sketch(kind, _) - if kind.algorithm() == &asap_types::post_asap::SketchAlgorithm::Cms); + if kind.algorithm() == &asap_types::ir::schema::SketchAlgorithm::Cms); if stored_only || asap_physical_operators::capability::validate_native_family(family).is_err() { // Families without a native state (e.g. UnivMon), or with native // stored state only (plain CMS), are outside precompute execution; @@ -499,10 +500,8 @@ fn grouped_raw_summary(family: FieldDataType, input: SummaryUpdate) -> (Physical // estimate each item's exact total; invalid weight contracts do not compile. #[test] fn raw_sample_heaps_resolve_items_from_labels() { - use asap_types::post_asap::{ - GroupingStrategy::PerSubpopulationInstance, NonNegativeWeightProof, SketchKind, - SketchParams, WeightDomain, - }; + use asap_types::ir::schema::GroupingStrategy::PerSubpopulationInstance; + use asap_types::ir::schema::{NonNegativeWeightProof, SketchKind, SketchParams, WeightDomain}; let heap = |algorithm, params| { FieldDataType::Sketch(SketchKind::new(algorithm, params), PerSubpopulationInstance) }; @@ -583,9 +582,9 @@ fn raw_sample_heaps_resolve_items_from_labels() { // `without` grouping over raw samples drops the listed labels and `__name__`. #[test] fn raw_sample_without_grouping_drops_labels_and_name() { - use asap_types::pre_asap::GroupKeys; + use asap_types::ir::operator::GroupKeys; let family = - FieldDataType::ExactAggregate(ExactKind::Sum, asap_types::post_asap::ExactParams::Sum); + FieldDataType::ExactAggregate(ExactKind::Sum, asap_types::ir::schema::ExactParams::Sum); let (mut dag, source, root) = grouped_raw_summary(family, SummaryUpdate::column(ColumnRef::SampleValue)); let service = dag diff --git a/crates/integration-tests/tests/promql_numeric_regressions.rs b/crates/integration-tests/tests/promql_numeric_regressions.rs index 3ec4d8eac..b844849e7 100644 --- a/crates/integration-tests/tests/promql_numeric_regressions.rs +++ b/crates/integration-tests/tests/promql_numeric_regressions.rs @@ -4,9 +4,10 @@ use asap_aware_mapping::replacement::is_logical_rewrite; use asap_aware_mapping::{ASAPStrategies, Replacement, ReplacementStrategy, TargetSubDAG}; use asap_integration_tests::fixtures::lower_promql; use asap_integration_tests::post_asap::post_asap_dag; +use asap_types::ir::operator::Reduction; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{ExactKind, FieldDataType, SummaryInputExpr, SummaryUpdate}; use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}; -use asap_types::post_asap::{ExactKind, FieldDataType, SummaryInputExpr, SummaryUpdate}; -use asap_types::pre_asap::{ColumnRef, Reduction}; use asap_types::types::AccuracyTarget; use std::rc::Rc; @@ -175,14 +176,14 @@ struct OneKeyTopKEvidence; impl asap_aware_mapping::accuracy::AccuracyEvidenceProvider for OneKeyTopKEvidence { fn propagation_stats( &self, - op: &asap_types::post_asap::CompositionOperator, + op: &asap_types::ir::properties::CompositionOperator, _family: &FieldDataType, - _query: Option<&asap_types::post_asap::SketchStatistic>, + _query: Option<&asap_types::ir::schema::SketchStatistic>, ) -> asap_aware_mapping::accuracy::PropagationStats { // Single-key fixture: no excluded keys; bounds cover every value below. if matches!( op, - asap_types::post_asap::CompositionOperator::TopKSelection + asap_types::ir::properties::CompositionOperator::TopKSelection ) { asap_aware_mapping::accuracy::PropagationStats { topk_selected_lower_bound: Some(-1000.), @@ -200,7 +201,7 @@ impl asap_aware_mapping::accuracy::AccuracyEvidenceProvider for OneKeyTopKEviden fn sketch_counts_use_unit_weights_and_signed_sums_keep_value_weights() { use asap_aware_mapping::accuracy::{DefaultAccuracyModel, EqualSplitAllocator}; use asap_aware_mapping::cost_model::DefaultCostModel; - use asap_types::post_asap::{NonNegativeWeightProof, SketchAlgorithm, WeightDomain}; + use asap_types::ir::schema::{NonNegativeWeightProof, SketchAlgorithm, WeightDomain}; let strategy = ASAPStrategies::new_with_planning_inputs_and_evidence( &DefaultCostModel, &DefaultAccuracyModel, diff --git a/crates/integration-tests/tests/promql_to_post_asap.rs b/crates/integration-tests/tests/promql_to_post_asap.rs index 3b8a6edb9..dbc3bc288 100644 --- a/crates/integration-tests/tests/promql_to_post_asap.rs +++ b/crates/integration-tests/tests/promql_to_post_asap.rs @@ -22,16 +22,16 @@ use asap_integration_tests::fixtures::lower_promql; use asap_integration_tests::post_asap::{ maintained, maintained_post_asap_dag, post_asap_dag, timed, }; -use asap_types::ir::operator_properties::Reduction; +use asap_types::ir::operator::Reduction; use asap_types::ir::physical_export::PhysicalASAPOperatorPayload; -use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, ScalarExpr}; -use asap_types::post_asap::{ - CompositionOperator, EntityIdentity, ExactKind, ExactParams, FieldDataType, GroupingStrategy, - Schema, SketchAlgorithm, SketchKind, SketchParams, SketchStatistic, SummaryInputExpr, - SummaryUpdate, +use asap_types::ir::properties::CompositionOperator; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::DataType; +use asap_types::ir::schema::{ + EntityIdentity, ExactKind, ExactParams, FieldDataType, GroupingStrategy, Schema, + SketchAlgorithm, SketchKind, SketchParams, SketchStatistic, SummaryInputExpr, SummaryUpdate, }; -use asap_types::pre_asap::expr_ir::ColumnRef; -use asap_types::pre_asap::schema::DataType; +use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, ScalarExpr}; use asap_types::types::AccuracyTarget; /// This crate has no "bind me one tree" public API any more — @@ -115,7 +115,7 @@ fn value_ranked_topk_preserves_summary_children_in_post_asap_dag() { }; assert_eq!( root.timing, - Some(asap_types::post_asap::ExecutionTiming::QueryTime) + Some(asap_types::ir::properties::ExecutionTiming::QueryTime) ); assert!(n.is_some_and(|n| n > 0) && *offset == 0); let Some(NonASAPOp::Sort { child, .. }) = sort.non_asap() else { @@ -123,7 +123,7 @@ fn value_ranked_topk_preserves_summary_children_in_post_asap_dag() { }; assert_eq!( sort.timing, - Some(asap_types::post_asap::ExecutionTiming::QueryTime) + Some(asap_types::ir::properties::ExecutionTiming::QueryTime) ); let Some(ASAPOp::FinalizeExactAccumulator { child: state }) = child.asap() else { panic!( @@ -298,7 +298,7 @@ fn grouped_rate_topk_consumes_finalized_rate_values() { .unwrap(); assert_eq!( node.output_state.timing, - asap_types::post_asap::ExecutionTiming::QueryTime + asap_types::ir::properties::ExecutionTiming::QueryTime ); let PhysicalASAPOperatorPayload::ASAP(ASAPOp::SummaryAgg { input, .. }) = &node.payload else { unreachable!() @@ -478,8 +478,8 @@ fn rate_and_increase_topk_use_summary_scores_and_grouped_limits() { )); let dag = post_asap_dag(&plan); for phase in [ - asap_types::post_asap::ExecutionTiming::IngestionTime, - asap_types::post_asap::ExecutionTiming::QueryTime, + asap_types::ir::properties::ExecutionTiming::IngestionTime, + asap_types::ir::properties::ExecutionTiming::QueryTime, ] { let phases = dag.nodes.iter().map(|node| (node.id, phase)).collect(); let placed = dag.with_execution_phases(&phases).unwrap(); @@ -491,8 +491,8 @@ fn rate_and_increase_topk_use_summary_scores_and_grouped_limits() { let guarantee = plan.guarantee.as_ref().unwrap(); assert!(guarantee.failure_probability.evaluate().unwrap() <= 0.01); assert!(guarantee.provenance.iter().any(|source| matches!(source, - asap_types::post_asap::GuaranteeSource::ChildGuarantee { guarantee, .. } - if guarantee.metric == asap_types::post_asap::ErrorMetric::Frequency))); + asap_types::ir::properties::GuaranteeSource::ChildGuarantee { guarantee, .. } + if guarantee.metric == asap_types::ir::properties::ErrorMetric::Frequency))); } } @@ -725,7 +725,7 @@ fn execute_topk_reference(plan: &OperatorNode) -> Vec<(String, f64)> { panic!("expected temporal input") }; let Some(NonASAPOp::Scan { - source: asap_types::pre_asap::Source::TimeSeries { metric }, + source: asap_types::ir::operator::Source::TimeSeries { metric }, predicates, .. }) = child.non_asap() @@ -1037,7 +1037,7 @@ fn promql_sum_of_count_over_time_is_composed_by_default_search() { assert_eq!(by.keys(), &[2]); assert!(matches!( measures.as_slice(), - [asap_types::pre_asap::AggIntent::Count { + [asap_types::ir::operator::AggIntent::Count { accuracy: AccuracyTarget::Exact }] )); @@ -1080,7 +1080,7 @@ fn nested_summary_explicitly_finalizes_exact_child_at_ingestion_time() { }; assert_eq!( child.timing, - Some(asap_types::post_asap::ExecutionTiming::IngestionTime) + Some(asap_types::ir::properties::ExecutionTiming::IngestionTime) ); assert!(matches!( source.asap(), @@ -1105,7 +1105,7 @@ fn nested_summary_explicitly_finalizes_exact_child_at_ingestion_time() { #[test] fn physical_node_owns_phase_independently_of_binary_payload() { - use asap_types::post_asap::ExecutionTiming; + use asap_types::ir::properties::ExecutionTiming; for (query, expected) in [ ( // One selector: both operands cover the same series. @@ -1252,7 +1252,7 @@ fn ddsketch_ratio_rejects_one_invalid_domain_when_the_other_is_missing() { }; matches!( measures.as_slice(), - [asap_types::pre_asap::agg_intent::AggIntent::Quantile { q, .. }] if *q == 0.9 + [asap_types::ir::operator::agg_intent::AggIntent::Quantile { q, .. }] if *q == 0.9 ) .then(|| QuantileInputDomain { lower: -1.0, diff --git a/crates/integration-tests/tests/scan.rs b/crates/integration-tests/tests/scan.rs index e43e27a6c..1aff439c1 100644 --- a/crates/integration-tests/tests/scan.rs +++ b/crates/integration-tests/tests/scan.rs @@ -11,10 +11,11 @@ use std::time::Duration; use asap_integration_tests::fixtures::lower_promql; use asap_integration_tests::fixtures::metric_schema; +use asap_types::ir::operator::Source; +use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; use asap_types::ir::{ ExprSemantics, NonASAPOp, OperatorNode, Predicate, ScalarExpr, TimeRangeKind, }; -use asap_types::pre_asap::{CompareOpKind, ScalarValue, Source}; use asap_types::types::AccuracyTarget; fn lower(q: &str) -> Rc { diff --git a/crates/integration-tests/tests/sql_to_physical.rs b/crates/integration-tests/tests/sql_to_physical.rs index ed9c52fe9..7f9c988d6 100644 --- a/crates/integration-tests/tests/sql_to_physical.rs +++ b/crates/integration-tests/tests/sql_to_physical.rs @@ -9,11 +9,9 @@ use asap_physical_operators::{ values::{Batch, Value}, }; use asap_types::ir::physical_export::PhysicalASAPOperatorPayload; -use asap_types::{ - post_asap::FieldDataType, - pre_asap::{DataType, Field, Schema}, - types::AccuracyTarget, -}; +use asap_types::ir::schema::FieldDataType; +use asap_types::ir::schema::{DataType, Field, Schema}; +use asap_types::types::AccuracyTarget; use futures::StreamExt; use physical_common::compile_physical_asap_dag; use std::{collections::BTreeMap, sync::Arc}; diff --git a/crates/integration-tests/tests/sql_to_post_asap.rs b/crates/integration-tests/tests/sql_to_post_asap.rs index 3121e99cb..3bcfc2c55 100644 --- a/crates/integration-tests/tests/sql_to_post_asap.rs +++ b/crates/integration-tests/tests/sql_to_post_asap.rs @@ -26,15 +26,15 @@ use asap_aware_mapping::{ }; use asap_frontend_sql::{lower_sql, lower_sql_dialect, SqlCatalog}; use asap_integration_tests::post_asap::post_asap_dag; -use asap_types::ir::operator_properties::Reduction; +use asap_types::ir::operator::Reduction; use asap_types::ir::physical_export::{EdgeRole, PhysicalASAPNodeId, PhysicalASAPOperatorPayload}; -use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, Predicate, ScalarExpr}; -use asap_types::post_asap::{ +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{ ExactKind, ExactParams, FieldDataType, GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SketchStatistic, SummaryUpdate, }; -use asap_types::pre_asap::expr_ir::ColumnRef; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; +use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, Predicate, ScalarExpr}; use asap_types::types::AccuracyTarget; use asap_types::workload::SqlDialect; @@ -319,7 +319,7 @@ async fn sql_join_recursively_binds_both_temporal_aggregate_children() { assert!(matches!( &cols[1].expr, ScalarExpr::Arithmetic { - op: asap_types::pre_asap::ArithmeticOpKind::Div, + op: asap_types::ir::scalar::ArithmeticOpKind::Div, .. } )); @@ -335,12 +335,12 @@ async fn sql_join_recursively_binds_both_temporal_aggregate_children() { join.operator ); }; - assert_eq!(kind, &asap_types::pre_asap::JoinKind::Inner); + assert_eq!(kind, &asap_types::ir::operator::JoinKind::Inner); assert!(matches!( &pred.0, ScalarExpr::Compare { left, - op: asap_types::pre_asap::CompareOpKind::Eq, + op: asap_types::ir::scalar::CompareOpKind::Eq, right, .. } if matches!(left.as_ref(), ScalarExpr::Column(0)) diff --git a/crates/integration-tests/tests/summary_coverage_e2e.rs b/crates/integration-tests/tests/summary_coverage_e2e.rs index b5936f059..c621e3a47 100644 --- a/crates/integration-tests/tests/summary_coverage_e2e.rs +++ b/crates/integration-tests/tests/summary_coverage_e2e.rs @@ -9,11 +9,10 @@ use std::rc::Rc; use asap_aware_mapping::{search_workload, DefaultCostModel}; use asap_frontend_sql::{lower_sql, SqlCatalog}; use asap_integration_tests::fixtures::lower_promql; -use asap_types::ir::summary_coverage::{ColumnIdentity, Constraint, SelectionBox}; +use asap_types::ir::properties::summary_coverage::{ColumnIdentity, Constraint, SelectionBox}; +use asap_types::ir::scalar::ScalarValue; +use asap_types::ir::schema::{DataType, Field, FieldDataType, Schema, SketchAlgorithm}; use asap_types::ir::{ASAPOp, NonASAPOp, OperatorNode, Predicate, ScalarExpr}; -use asap_types::post_asap::{FieldDataType, SketchAlgorithm}; -use asap_types::pre_asap::expr_ir::ScalarValue; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; fn accuracy() -> AccuracyTarget { diff --git a/crates/integration-tests/tests/time_range.rs b/crates/integration-tests/tests/time_range.rs index 95212ca99..eb7955d9a 100644 --- a/crates/integration-tests/tests/time_range.rs +++ b/crates/integration-tests/tests/time_range.rs @@ -12,8 +12,8 @@ use std::time::Duration; use asap_integration_tests::fixtures::lower_promql; use asap_integration_tests::fixtures::metric_schema; +use asap_types::ir::operator::{AggIntent, Reduction, Source}; use asap_types::ir::{NonASAPOp, OperatorNode, TimeRangeKind}; -use asap_types::pre_asap::{AggIntent, Reduction, Source}; use asap_types::types::AccuracyTarget; fn lower(q: &str) -> Rc { diff --git a/crates/planner/src/lib.rs b/crates/planner/src/lib.rs index 506ed12ea..f9be28420 100644 --- a/crates/planner/src/lib.rs +++ b/crates/planner/src/lib.rs @@ -11,7 +11,7 @@ //! and a catalog — skips this crate and calls //! [`asap_aware_mapping::optimize`] directly. -use asap_types::parsed_workload::{ParsedWorkload, ParsedWorkloadError}; +use asap_types::workload::parsed_workload::{ParsedWorkload, ParsedWorkloadError}; use asap_types::workload::{PlanningWorkload, QueryLanguage, SqlDialect, WorkloadError}; use asap_frontend_metricsql::{lower_metricsql_query, MetricsqlError}; diff --git a/crates/planner/tests/e2e_plan.rs b/crates/planner/tests/e2e_plan.rs index 0f929c96d..17eadb033 100644 --- a/crates/planner/tests/e2e_plan.rs +++ b/crates/planner/tests/e2e_plan.rs @@ -10,7 +10,7 @@ use asap_aware_mapping::replacement::default_strategies_with_evidence; use asap_aware_mapping::search_workload_with_targets; use asap_frontend_sql::{lower_sql_dialect, SqlCatalog}; use asap_planner::{e2e_plan, FrontendInput, PlanError, UserInput, UserInputError}; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::types::AccuracyTarget; use asap_types::workload::{ AccuracyRequirement, BatchEntry, DataArrival, DataWorkload, DurationMs, Evidence, diff --git a/crates/planner/tests/summary_sharing.rs b/crates/planner/tests/summary_sharing.rs index 8eb9ed4f8..d848814be 100644 --- a/crates/planner/tests/summary_sharing.rs +++ b/crates/planner/tests/summary_sharing.rs @@ -17,14 +17,14 @@ use asap_aware_mapping::{ use asap_frontend_promql::lower_promql_workload; use asap_frontend_sql::SqlCatalog; use asap_planner::{e2e_plan, FrontendInput, UserInput}; -use asap_types::post_asap::{ +use asap_types::ir::operator::agg_intent::default_quantile; +use asap_types::ir::operator::AggIntent; +use asap_types::ir::properties::{ AccuracyError, BoundExpr, CompositionOperator, ErrorMetric, ProbabilityExpr, ResultGuarantee, - SketchStatistic, }; -use asap_types::post_asap::{FieldDataType, SketchAlgorithm, SketchKind, SketchParams}; -use asap_types::pre_asap::agg_intent::default_quantile; -use asap_types::pre_asap::schema::{DataType, Field, Schema}; -use asap_types::pre_asap::AggIntent; +use asap_types::ir::schema::SketchStatistic; +use asap_types::ir::schema::{DataType, Field, Schema}; +use asap_types::ir::schema::{FieldDataType, SketchAlgorithm, SketchKind, SketchParams}; use asap_types::types::AccuracyTarget; use asap_types::workload::{ AccuracyRequirement, DataArrival, DataWorkload, DurationMs, Evidence, LatencyRequirement, diff --git a/crates/sql-function-catalog/src/lib.rs b/crates/sql-function-catalog/src/lib.rs index f2aedbaa9..6b2a0ceb5 100644 --- a/crates/sql-function-catalog/src/lib.rs +++ b/crates/sql-function-catalog/src/lib.rs @@ -74,7 +74,7 @@ pub enum Arity { /// classification [`lower_agg_intent`](../asap_frontend_sql/index.html) /// switches on to build the real `AggIntent`. /// -/// Deliberately *not* `asap_types::pre_asap::agg_intent::AggIntent` itself: +/// Deliberately *not* `asap_types::ir::operator::agg_intent::AggIntent` itself: /// most `AggIntent` variants carry call-site-only state that isn't a /// function of the name alone -- the ambient `AccuracyTarget` (thread-local, /// not catalog data), φ pulled from a call's literal 2nd argument, whether diff --git a/crates/types/src/dag_export.rs b/crates/types/src/dag_export.rs index 9efbd66c5..de9883a0d 100644 --- a/crates/types/src/dag_export.rs +++ b/crates/types/src/dag_export.rs @@ -62,10 +62,10 @@ use serde::Serialize; use crate::cost::CostAnnotation; use crate::ir::cse::{structural_hash, HashCache}; -use crate::ir::operator_properties::Source; +use crate::ir::operator::operator_properties::Source; +use crate::ir::properties::{AccuracyError, ResultGuarantee}; +use crate::ir::schema::FieldDataType; use crate::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, ScalarExpr}; -use crate::post_asap::{AccuracyError, ResultGuarantee}; -use crate::pre_asap::schema::FieldDataType; /// One flattened IR node. `detail` holds this node's own scalar fields /// (predicates, aggregate funcs, schema, sort keys, …) — everything except @@ -1062,15 +1062,17 @@ mod tests { use std::rc::Rc; use super::*; - use crate::ir::operator_properties::{GroupKeys, JoinKind, Reduction}; - use crate::ir::Predicate; - use crate::post_asap::{ - BoundExpr, CompositionOperator, ErrorMetric, GroupingStrategy, GuaranteeSource, - ProbabilityExpr, SketchAlgorithm, SketchKind, SketchParams, SketchStatistic, SummaryUpdate, + use crate::ir::operator::agg_intent::AggIntent; + use crate::ir::operator::operator_properties::{GroupKeys, JoinKind, Reduction}; + use crate::ir::properties::{ + BoundExpr, CompositionOperator, ErrorMetric, GuaranteeSource, ProbabilityExpr, + }; + use crate::ir::scalar::{ColumnRef, ScalarValue}; + use crate::ir::schema::{DataType, Field, Schema}; + use crate::ir::schema::{ + GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SketchStatistic, SummaryUpdate, }; - use crate::pre_asap::agg_intent::AggIntent; - use crate::pre_asap::expr_ir::{ColumnRef, ScalarValue}; - use crate::pre_asap::schema::{DataType, Field, Schema}; + use crate::ir::Predicate; use crate::types::AccuracyTarget; @@ -1728,7 +1730,7 @@ mod tests { ); let root = OperatorNode::new_shared(crate::ir::Operator::NonASAP(NonASAPOp::SQLWindowFunc { - func: crate::ir::operator_properties::WindowFuncKind::RowNumber, + func: crate::ir::operator::operator_properties::WindowFuncKind::RowNumber, args: vec![], partition_by: GroupKeys::none(), order_by: vec![], diff --git a/crates/types/src/ir/canonicalize.rs b/crates/types/src/ir/canonicalize.rs index 691ba6610..dcdd91da6 100644 --- a/crates/types/src/ir/canonicalize.rs +++ b/crates/types/src/ir/canonicalize.rs @@ -30,13 +30,13 @@ use std::collections::HashMap; use std::rc::Rc; -use super::node::{Operator, OperatorNode}; -use super::non_asap::NonASAPOp; -use super::scalar::{ExprSemantics, Predicate, ProjectItem, ScalarExpr, SortKey}; -use crate::ir::operator_properties::{JoinKind, Reduction}; +use crate::ir::operator::agg_intent::{topk, AggIntent}; +use crate::ir::operator::node::{Operator, OperatorNode}; +use crate::ir::operator::non_asap::NonASAPOp; +use crate::ir::operator::operator_properties::{JoinKind, Reduction}; +use crate::ir::scalar::{CompareOpKind, ScalarValue}; +use crate::ir::scalar::{ExprSemantics, Predicate, ProjectItem, ScalarExpr, SortKey}; use crate::ir::SchemaDerivationError; -use crate::pre_asap::agg_intent::{topk, AggIntent}; -use crate::pre_asap::expr_ir::{CompareOpKind, ScalarValue}; use crate::types::AccuracyTarget; /// Rewrite the DAG under `root` into its canonical form (bottom-up). @@ -367,12 +367,12 @@ fn contains_scalar_subquery(expr: &ScalarExpr) -> bool { #[cfg(test)] mod tests { use super::*; - use crate::ir::operator_properties::WindowFuncKind; - use crate::ir::operator_properties::{ + use crate::ir::operator::operator_properties::WindowFuncKind; + use crate::ir::operator::operator_properties::{ ConcatDiscriminatorKey, GroupKeys, Source, WindowFrame, WindowFrameBound, WindowFrameOffset, WindowFrameUnits, }; - use crate::pre_asap::schema::{DataType, Field, Schema}; + use crate::ir::schema::{DataType, Field, Schema}; fn node(op: NonASAPOp) -> Rc { Rc::new(OperatorNode::new(Operator::NonASAP(op)).expect("fixture derives a schema")) diff --git a/crates/types/src/ir/cse.rs b/crates/types/src/ir/cse.rs index c229772f7..ef903d2e5 100644 --- a/crates/types/src/ir/cse.rs +++ b/crates/types/src/ir/cse.rs @@ -55,7 +55,7 @@ use std::collections::HashMap; use std::hash::{Hash, Hasher}; use std::rc::Rc; -use super::node::{Operator, OperatorNode}; +use super::operator::node::{Operator, OperatorNode}; /// [`structural_hash`]'s memoization cache: an already-hashed node's `Rc` /// pointer to its hash. A fresh cache is always correct; what matters is @@ -277,17 +277,17 @@ pub fn share_common_sub_dags( #[cfg(test)] mod tests { use super::*; - use crate::ir::asap::ASAPOp; - use crate::ir::operator_properties::{BinaryOpKind, GroupKeys, Reduction, Source}; - use crate::ir::ScalarExpr; - use crate::ir::{BinaryOperator, NonASAPOp}; - use crate::post_asap::guarantee::ResultGuarantee; - use crate::post_asap::sketch::{ + use crate::ir::operator::AggIntent; + use crate::ir::operator::{BinaryOpKind, GroupKeys, Reduction, Source}; + use crate::ir::properties::ResultGuarantee; + use crate::ir::scalar::{ColumnRef, CompareOpKind}; + use crate::ir::schema::{DataType, Field, FieldDataType, Schema}; + use crate::ir::schema::{ GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate, }; - use crate::pre_asap::agg_intent::AggIntent; - use crate::pre_asap::expr_ir::{ColumnRef, CompareOpKind}; - use crate::pre_asap::schema::{DataType, Field, FieldDataType, Schema}; + use crate::ir::ASAPOp; + use crate::ir::ScalarExpr; + use crate::ir::{BinaryOperator, NonASAPOp}; use crate::types::AccuracyTarget; @@ -532,7 +532,7 @@ mod tests { #[test] fn evaluations_share_their_producer_but_not_each_other() { - use crate::post_asap::sketch::SketchStatistic; + use crate::ir::schema::SketchStatistic; let evaluation = |q: f64| { Rc::new(OperatorNode::with_schema( Operator::ASAP(ASAPOp::SummaryEstimate { diff --git a/crates/types/src/ir/flat.rs b/crates/types/src/ir/flat.rs index 434a3406f..e1f3eb12a 100644 --- a/crates/types/src/ir/flat.rs +++ b/crates/types/src/ir/flat.rs @@ -13,11 +13,11 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; -use super::node::{Operator, OperatorNode, OperatorResultKind}; +use super::operator::node::{Operator, OperatorNode, OperatorResultKind}; use super::query::QueryRoot; -use crate::post_asap::execution_data_state::ExecutionTiming; -use crate::post_asap::guarantee::ResultGuarantee; -use crate::pre_asap::schema::Schema; +use crate::ir::properties::ExecutionTiming; +use crate::ir::properties::ResultGuarantee; +use crate::ir::schema::Schema; /// Index of a node in [`FlatDag::nodes`]. pub type NodeId = usize; @@ -86,9 +86,9 @@ fn visit( #[cfg(test)] mod tests { use super::*; + use crate::ir::scalar::ScalarValue; + use crate::ir::schema::{DataType, Field}; use crate::ir::{NonASAPOp, Predicate, ProjectItem, ScalarExpr}; - use crate::pre_asap::expr_ir::ScalarValue; - use crate::pre_asap::schema::{DataType, Field}; fn values() -> Rc { OperatorNode::new_shared(Operator::NonASAP(NonASAPOp::Values { diff --git a/crates/types/src/ir/mod.rs b/crates/types/src/ir/mod.rs index 6996fafdd..62aed5a59 100644 --- a/crates/types/src/ir/mod.rs +++ b/crates/types/src/ir/mod.rs @@ -1,30 +1,32 @@ //! The operator IR from #511: one operator DAG for every planning stage. -pub mod aggregate_schema; -pub mod asap; -pub mod error; -pub mod node; -pub mod non_asap; -pub mod operator_properties; +//! +//! - [`operator`] — §1 operators: [`OperatorNode`] and its operator families. +//! - [`scalar`] — §2.2 scalar expressions and column references. +//! - [`schema`] — §2.1 per-edge [`schema::Schema`] and summary state types. +//! - [`properties`] — §2.2–2.3 node properties: accuracy guarantees, execution +//! timing, and summary coverage. +//! - [`flat`], [`physical_export`], [`cse`], [`canonicalize`] — DAG passes and +//! transport. +pub mod operator; +pub mod properties; pub mod query; pub mod scalar; -pub use asap::{ASAPOp, UNIMPLEMENTED_ASAP_OP}; -pub use error::SchemaDerivationError; -pub use node::{Operator, OperatorNode, OperatorResultKind}; -pub use non_asap::{BinaryOperator, NonASAPOp, TimeRangeKind}; +pub mod schema; +pub use operator::asap::{ASAPOp, UNIMPLEMENTED_ASAP_OP}; +pub use operator::node::{Operator, OperatorNode, OperatorResultKind}; +pub use operator::non_asap::{BinaryOperator, NonASAPOp, TimeRangeKind}; pub use query::QueryRoot; pub use scalar::{ExprSemantics, Predicate, ProjectItem, ScalarExpr, SortKey}; +pub use schema::error::SchemaDerivationError; pub mod canonicalize; pub mod cse; pub mod flat; /// Physical ASAP DAG: the flattened operators plus execution timing. pub mod physical_export; -/// Execution timing for physical plans: a materialization assignment expanded onto every node. -pub mod timing; -pub use timing::{ +pub use properties::timing::{ apply_materialization_timings, data_state, planned_data_state, split_shared_by_phase, validate_maintained, MaterializationAssignment, TimingMemo, }; + pub mod schema_support; -/// Semantic observation coverage, separate from field layout and physical timing. -pub mod summary_coverage; diff --git a/crates/types/src/pre_asap/agg_intent.rs b/crates/types/src/ir/operator/agg_intent.rs similarity index 98% rename from crates/types/src/pre_asap/agg_intent.rs rename to crates/types/src/ir/operator/agg_intent.rs index 1e926bd44..d388c6910 100644 --- a/crates/types/src/pre_asap/agg_intent.rs +++ b/crates/types/src/ir/operator/agg_intent.rs @@ -15,8 +15,8 @@ use serde::{Deserialize, Serialize}; -use crate::ir::operator_properties::DataModel; -use crate::pre_asap::schema::{ColumnId, DataType, Field, FieldDataType}; +use crate::ir::operator::operator_properties::DataModel; +use crate::ir::schema::{ColumnId, DataType, Field, FieldDataType}; use crate::types::AccuracyTarget; /// "What to compute" — the vocabulary the planner pivots on. @@ -392,7 +392,7 @@ impl AggIntent { /// malformed selectors fail instead of acquiring a fabricated output type. pub fn arg_selector_columns( &self, - schema: &super::schema::Schema, + schema: &crate::ir::schema::Schema, ) -> Result, String> { let Self::Extension { ext_kind, payload } = self else { return Ok(None); @@ -407,14 +407,14 @@ impl AggIntent { return Err("arg selector requires arg_col and val_col only".into()); } let resolve = |field: &str| -> Result { - let reference: super::expr_ir::ColumnRef = serde_json::from_value( + let reference: crate::ir::scalar::ColumnRef = serde_json::from_value( fields .get(field) .ok_or_else(|| format!("missing arg selector {field}"))? .clone(), ) .map_err(|e| e.to_string())?; - super::column_resolution::resolve_column_ref(&reference, schema) + crate::ir::scalar::column_resolution::resolve_column_ref(&reference, schema) .map_err(|e| e.to_string()) }; Ok(Some((resolve("arg_col")?, resolve("val_col")?))) @@ -738,7 +738,7 @@ pub fn default_quantile(q: f64) -> AggIntent { #[cfg(test)] mod tests { use super::*; - use crate::pre_asap::schema::{DataType, Field}; + use crate::ir::schema::{DataType, Field}; fn c(name: &str, dtype: DataType) -> Field { Field::plain(name, dtype, false) @@ -966,7 +966,8 @@ mod tests { #[cfg(test)] mod arg_selector_contract_tests { use super::*; - use crate::pre_asap::{ColumnRef, Schema}; + use crate::ir::scalar::ColumnRef; + use crate::ir::schema::Schema; #[test] fn arg_selector_rejects_missing_or_unresolved_arguments() { let schema = Schema::new(vec![Field::plain("value", DataType::Float64, false)]); diff --git a/crates/types/src/ir/asap.rs b/crates/types/src/ir/operator/asap.rs similarity index 93% rename from crates/types/src/ir/asap.rs rename to crates/types/src/ir/operator/asap.rs index a434bc09e..f3ca39e4f 100644 --- a/crates/types/src/ir/asap.rs +++ b/crates/types/src/ir/operator/asap.rs @@ -5,12 +5,12 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; -use super::node::{OperatorNode, OperatorResultKind}; -use crate::ir::operator_properties::Reduction; +use crate::ir::operator::maintained_population::{MaintainedPopulation, PopulationStatistic}; +use crate::ir::operator::node::{OperatorNode, OperatorResultKind}; +use crate::ir::operator::Reduction; +use crate::ir::schema::{ColumnId, DataType, Field, FieldDataType, Schema}; +use crate::ir::schema::{GroupingStrategy, SketchStatistic, SummaryUpdate}; use crate::ir::SchemaDerivationError; -use crate::post_asap::maintained_population::{MaintainedPopulation, PopulationStatistic}; -use crate::post_asap::sketch::{GroupingStrategy, SketchStatistic, SummaryUpdate}; -use crate::pre_asap::schema::{ColumnId, DataType, Field, FieldDataType, Schema}; /// Why an ASAP operator cannot be used yet. pub const UNIMPLEMENTED_ASAP_OP: &str = @@ -31,7 +31,7 @@ pub enum ASAPOp> { reduction: Reduction, grouping: GroupingStrategy, #[serde(default)] - filter: Option>, + filter: Option>, }, /// Read out a query result from built summary state. Output is a /// row-shaped schema. @@ -123,7 +123,7 @@ impl ASAPOp { grouping: grouping.clone(), filter: filter .as_ref() - .map(|p| super::scalar::Predicate(p.0.map_operator_refs(&mut f))), + .map(|p| crate::ir::scalar::Predicate(p.0.map_operator_refs(&mut f))), }, SummaryEstimate { summary_input, @@ -230,15 +230,15 @@ impl ASAPOp { reduction, .. } => { - let mut schema = crate::ir::aggregate_schema::aggregate_output_schema( + let mut schema = crate::ir::schema::aggregate_output_schema( &child.schema, reduction, - &[crate::pre_asap::AggIntent::Sum { col: None }], + &[crate::ir::operator::AggIntent::Sum { col: None }], &[], )?; let index = match reduction { - Reduction::PerEntity => crate::pre_asap::resolve_column_ref( - &crate::pre_asap::ColumnRef::SampleValue, + Reduction::PerEntity => crate::ir::scalar::resolve_column_ref( + &crate::ir::scalar::ColumnRef::SampleValue, &schema, ) .map_err(|e| SchemaDerivationError::InvalidScalarSignature(e.to_string()))?, @@ -288,11 +288,11 @@ impl ASAPOp { }) = child.asap() { { - use crate::post_asap::{ExactKind, SummaryInputExpr}; - use crate::pre_asap::AggIntent; + use crate::ir::operator::AggIntent; + use crate::ir::schema::{ExactKind, SummaryInputExpr}; let column = match &input.weight { SummaryInputExpr::Column(col) => Some( - crate::pre_asap::column_resolution::resolve_column_ref( + crate::ir::scalar::column_resolution::resolve_column_ref( col, &source.schema, ) @@ -315,7 +315,7 @@ impl ASAPOp { }; measure .map(|measure| { - super::NonASAPOp::Aggregate { + crate::ir::NonASAPOp::Aggregate { child: Rc::clone(source), reduction: reduction.clone(), measures: vec![measure], @@ -354,8 +354,8 @@ impl ASAPOp { } MaintainPopulation { child, .. } => child.schema.clone(), EvaluatePopulation { child, evaluation } => { - use crate::post_asap::maintained_population::PopulationInput; - use crate::pre_asap::{AggIntent, GroupKeys}; + use crate::ir::operator::maintained_population::PopulationInput; + use crate::ir::operator::{AggIntent, GroupKeys}; let Some(MaintainPopulation { child: source, population, @@ -408,7 +408,7 @@ impl ASAPOp { PopulationStatistic::Average => AggIntent::Avg { col: column }, PopulationStatistic::TopK { .. } => unreachable!(), }; - super::NonASAPOp::Aggregate { + crate::ir::NonASAPOp::Aggregate { child: source.clone(), reduction: Reduction::Reduce(keys), measures: vec![measure], @@ -500,7 +500,7 @@ impl ASAPOp { query, } => { needs_state(summary_input, "SummaryEstimate")?; - use crate::post_asap::sketch::SketchCategory as C; + use crate::ir::schema::SketchCategory as C; let states: Vec<_> = summary_input .schema .fields @@ -572,13 +572,13 @@ impl ASAPOp { )); } fn check( - expr: &crate::post_asap::SummaryInputExpr, + expr: &crate::ir::schema::SummaryInputExpr, schema: &Schema, ) -> Result<(), SchemaDerivationError> { - use crate::post_asap::SummaryInputExpr; + use crate::ir::schema::SummaryInputExpr; match expr { SummaryInputExpr::Column(col) => { - crate::pre_asap::resolve_column_ref(col, schema).map_err(|e| { + crate::ir::scalar::resolve_column_ref(col, schema).map_err(|e| { SchemaDerivationError::InvalidScalarSignature(e.to_string()) })?; } @@ -618,8 +618,8 @@ impl ASAPOp { } /// The plain value an exact accumulator finalizes to. -fn finalized_data_type(kind: &crate::post_asap::sketch::ExactKind) -> DataType { - use crate::post_asap::sketch::ExactKind; +fn finalized_data_type(kind: &crate::ir::schema::state_type::ExactKind) -> DataType { + use crate::ir::schema::ExactKind; match kind { ExactKind::Count => DataType::Int64, _ => DataType::Float64, @@ -630,11 +630,11 @@ fn finalized_data_type(kind: &crate::post_asap::sketch::ExactKind) -> DataType { /// of the relational input the state was built from. fn source_kind(node: &OperatorNode) -> OperatorResultKind { match &node.operator { - super::node::Operator::ASAP(op) => match op.children().first() { + crate::ir::operator::node::Operator::ASAP(op) => match op.children().first() { Some(child) => source_kind(child), None => OperatorResultKind::Relation, }, - super::node::Operator::NonASAP(_) => match node.result_kind { + crate::ir::operator::node::Operator::NonASAP(_) => match node.result_kind { OperatorResultKind::RangeVector => OperatorResultKind::InstantVector, OperatorResultKind::State => OperatorResultKind::Relation, other => other, diff --git a/crates/types/src/post_asap/maintained_population.rs b/crates/types/src/ir/operator/maintained_population.rs similarity index 95% rename from crates/types/src/post_asap/maintained_population.rs rename to crates/types/src/ir/operator/maintained_population.rs index 5e64b5436..2d2eebc30 100644 --- a/crates/types/src/post_asap/maintained_population.rs +++ b/crates/types/src/ir/operator/maintained_population.rs @@ -43,7 +43,7 @@ pub enum PopulationInput { Rows { input: std::rc::Rc, value_column: usize, - grouping: crate::pre_asap::GroupKeys, + grouping: crate::ir::operator::GroupKeys, }, } @@ -57,8 +57,10 @@ pub struct MaintainedPopulation { impl CurrentSeriesInput { /// Verify the named contract against the canonical maintenance input. pub fn matches_node(&self, input: &crate::ir::OperatorNode) -> bool { + use crate::ir::operator::Source; + use crate::ir::scalar::{CompareOpKind, ScalarValue}; + use crate::ir::schema::DataType; use crate::ir::{NonASAPOp, Operator, ScalarExpr, TimeRangeKind}; - use crate::pre_asap::{CompareOpKind, DataType, ScalarValue, Source}; let input = match &input.operator { Operator::NonASAP(NonASAPOp::TimeRange { range, @@ -137,8 +139,9 @@ impl CurrentSeriesInput { impl MaintainedPopulation { /// Whether `input` is the maintenance input this population declares. pub fn matches_node(&self, input: &crate::ir::OperatorNode) -> bool { + use crate::ir::operator::Source; + use crate::ir::schema::DataType; use crate::ir::{NonASAPOp, Operator}; - use crate::pre_asap::{DataType, Source}; match &self.input { PopulationInput::CurrentSeries(spec) => spec.matches_node(input), PopulationInput::Rows { diff --git a/crates/types/src/ir/operator/mod.rs b/crates/types/src/ir/operator/mod.rs new file mode 100644 index 000000000..09a2cbf2b --- /dev/null +++ b/crates/types/src/ir/operator/mod.rs @@ -0,0 +1,19 @@ +//! #511 §1: the operators of the unified DAG and their parameters. + +pub mod agg_intent; +pub mod asap; +pub mod maintained_population; +pub mod node; +pub mod non_asap; +pub mod operator_properties; + +pub use agg_intent::{ + agg_accuracy, agg_is_exact, agg_is_mergeable, default_cardinality, default_quantile, AggIntent, + MathFunc, TimeFunc, +}; +pub use operator_properties::{ + AtModifier, BinaryOpKind, ColState, ConcatDiscriminatorKey, DataModel, GroupKeys, GroupSide, + InfoMatcher, JoinKind, PromQLVectorSetOpKind, Reduction, RelationalSetOpKind, SampleKind, + Source, TimeShift, VectorGrouping, VectorMatch, VectorMatchKind, WindowFrame, WindowFrameBound, + WindowFrameOffset, WindowFrameUnits, WindowFuncKind, +}; diff --git a/crates/types/src/ir/node.rs b/crates/types/src/ir/operator/node.rs similarity index 95% rename from crates/types/src/ir/node.rs rename to crates/types/src/ir/operator/node.rs index eaa7ca169..0a9b3a6f1 100644 --- a/crates/types/src/ir/node.rs +++ b/crates/types/src/ir/operator/node.rs @@ -9,13 +9,13 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; -use super::asap::ASAPOp; -use super::non_asap::NonASAPOp; -use super::summary_coverage::SummaryCoverage; +use crate::ir::operator::asap::ASAPOp; +use crate::ir::operator::non_asap::NonASAPOp; +use crate::ir::properties::summary_coverage::SummaryCoverage; +use crate::ir::properties::ExecutionTiming; +use crate::ir::properties::ResultGuarantee; +use crate::ir::schema::Schema; use crate::ir::SchemaDerivationError; -use crate::post_asap::execution_data_state::ExecutionTiming; -use crate::post_asap::guarantee::ResultGuarantee; -use crate::pre_asap::schema::Schema; /// The output category of an operator, derived from the operation and its /// inputs. Matching column schemas do not make categories interchangeable. @@ -311,9 +311,9 @@ impl OperatorNode { "execution timing is unassigned".into(), ) })?; - if timing == crate::post_asap::ExecutionTiming::IngestionTime + if timing == crate::ir::properties::ExecutionTiming::IngestionTime && node.children().iter().any(|child| { - child.timing != Some(crate::post_asap::ExecutionTiming::IngestionTime) + child.timing != Some(crate::ir::properties::ExecutionTiming::IngestionTime) }) { return Err(SchemaDerivationError::InvalidScalarSignature( @@ -333,10 +333,9 @@ impl OperatorNode { pub fn validate_structure(self: &Rc) -> Result<(), SchemaDerivationError> { for node in Self::reachable(self) { if node.schema.time_index.is_some_and(|i| { - node.schema - .fields - .get(i) - .is_none_or(|f| f.plain_dtype() != Some(&crate::pre_asap::DataType::Timestamp)) + node.schema.fields.get(i).is_none_or(|f| { + f.plain_dtype() != Some(&crate::ir::schema::DataType::Timestamp) + }) }) || node .schema .unique_keys diff --git a/crates/types/src/ir/non_asap.rs b/crates/types/src/ir/operator/non_asap.rs similarity index 98% rename from crates/types/src/ir/non_asap.rs rename to crates/types/src/ir/operator/non_asap.rs index e1cd14687..ef3446c20 100644 --- a/crates/types/src/ir/non_asap.rs +++ b/crates/types/src/ir/operator/non_asap.rs @@ -6,16 +6,16 @@ use std::time::Duration; use serde::{Deserialize, Serialize}; -use super::node::{OperatorNode, OperatorResultKind}; -use super::scalar::{Predicate, ProjectItem, ScalarExpr, SortKey}; -use crate::ir::aggregate_schema::aggregate_output_schema; -use crate::ir::operator_properties::{ +use crate::ir::operator::agg_intent::AggIntent; +use crate::ir::operator::node::{OperatorNode, OperatorResultKind}; +use crate::ir::operator::operator_properties::{ BinaryOpKind, ConcatDiscriminatorKey, GroupKeys, InfoMatcher, JoinKind, Reduction, RelationalSetOpKind, SampleKind, Source, TimeShift, VectorMatch, WindowFrame, WindowFuncKind, }; +use crate::ir::scalar::{Predicate, ProjectItem, ScalarExpr, SortKey}; +use crate::ir::schema::aggregate_schema::aggregate_output_schema; +use crate::ir::schema::{ColumnId, DataType, Field, FieldDataType, Schema}; use crate::ir::SchemaDerivationError; -use crate::pre_asap::agg_intent::AggIntent; -use crate::pre_asap::schema::{ColumnId, DataType, Field, FieldDataType, Schema}; /// All semantics owned by a binary operator. #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] @@ -750,8 +750,8 @@ impl NonASAPOp { .and_then(|m| m.grouping.as_ref()); let right_rows = matches!( operator.kind, - BinaryOpKind::Set(crate::pre_asap::PromQLVectorSetOpKind::Or) - ) || matches!(grouping, Some(g) if g.side == crate::pre_asap::GroupSide::Right); + BinaryOpKind::Set(crate::ir::operator::PromQLVectorSetOpKind::Or) + ) || matches!(grouping, Some(g) if g.side == crate::ir::operator::GroupSide::Right); let mut additions = Vec::new(); if right_rows { additions.extend( @@ -1076,11 +1076,11 @@ pub fn any_measure_filtered(filters: &[Option]) -> bool { #[cfg(test)] mod tests { use super::*; - use crate::ir::operator_properties::{ + use crate::ir::operator::operator_properties::{ AtModifier, VectorMatchKind, WindowFrameBound, WindowFrameOffset, WindowFrameUnits, }; use crate::ir::scalar::ExprSemantics; - use crate::pre_asap::expr_ir::{ArithmeticOpKind, CompareOpKind, ScalarValue}; + use crate::ir::scalar::{ArithmeticOpKind, CompareOpKind, ScalarValue}; fn col(name: &str, dtype: DataType, nullable: bool) -> Field { Field::plain(name, dtype, nullable) diff --git a/crates/types/src/ir/operator_properties.rs b/crates/types/src/ir/operator/operator_properties.rs similarity index 99% rename from crates/types/src/ir/operator_properties.rs rename to crates/types/src/ir/operator/operator_properties.rs index 27648351b..e5a04a720 100644 --- a/crates/types/src/ir/operator_properties.rs +++ b/crates/types/src/ir/operator/operator_properties.rs @@ -3,8 +3,9 @@ //! For example, `Aggregate.by` uses [`GroupKeys`], a join chooses [`JoinKind`], //! and a SQL window carries [`WindowFrame`]. These types describe what an //! operator does. Derived node metadata (schema, guarantee, timing) lives on -//! [`super::OperatorNode`], not in this module. -use crate::pre_asap::{ArithmeticOpKind, ColumnId, ColumnRef, CompareOpKind, ScalarValue}; +//! [`crate::ir::OperatorNode`], not in this module. +use crate::ir::scalar::{ArithmeticOpKind, ColumnRef, CompareOpKind, ScalarValue}; +use crate::ir::schema::ColumnId; use serde::{Deserialize, Serialize}; /// The column-reference type an operator parameter is generic over: /// positional [`ColumnId`] once bound, name-based [`ColumnRef`] before. diff --git a/crates/types/src/ir/physical_export.rs b/crates/types/src/ir/physical_export.rs index 1e779408f..c7749827d 100644 --- a/crates/types/src/ir/physical_export.rs +++ b/crates/types/src/ir/physical_export.rs @@ -2,7 +2,7 @@ //! //! The flattened operators of [`super::flat`], plus the execution timing //! (data state) of every node and edge. The input must already be timed -//! ([`super::timing::apply_materialization_timings`]); export reads each node's +//! ([`super::properties::timing::apply_materialization_timings`]); export reads each node's //! timing and does not re-run data-state validation. use std::collections::{BTreeMap, HashMap, HashSet}; @@ -11,18 +11,16 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; use thiserror::Error; -use super::asap::ASAPOp; use super::flat::{flatten, NodeId}; -use super::node::{Operator, OperatorNode}; -use super::non_asap::NonASAPOp; -use super::operator_properties::Reduction; +use super::operator::asap::ASAPOp; +use super::operator::node::{Operator, OperatorNode}; +use super::operator::non_asap::NonASAPOp; +use super::operator::operator_properties::Reduction; +use super::properties::timing::data_state; use super::query::QueryRoot; -use super::timing::data_state; -use crate::post_asap::execution_data_state::{ - ExecutionDataState, ExecutionDataStateError, ExecutionTiming, -}; -use crate::post_asap::guarantee::ResultGuarantee; -use crate::pre_asap::schema::{FieldDataType, Schema}; +use crate::ir::properties::ResultGuarantee; +use crate::ir::properties::{ExecutionDataState, ExecutionDataStateError, ExecutionTiming}; +use crate::ir::schema::{FieldDataType, Schema}; pub const PHYSICAL_ASAP_DAG_WIRE_VERSION: u32 = 8; @@ -351,7 +349,7 @@ pub fn compile_physical_asap_dag( } /// Export the timed DAG below `root`. Every reachable node must carry a -/// timing (see [`super::timing::apply_materialization_timings`]); the data-state +/// timing (see [`super::properties::timing::apply_materialization_timings`]); the data-state /// rules were checked by that pass and are not re-run here. pub fn compile_physical_asap_dag_with_node_ids( root: &Rc, diff --git a/crates/types/src/post_asap/execution_data_state.rs b/crates/types/src/ir/properties/execution.rs similarity index 91% rename from crates/types/src/post_asap/execution_data_state.rs rename to crates/types/src/ir/properties/execution.rs index ad6e28781..22545824c 100644 --- a/crates/types/src/post_asap/execution_data_state.rs +++ b/crates/types/src/ir/properties/execution.rs @@ -3,14 +3,11 @@ //! [`ExecutionTiming`] says when a node's value is produced (ingestion vs. //! query time); [`ExecutionDataState`] pairs it with the [`DataPrimitive`] //! the edge carries (raw values vs. summary state). The rules that assign -//! and check them over a DAG live in [`crate::ir::timing`], which reports +//! and check them over a DAG live in [`crate::ir::properties::timing`], which reports //! violations as [`ExecutionDataStateError`]. use thiserror::Error; -use crate::ir::SchemaDerivationError; -use crate::pre_asap::schema::Schema; - /// When a post-ASAP value is produced. #[derive( Default, Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, @@ -146,21 +143,6 @@ pub enum ExecutionDataStateError { UntimedNode { operator: &'static str }, } -/// `schema` as a summary-planning node output: fields and time axis kept, -/// unique keys dropped, closed. -pub fn lift_plain(schema: &Schema) -> Schema { - Schema::lifted(schema.fields.clone(), schema.time_index) -} - -/// Why an exact operator's output schema could not be derived. -#[derive(Debug, Error)] -pub enum ExactOperationSchemaError { - #[error("exact operator input carries summary state, not plain columns")] - NonPlainInput, - #[error("schema derivation failed: {0}")] - Schema(#[from] SchemaDerivationError), -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/types/src/post_asap/guarantee.rs b/crates/types/src/ir/properties/guarantee.rs similarity index 100% rename from crates/types/src/post_asap/guarantee.rs rename to crates/types/src/ir/properties/guarantee.rs diff --git a/crates/types/src/ir/properties/mod.rs b/crates/types/src/ir/properties/mod.rs new file mode 100644 index 000000000..a51c74808 --- /dev/null +++ b/crates/types/src/ir/properties/mod.rs @@ -0,0 +1,13 @@ +//! #511 §2.2–2.3: node properties beyond the schema — the accuracy +//! guarantee, execution timing and data state, and summary coverage. + +pub mod execution; +pub mod guarantee; +pub mod summary_coverage; +pub mod timing; + +pub use execution::{DataPrimitive, ExecutionDataState, ExecutionDataStateError, ExecutionTiming}; +pub use guarantee::{ + AccuracyError, BoundExpr, CompositionOperator, ErrorMetric, GuaranteeSource, ProbabilityExpr, + ResultGuarantee, +}; diff --git a/crates/types/src/ir/summary_coverage.rs b/crates/types/src/ir/properties/summary_coverage.rs similarity index 98% rename from crates/types/src/ir/summary_coverage.rs rename to crates/types/src/ir/properties/summary_coverage.rs index 1bbb2978a..62c37b8b6 100644 --- a/crates/types/src/ir/summary_coverage.rs +++ b/crates/types/src/ir/properties/summary_coverage.rs @@ -17,12 +17,12 @@ use std::rc::Rc; use thiserror::Error; -use super::asap::ASAPOp; -use super::node::{Operator, OperatorNode}; -use super::non_asap::{NonASAPOp, TimeRangeKind}; -use super::scalar::{Predicate, ScalarExpr}; -use crate::pre_asap::expr_ir::{CompareOpKind, ScalarValue}; -use crate::pre_asap::schema::{ColumnId, Schema}; +use crate::ir::operator::asap::ASAPOp; +use crate::ir::operator::node::{Operator, OperatorNode}; +use crate::ir::operator::non_asap::{NonASAPOp, TimeRangeKind}; +use crate::ir::scalar::{CompareOpKind, ScalarValue}; +use crate::ir::scalar::{Predicate, ScalarExpr}; +use crate::ir::schema::{ColumnId, Schema}; #[derive(Debug, Clone, PartialEq)] pub struct SummaryCoverage { diff --git a/crates/types/src/ir/timing.rs b/crates/types/src/ir/properties/timing.rs similarity index 96% rename from crates/types/src/ir/timing.rs rename to crates/types/src/ir/properties/timing.rs index 483d92399..52cb2a0da 100644 --- a/crates/types/src/ir/timing.rs +++ b/crates/types/src/ir/properties/timing.rs @@ -36,14 +36,14 @@ use std::collections::HashMap; use std::rc::Rc; -use super::asap::ASAPOp; -use super::node::{Operator, OperatorNode}; -use super::non_asap::NonASAPOp; -use crate::ir::operator_properties::BinaryOpKind; -use crate::post_asap::execution_data_state::{ +use crate::ir::operator::asap::ASAPOp; +use crate::ir::operator::node::{Operator, OperatorNode}; +use crate::ir::operator::non_asap::NonASAPOp; +use crate::ir::operator::operator_properties::BinaryOpKind; +use crate::ir::properties::execution::{ DataPrimitive, ExecutionDataState, ExecutionDataStateError, ExecutionTiming, }; -use crate::pre_asap::schema::{DataType, FieldDataType, Schema}; +use crate::ir::schema::{DataType, FieldDataType, Schema}; /// The per-state materialization choice: for each `SummaryAgg` node (by /// identity), whether its state is maintained at ingestion time or computed @@ -130,7 +130,7 @@ fn forces_query_time(node: &OperatorNode, seen: &mut HashMap<*const OperatorNode .schema .fields .iter() - .any(|f| f.name == crate::pre_asap::schema::PROMQL_SERIES_IDENTITY) + .any(|f| f.name == crate::ir::schema::PROMQL_SERIES_IDENTITY) && per_series_rows(lhs).is_none_or(|rows| per_series_rows(rhs) != Some(rows)) => { true @@ -501,7 +501,7 @@ fn validate_non_asap( } => { let is_div = matches!( operator.kind, - BinaryOpKind::Arithmetic(crate::pre_asap::ArithmeticOpKind::Div) + BinaryOpKind::Arithmetic(crate::ir::scalar::ArithmeticOpKind::Div) ); if (operator.checked_relative_division && operator.checked_finite_division) || ((operator.checked_relative_division || operator.checked_finite_division) @@ -516,8 +516,7 @@ fn validate_non_asap( && (matches!( field.dtype, FieldDataType::Plain(DataType::Float64 | DataType::Timestamp) - ) || (field.name - == crate::pre_asap::schema::PROMQL_SERIES_IDENTITY + ) || (field.name == crate::ir::schema::PROMQL_SERIES_IDENTITY && field.dtype == FieldDataType::Plain(DataType::Utf8))) }) }; @@ -535,14 +534,14 @@ fn validate_non_asap( .schema .fields .iter() - .filter(|f| f.name == crate::pre_asap::schema::PROMQL_SERIES_IDENTITY) + .filter(|f| f.name == crate::ir::schema::PROMQL_SERIES_IDENTITY) .count() > 1 || (node .schema .fields .iter() - .any(|f| f.name == crate::pre_asap::schema::PROMQL_SERIES_IDENTITY) + .any(|f| f.name == crate::ir::schema::PROMQL_SERIES_IDENTITY) && per_series_rows(lhs) .is_none_or(|rows| per_series_rows(rhs) != Some(rows))) || !plain_float_or_ts(&node.schema) @@ -649,13 +648,13 @@ pub fn split_shared_by_phase( /// Maintenance arithmetic needs the same per-series population on both sides. fn per_series_rows(node: &OperatorNode) -> Option<&OperatorNode> { - use crate::post_asap::ExactKind; + use crate::ir::schema::ExactKind; match &node.operator { Operator::ASAP(ASAPOp::FinalizeExactAccumulator { child }) => match &child.operator { Operator::ASAP(ASAPOp::SummaryAgg { child, family: FieldDataType::ExactAggregate(ExactKind::Sum | ExactKind::Count, _), - reduction: crate::pre_asap::Reduction::PerEntity, + reduction: crate::ir::operator::Reduction::PerEntity, filter: None, .. }) => Some(child), @@ -672,15 +671,15 @@ fn per_series_rows(node: &OperatorNode) -> Option<&OperatorNode> { #[cfg(test)] mod tests { use super::*; - use crate::ir::non_asap::NonASAPOp; - use crate::ir::operator_properties::{Reduction, Source}; - use crate::post_asap::sketch::{ + use crate::ir::operator::agg_intent::AggIntent; + use crate::ir::operator::non_asap::NonASAPOp; + use crate::ir::operator::operator_properties::{Reduction, Source}; + use crate::ir::scalar::ColumnRef; + use crate::ir::schema::state_type::{ ExactKind, ExactParams, GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SketchStatistic, SummaryUpdate, }; - use crate::pre_asap::agg_intent::AggIntent; - use crate::pre_asap::expr_ir::ColumnRef; - use crate::pre_asap::schema::Field; + use crate::ir::schema::Field; fn scan_with(fields: Vec) -> Rc { OperatorNode::new_shared(crate::ir::Operator::NonASAP(NonASAPOp::Scan { diff --git a/crates/types/src/ir/query.rs b/crates/types/src/ir/query.rs index 67ec50359..542936334 100644 --- a/crates/types/src/ir/query.rs +++ b/crates/types/src/ir/query.rs @@ -1,6 +1,6 @@ //! Query results are either an operator result or a standalone scalar expression. //! The root discriminator is not an operator and never creates a dag node. -use super::{OperatorNode, ScalarExpr}; +use crate::ir::{OperatorNode, ScalarExpr}; use serde::{Deserialize, Serialize}; use std::rc::Rc; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -18,7 +18,7 @@ impl QueryRoot { match self { Self::Operator(node) => node.validate_structure(), Self::Scalar(expr) => { - expr.scalar_type(&crate::pre_asap::Schema::default())?; + expr.scalar_type(&crate::ir::schema::Schema::default())?; for node in expr.operator_refs() { node.validate_structure()?; } diff --git a/crates/types/src/pre_asap/column_resolution.rs b/crates/types/src/ir/scalar/column_resolution.rs similarity index 98% rename from crates/types/src/pre_asap/column_resolution.rs rename to crates/types/src/ir/scalar/column_resolution.rs index e2d8120d6..587d182eb 100644 --- a/crates/types/src/pre_asap/column_resolution.rs +++ b/crates/types/src/ir/scalar/column_resolution.rs @@ -7,8 +7,8 @@ use thiserror::Error; -use super::expr_ir::ColumnRef; -use super::schema::{ColumnId, DataType, FieldDataType, Schema}; +use crate::ir::scalar::ColumnRef; +use crate::ir::schema::{ColumnId, DataType, FieldDataType, Schema}; /// Errors returned by the resolution helpers. #[derive(Debug, Error, PartialEq, Eq)] @@ -109,7 +109,7 @@ pub fn resolve_group_keys_promql( #[cfg(test)] mod tests { use super::*; - use crate::pre_asap::schema::Field; + use crate::ir::schema::Field; /// The conventional PromQL leaf shape: `(ts: Timestamp, value: Float64)`. fn ts_value_schema() -> Schema { diff --git a/crates/types/src/pre_asap/expr_ir.rs b/crates/types/src/ir/scalar/expr_ir.rs similarity index 96% rename from crates/types/src/pre_asap/expr_ir.rs rename to crates/types/src/ir/scalar/expr_ir.rs index fe373e58f..50606f185 100644 --- a/crates/types/src/pre_asap/expr_ir.rs +++ b/crates/types/src/ir/scalar/expr_ir.rs @@ -1,7 +1,7 @@ //! Column-reference and scalar-operator vocabulary shared by the IR's scalar //! expressions ([`crate::ir::ScalarExpr`]) and the front ends' unresolved //! form: [`ColumnRef`] (name-based, front-end-emitted; positional -//! [`ColumnId`](super::schema::ColumnId) once bound), and [`ScalarValue`], +//! [`ColumnId`](crate::ir::schema::ColumnId) once bound), and [`ScalarValue`], //! [`CompareOpKind`], [`ArithmeticOpKind`] — the **union** of what the two //! front ends need: PromQL contributes `Regex` / `NotRegex` (`=~` / `!~`); SQL //! contributes arithmetic, `CASE`, `IN`, `CAST`, `IS [NOT] NULL`, scalar @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; /// A name-based column reference — the front-end-emitted, unresolved form of /// [`ScalarExpr::Column`](crate::ir::ScalarExpr::Column); front-end name -/// resolution turns it into a positional [`ColumnId`](super::schema::ColumnId). +/// resolution turns it into a positional [`ColumnId`](crate::ir::schema::ColumnId). /// This is a logical reference, not schema metadata or a runtime data array. /// `SampleValue` names the implicit PromQL sample column; `Wildcard` represents /// an all-columns/rows request. diff --git a/crates/types/src/ir/scalar.rs b/crates/types/src/ir/scalar/mod.rs similarity index 97% rename from crates/types/src/ir/scalar.rs rename to crates/types/src/ir/scalar/mod.rs index 3d724b250..a7473534f 100644 --- a/crates/types/src/ir/scalar.rs +++ b/crates/types/src/ir/scalar/mod.rs @@ -3,20 +3,26 @@ //! //! A [`ScalarExpr`] never produces a table. It is owned by value by an operator //! field (`Filter.pred`, `ProjectItem.expr`, `SortKey.expr`, `HAVING`, window -//! arguments, relabel values) or by a [`super::QueryRoot::Scalar`] query root. +//! arguments, relabel values) or by a [`crate::ir::QueryRoot::Scalar`] query root. //! The only operator references inside a scalar tree are the explicit //! plan-reading variants (`PromqlScalarFromVector`, `ScalarSubquery`, `Exists`, //! `InSubquery`); every traversal of the operator DAG follows them. +pub mod column_resolution; +mod expr_ir; +pub mod scalar_type_rules; + +pub use column_resolution::{resolve_column_ref, resolve_column_refs, ResolveError}; +pub use expr_ir::{ArithmeticOpKind, ColumnRef, CompareOpKind, ScalarValue}; + use std::rc::Rc; use serde::{Deserialize, Serialize}; -use super::node::OperatorNode; +use crate::ir::operator::node::OperatorNode; +use crate::ir::scalar::scalar_type_rules::MapScalarFunction; +use crate::ir::schema::{ColumnId, DataType, Schema}; use crate::ir::SchemaDerivationError; -use crate::pre_asap::expr_ir::{ArithmeticOpKind, CompareOpKind, ScalarValue}; -use crate::pre_asap::scalar_type_rules::MapScalarFunction; -use crate::pre_asap::schema::{ColumnId, DataType, Schema}; /// Which language's numeric and comparison rules an expression follows. /// Both languages use `Float64`, so a result type alone does not preserve @@ -488,7 +494,8 @@ impl ScalarExpr { (to.clone(), *try_cast || nullable) } ScalarExpr::FunctionCall { name, args } => { - if let Some(arity) = crate::pre_asap::scalar_type_rules::promql_function_arity(name) + if let Some(arity) = + crate::ir::scalar::scalar_type_rules::promql_function_arity(name) { if args.len() != arity || args @@ -558,7 +565,7 @@ impl ScalarExpr { // `scalar(v)` is one float sample (NaN when the vector is not // exactly one series); a scalar subquery is its single column. ScalarExpr::PromqlScalarFromVector(node) => { - if node.result_kind != super::OperatorResultKind::InstantVector { + if node.result_kind != crate::ir::OperatorResultKind::InstantVector { return Err(signature("scalar() requires an instant vector")); } (DataType::Float64, false) @@ -602,7 +609,7 @@ fn common_scalar_type(a: &DataType, b: &DataType) -> Result Result<(), SchemaDerivationError> { - if node.result_kind == super::OperatorResultKind::Relation { + if node.result_kind == crate::ir::OperatorResultKind::Relation { Ok(()) } else { Err(signature("SQL subquery requires a relation")) @@ -610,7 +617,7 @@ fn relation(node: &OperatorNode) -> Result<(), SchemaDerivationError> { } fn scalar_subquery_field( node: &OperatorNode, -) -> Result<&crate::pre_asap::Field, SchemaDerivationError> { +) -> Result<&crate::ir::schema::Field, SchemaDerivationError> { relation(node)?; match node.schema.fields.as_slice() { [field] => Ok(field), @@ -746,9 +753,9 @@ pub fn element_access_type( #[cfg(test)] mod tests { use super::*; - use crate::ir::operator_properties::Source; + use crate::ir::operator::operator_properties::Source; + use crate::ir::schema::{Field, FieldDataType}; use crate::ir::{NonASAPOp, OperatorNode}; - use crate::pre_asap::schema::{Field, FieldDataType}; fn call(name: &str, args: Vec) -> ScalarExpr { ScalarExpr::FunctionCall { diff --git a/crates/types/src/pre_asap/scalar_type_rules.rs b/crates/types/src/ir/scalar/scalar_type_rules.rs similarity index 99% rename from crates/types/src/pre_asap/scalar_type_rules.rs rename to crates/types/src/ir/scalar/scalar_type_rules.rs index 3efad3f7e..81be9e466 100644 --- a/crates/types/src/pre_asap/scalar_type_rules.rs +++ b/crates/types/src/ir/scalar/scalar_type_rules.rs @@ -1,6 +1,6 @@ //! Shared type and nullability rules used to validate scalar expressions. //! These rules do not evaluate expressions or define physical representations. -use super::schema::DataType; +use crate::ir::schema::DataType; /// Names are resolved once against this closed builtin set; unknown functions /// remain outside these type rules. Map access keeps the first duplicate key diff --git a/crates/types/src/ir/aggregate_schema.rs b/crates/types/src/ir/schema/aggregate_schema.rs similarity index 95% rename from crates/types/src/ir/aggregate_schema.rs rename to crates/types/src/ir/schema/aggregate_schema.rs index 10b33d2ae..408fbdec4 100644 --- a/crates/types/src/ir/aggregate_schema.rs +++ b/crates/types/src/ir/schema/aggregate_schema.rs @@ -5,9 +5,11 @@ //! aggregate result; a PromQL per-series range reduction preserves labels //! and produces a Float64 sample value. This module derives schemas, not //! aggregate values or summary candidates. -use super::operator_properties::*; -use super::SchemaDerivationError; -use crate::pre_asap::{AggIntent, ColumnId, ColumnRef, DataType, Field, FieldDataType, Schema}; +use crate::ir::operator::operator_properties::*; +use crate::ir::operator::AggIntent; +use crate::ir::scalar::ColumnRef; +use crate::ir::schema::{ColumnId, DataType, Field, FieldDataType, Schema}; +use crate::ir::SchemaDerivationError; /// Output schema of a *per-series* window/range reduction (`rate`/`increase`, /// or an `*_over_time` reducer under a time `Window`). Such a reduction emits /// one value per series, so every label column of `input` is preserved and only @@ -20,7 +22,7 @@ fn per_series_reduction_schema( let vi = if let Some(index) = agg.input_cols().first() { *index } else { - crate::pre_asap::column_resolution::resolve_column_ref(&ColumnRef::SampleValue, input) + crate::ir::scalar::column_resolution::resolve_column_ref(&ColumnRef::SampleValue, input) .map_err(|error| SchemaDerivationError::InvalidSampleColumn(error.to_string()))? }; if !matches!( @@ -101,10 +103,12 @@ pub fn aggregate_output_schema( ))?; out_cols.push(c.clone()); } - let value_col_idx = - crate::pre_asap::column_resolution::resolve_column_ref(&ColumnRef::SampleValue, in_schema) - .ok() - .or_else(|| (0..in_schema.fields.len()).find(|i| !by.contains(i))); + let value_col_idx = crate::ir::scalar::column_resolution::resolve_column_ref( + &ColumnRef::SampleValue, + in_schema, + ) + .ok() + .or_else(|| (0..in_schema.fields.len()).find(|i| !by.contains(i))); let probe = value_col_idx .and_then(|i| in_schema.fields.get(i)) .cloned() @@ -200,7 +204,7 @@ fn without_output_schema( let mut out_cols: Vec = Vec::new(); for (i, col) in in_schema.fields.iter().enumerate() { let is_time = in_schema.time_index == Some(i); - let is_value = crate::pre_asap::column_resolution::resolve_column_ref( + let is_value = crate::ir::scalar::column_resolution::resolve_column_ref( &ColumnRef::SampleValue, in_schema, ) diff --git a/crates/types/src/ir/error.rs b/crates/types/src/ir/schema/error.rs similarity index 88% rename from crates/types/src/ir/error.rs rename to crates/types/src/ir/schema/error.rs index a0f9e2271..d4f3b05b5 100644 --- a/crates/types/src/ir/error.rs +++ b/crates/types/src/ir/schema/error.rs @@ -3,7 +3,7 @@ //! [`SchemaDerivationError`] distinguishes invalid scalar signatures, out-of-range //! grouping columns, empty concatenations, and invalid sample columns. //! Structural DAG and execution-timing validation have separate error types. -use crate::pre_asap::ColumnId; +use crate::ir::schema::ColumnId; use thiserror::Error; /// Errors from schema and type derivation over an operator DAG. #[derive(Debug, Error)] @@ -17,5 +17,5 @@ pub enum SchemaDerivationError { #[error("invalid per-series sample column: {0}")] InvalidSampleColumn(String), #[error("invalid summary coverage: {0}")] - Coverage(#[from] super::summary_coverage::CoverageError), + Coverage(#[from] crate::ir::properties::summary_coverage::CoverageError), } diff --git a/crates/types/src/pre_asap/schema.rs b/crates/types/src/ir/schema/mod.rs similarity index 97% rename from crates/types/src/pre_asap/schema.rs rename to crates/types/src/ir/schema/mod.rs index 7eec788b7..3ea89792d 100644 --- a/crates/types/src/pre_asap/schema.rs +++ b/crates/types/src/ir/schema/mod.rs @@ -13,13 +13,21 @@ #![allow(dead_code)] -use serde::{Deserialize, Serialize}; - -use crate::post_asap::sketch::{ - ExactKind, ExactParams, GroupingStrategy, SamplingKind, SamplingParams, SketchKind, - StatModelKind, StatModelParams, WaveletKind, WaveletParams, +pub mod aggregate_schema; +pub mod error; +pub mod state_type; + +pub use aggregate_schema::aggregate_output_schema; +pub use error::SchemaDerivationError; +pub use state_type::{ + default_hydra_params, hydra_kind_for, EntityIdentity, ExactKind, ExactParams, GroupingStrategy, + HydraKind, HydraParams, NonNegativeWeightProof, SamplingKind, SamplingParams, SketchAlgorithm, + SketchCategory, SketchKind, SketchParams, SketchStatistic, StatModelKind, StatModelParams, + SummaryInputExpr, SummaryUpdate, WaveletKind, WaveletParams, WeightDomain, }; +use serde::{Deserialize, Serialize}; + /// Zero-based position of a column in a particular operator's input or output. /// /// During planning, the position indexes [`Schema::fields`] to obtain metadata; diff --git a/crates/types/src/post_asap/sketch.rs b/crates/types/src/ir/schema/state_type.rs similarity index 96% rename from crates/types/src/post_asap/sketch.rs rename to crates/types/src/ir/schema/state_type.rs index 65e78d24f..2c26b0f37 100644 --- a/crates/types/src/post_asap/sketch.rs +++ b/crates/types/src/ir/schema/state_type.rs @@ -1,6 +1,24 @@ +//! Summary-state types carried by [`FieldDataType`](crate::ir::schema::FieldDataType). +//! +//! Where an intent ([`crate::ir::operator::AggIntent`]) says *what* to compute +//! ("a quantile to ε accuracy"), these types say *how* a summary realizes it: +//! the family, kind/algorithm and parameters are committed — one +//! `(Kind, Params)` pair per family ([`ExactKind`]/[`ExactParams`], +//! [`SamplingKind`]/[`SamplingParams`], [`WaveletKind`]/[`WaveletParams`], +//! [`StatModelKind`]/[`StatModelParams`]). The `Sketch` family nests a third +//! level, [`SketchKind`] (quantile/cardinality/frequency/top-k), carrying the +//! committed [`SketchAlgorithm`] and [`SketchParams`], because it is the one +//! family with more than one algorithm per purpose. +//! +//! [`GroupingStrategy`] is a second, orthogonal axis: how many physical +//! instances of a summary exist across a grouped aggregate's `by` +//! subpopulations (per-subpopulation vs. one shared Hydra instance — see +//! `asap_aware_mapping::grouping`). It rides on `ASAPOp::SummaryAgg` and on +//! sketch-valued edge types. + use serde::{Deserialize, Serialize}; -use crate::pre_asap::ColumnRef; +use crate::ir::scalar::ColumnRef; // ── Exact accumulators ────────────────────────────────────────────────────── @@ -134,7 +152,7 @@ pub enum SketchCategory { /// quantile-style, cardinality-style, frequency-style, or heavy-hitter/ /// top-k-style estimation — together with the concrete [`SketchAlgorithm`] /// and [`SketchParams`] realizing it. Sits between -/// [`FieldDataType::Sketch`](super::schema::FieldDataType::Sketch) +/// [`FieldDataType::Sketch`](crate::ir::schema::FieldDataType::Sketch) /// (the `Sketch` family as a whole, sibling to `Sample`/`Wavelet`/ /// `StatModel`) and the bare algorithm: `Kll` vs. `DDSketch` is a choice /// *within* `Quantile`, not a choice *of* `SketchKind` — every `Quantile` diff --git a/crates/types/src/ir/schema_support.rs b/crates/types/src/ir/schema_support.rs index 95c42070d..bace1743f 100644 --- a/crates/types/src/ir/schema_support.rs +++ b/crates/types/src/ir/schema_support.rs @@ -1,5 +1,5 @@ //! Series-identity realization for the unified dag. -use crate::pre_asap::schema::*; +use crate::ir::schema::*; /// Resolve a PromQL root to rows carrying [`PROMQL_SERIES_IDENTITY`] before /// candidate search. `closed` describes physical columns here: the final /// column contains every dynamic source label. It does not assert that the @@ -12,8 +12,8 @@ use crate::pre_asap::schema::*; pub fn with_promql_series_identity( root: &std::rc::Rc, ) -> Result, String> { + use crate::ir::operator::Source; use crate::ir::{NonASAPOp, Operator, OperatorNode}; - use crate::pre_asap::Source; use std::{collections::HashMap, rc::Rc}; fn visit( node: &Rc, diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index c48fd9df0..3f666d8a6 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -1,27 +1,20 @@ //! `asap-types` — shared vocabulary for the whole workspace. //! -//! - [`ir`] — the unified operator IR: one operator language before and -//! after ASAP optimization ([`ir::OperatorNode`]), plus its passes -//! (canonicalize, CSE, timing), the flat DAG form ([`ir::flat`]) and the -//! physical ASAP DAG ([`ir::physical_export`]). -//! - [`pre_asap`] — the shared field vocabulary the IR's operators are -//! built from (grouping keys, reductions, sources, aggregation intents, -//! scalar literal / operator kinds, [`pre_asap::Schema`]). -//! - [`post_asap`] — summary-state types (families, kinds, parameters, -//! grouping strategy), accuracy guarantees, and the execution-timing -//! vocabulary. No execution logic lives in this workspace (issue #190). -//! [`post_asap::query_time`] holds pure posterior error-bound math -//! (issue #239) a future sketch runtime's evaluation path can call; see its -//! docs for why it is unwired today. -//! - [`types`] / [`workload`] / [`parsed_workload`] / [`dag_export`] / -//! [`cost`] / [`resources`] — workload, batch, export and cost types. +//! - [`ir`] — the unified operator IR (#511): one operator DAG before and +//! after ASAP optimization ([`ir::OperatorNode`]), arranged by #511 section +//! ([`ir::operator`], [`ir::scalar`], [`ir::schema`], [`ir::properties`]), +//! plus its passes (canonicalize, CSE, timing) and the wire export +//! ([`ir::export`]). No execution logic lives in this crate (issue #190). +//! - [`workload`] — planner inputs (#509): query and data workloads, the +//! lowered [`workload::parsed_workload`], and [`workload::resources`]. +//! - [`physical`] — #509 Stage 2 decision data: exact-operator schema helpers +//! and window-summary pane primitives. +//! - [`types`] / [`dag_export`] / [`cost`] — accuracy targets, the generic +//! DAG export, and cost annotations. pub mod cost; pub mod dag_export; pub mod ir; -pub mod parsed_workload; -pub mod post_asap; -pub mod pre_asap; -pub mod resources; +pub mod physical; pub mod serde_f64; pub mod types; pub mod workload; diff --git a/crates/types/src/physical/execution_data_state.rs b/crates/types/src/physical/execution_data_state.rs new file mode 100644 index 000000000..64620e01d --- /dev/null +++ b/crates/types/src/physical/execution_data_state.rs @@ -0,0 +1,21 @@ +//! Exact-operator schema helpers for summary planning. + +use thiserror::Error; + +use crate::ir::schema::Schema; +use crate::ir::SchemaDerivationError; + +/// `schema` as a summary-planning node output: fields and time axis kept, +/// unique keys dropped, closed. +pub fn lift_plain(schema: &Schema) -> Schema { + Schema::lifted(schema.fields.clone(), schema.time_index) +} + +/// Why an exact operator's output schema could not be derived. +#[derive(Debug, Error)] +pub enum ExactOperationSchemaError { + #[error("exact operator input carries summary state, not plain columns")] + NonPlainInput, + #[error("schema derivation failed: {0}")] + Schema(#[from] SchemaDerivationError), +} diff --git a/crates/types/src/physical/mod.rs b/crates/types/src/physical/mod.rs new file mode 100644 index 000000000..f599ad28c --- /dev/null +++ b/crates/types/src/physical/mod.rs @@ -0,0 +1,10 @@ +//! #509 Stage 2 decision data: exact-operator schema helpers for +//! materialization and the pane primitives of window summaries. + +pub mod execution_data_state; +pub mod summary_window; + +pub use execution_data_state::{lift_plain, ExactOperationSchemaError}; +pub use summary_window::{ + plan_pane_phase, validate_pane_coverage, PaneCoverageError, PaneLayout, WindowEdgeCoverage, +}; diff --git a/crates/types/src/post_asap/summary_window.rs b/crates/types/src/physical/summary_window.rs similarity index 100% rename from crates/types/src/post_asap/summary_window.rs rename to crates/types/src/physical/summary_window.rs diff --git a/crates/types/src/post_asap/mod.rs b/crates/types/src/post_asap/mod.rs deleted file mode 100644 index 04e3264c2..000000000 --- a/crates/types/src/post_asap/mod.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Summary-state types and the execution-timing vocabulary of the operator -//! IR ([`crate::ir`]). -//! -//! Where an intent ([`crate::pre_asap::AggIntent`]) says *what* to compute -//! ("a quantile to ε accuracy"), these types say *how* a summary realizes it: -//! the family, kind/algorithm and parameters are committed — one -//! `(Kind, Params)` pair per family ([`sketch::ExactKind`]/[`sketch::ExactParams`], -//! [`sketch::SamplingKind`]/[`sketch::SamplingParams`], -//! [`sketch::WaveletKind`]/[`sketch::WaveletParams`], -//! [`sketch::StatModelKind`]/[`sketch::StatModelParams`]). The `Sketch` family -//! nests a third level, [`sketch::SketchKind`] (quantile/cardinality/ -//! frequency/top-k), carrying the committed [`sketch::SketchAlgorithm`] and -//! [`sketch::SketchParams`], because it is the one family with more than one -//! algorithm per purpose. -//! -//! [`sketch::GroupingStrategy`] is a second, orthogonal axis: how many -//! physical instances of a summary exist across a grouped aggregate's `by` -//! subpopulations (per-subpopulation vs. one shared Hydra instance — see -//! `asap_aware_mapping::grouping`). It rides on `ASAPOp::SummaryAgg` and on -//! sketch-valued edge types. -//! -//! The rest: accuracy guarantees ([`guarantee`]), maintained populations, -//! summary-window panes, and the execution timing / -//! data-state vocabulary ([`execution_data_state`]). - -pub mod execution_data_state; -pub mod guarantee; -pub mod maintained_population; -pub mod query_time; -pub mod sketch; -pub mod summary_window; - -pub use crate::pre_asap::schema::{Field, FieldDataType, Schema}; -pub use execution_data_state::{ - lift_plain, DataPrimitive, ExactOperationSchemaError, ExecutionDataState, - ExecutionDataStateError, ExecutionTiming, -}; -pub use guarantee::{ - AccuracyError, BoundExpr, CompositionOperator, ErrorMetric, GuaranteeSource, ProbabilityExpr, - ResultGuarantee, -}; -pub use query_time::{ - classic_cms_sizing, cms_posterior_error_bound, count_sketch_posterior_error_bound, - cu_sketch_posterior_error_bound, traditional_a_priori_bound, -}; -pub use sketch::{ - default_hydra_params, hydra_kind_for, EntityIdentity, ExactKind, ExactParams, GroupingStrategy, - HydraKind, HydraParams, NonNegativeWeightProof, SamplingKind, SamplingParams, SketchAlgorithm, - SketchCategory, SketchKind, SketchParams, SketchStatistic, StatModelKind, StatModelParams, - SummaryInputExpr, SummaryUpdate, WaveletKind, WaveletParams, WeightDomain, -}; -pub use summary_window::{ - plan_pane_phase, validate_pane_coverage, PaneCoverageError, PaneLayout, WindowEdgeCoverage, -}; diff --git a/crates/types/src/post_asap/query_time/error_estimation.rs b/crates/types/src/post_asap/query_time/error_estimation.rs deleted file mode 100644 index f2bf229da..000000000 --- a/crates/types/src/post_asap/query_time/error_estimation.rs +++ /dev/null @@ -1,643 +0,0 @@ -//! Posterior (query-time) sketch error estimation — Chen, Wu, Yang, Jiang, -//! Liu, ["Precise Error Estimation for Sketch-based Flow -//! Measurement"](https://zaoxing.github.io/papers/2021/IMC21_ErrorEstimation.pdf) -//! (IMC '21). Tracks issue #239. -//! -//! ## What this is -//! -//! The traditional CMS/Count-Sketch/CU-Sketch guarantee is an *a priori*, -//! worst-case bound derived before any data is seen: e.g. classic CMS sizing -//! (`w = ⌈e/ε⌉` counters/row, `r = ⌈ln(1/δ)⌉` rows — exactly -//! `crates/asap-aware-mapping/src/implementation.rs`'s `cms_width`/`cms_depth`) -//! guarantees `Pr[error > ε·|F|₁] < δ` obliviously to the real data -//! distribution, by construction assuming the adversarial worst case (§3, -//! §3.3 of the paper). -//! -//! The paper's insight: once a sketch has actually ingested data, its *real* -//! counter values already encode a tighter, still-rigorous bound — no need -//! to fall back to the worst case. [`cms_posterior_error_bound`] implements -//! that estimator (§3.1's Algorithm 1): given one sketch row's `w` counter -//! values and the target confidence `1−δ`, it returns the -//! `⌊w·δ^(1/r)⌋`-th largest counter in that row as the error bound, valid -//! with confidence `1−δ` for *any* flow's estimate (not just the one -//! queried) — proved in §3.2 (Theorems 3.1/3.2/3.4) to closely approximate -//! the true ground-truth error bound (bias `O(1/√w)`, Eq. 5), and in §3.3 -//! (Eq. 6) to always be at least as tight as the traditional a priori bound -//! for the same `(w, r)`. [`traditional_a_priori_bound`] and -//! [`classic_cms_sizing`] implement that traditional bound/sizing for -//! comparison — see [`cms_posterior_bound_is_at_most_traditional_bound`] -//! below for the checked property. -//! -//! Appendix A.1 generalizes the technique: [`cu_sketch_posterior_error_bound`] -//! (Algorithm 2) is — per the paper's own text — *identical* to -//! [`cms_posterior_error_bound`], since CU-Sketch shares CM-Sketch's -//! "minimum counter across rows" query paradigm. -//! [`count_sketch_posterior_error_bound`] (Algorithm 3) is Count-Sketch's -//! variant: because Count-Sketch estimates a flow's size as the *median* of -//! its `r` signed counters rather than the minimum, the estimator instead -//! searches for the smallest fractile `p₀` whose two-sided binomial-tail -//! probability clears `δ` (Theorem A.1, `r = 2k+1` odd only — see that -//! function's docs for why even `r` is out of scope here). -//! -//! ## What this is *not* — no runtime sketch exists yet to wire this into -//! -//! This issue names two possible integration points: (1) runtime/evaluation-time -//! accuracy reporting from a sketch's *actual* counters, and (2) tighter -//! plan-time sizing. As of this module landing, **this repository has no -//! vendored CMS/CountSketch/CU-Sketch runtime and no counter-array data -//! structure anywhere** — confirmed by inspecting -//! `crates/types/src/post_asap/sketch.rs` (`SketchAlgorithm`, `SketchParams`, -//! this module's neighbors) and `crates/asap-aware-mapping/src/implementation.rs` -//! (`default_size_params`, `cms_width`, `cms_depth`): both are purely -//! planning-time sizing metadata. There is no `A[row][col]` counter matrix -//! anywhere in the workspace for these functions to be handed at query -//! time. So integration point (1) — reporting an *actual* query's posterior -//! error from real counters at evaluation — has nothing to wire into today. -//! -//! The functions here are deliberately **sketch-object-agnostic**: they take -//! plain counter slices (`&[u64]` / `&[i64]`) and numeric parameters, not a -//! concrete sketch type, specifically so that the moment a real CMS/ -//! Count-Sketch/CU-Sketch runtime lands in this workspace, its evaluation path -//! can call these functions directly on its real counter arrays with zero -//! changes needed here. That wiring is out of scope for this module — see -//! issue #239. -//! -//! Integration point (2) — tighter *plan-time* sizing under an expected-case -//! (non-adversarial) assumption — is wired for real, since it touches code -//! that already exists: see -//! `crates/asap-aware-mapping/src/implementation.rs::posterior_aware_size_params`. - -// ── Posterior (query-time) estimators ─────────────────────────────────────── - -/// Count-Min Sketch posterior error estimator — §3.1, Algorithm 1. -/// -/// `row` is one sketch row's `w` raw counter values (any of the sketch's `r` -/// rows — the algorithm is defined per-row and every row gives an -/// independent, equally valid estimate). `rows` is the sketch's total row -/// count `r` (used only to convert the target confidence into the -/// per-row fractile `p = δ^(1/r)`, per the union-bound argument in §3.1: -/// "the probability δ that all r corresponding counters are not bounded by -/// g(δ) is p^r"). `delta` is the target failure probability `δ` (so the -/// returned bound holds with confidence `1−δ`). -/// -/// Returns the `⌊w·p⌋`-th largest value in `row` (1-indexed, clamped to -/// `[1, w]`), matching the paper's own descriptive prose in §3.1 ("report -/// the ⌊wp⌋-th largest counter as our estimation for g(δ)"). Note: the -/// paper's Algorithm 1 pseudocode box instead prints `⌈wp⌉` (ceiling) — the -/// paper is internally inconsistent between its prose and its pseudocode -/// box on this rounding direction. This implementation follows the prose -/// (and issue #239's own paraphrase of it); the two conventions differ by -/// at most one rank, well within the paper's own `O(1/√w)` bias bound -/// (Eq. 5), so the choice does not affect any of this module's correctness -/// properties. -/// -/// Returns `None` for degenerate inputs: an empty row, zero rows, or `delta` -/// outside `(0, 1]`. -pub fn cms_posterior_error_bound(row: &[u64], rows: u32, delta: f64) -> Option { - let idx = posterior_rank(row.len(), rows, delta)?; - Some(kth_largest(row, idx)) -} - -/// CU-Sketch posterior error estimator — Appendix A.1, Algorithm 2. -/// -/// Per the paper: "the algorithm for CU-Sketch is exactly the same as that -/// for CM-Sketch due to their similar properties in generating sketch: they -/// share a common query paradigm that returns the minimum counter value -/// among the `r` rows as the estimated flow size." This is a distinctly -/// named entry point (matching the paper's own Algorithm 2 naming) that -/// delegates to [`cms_posterior_error_bound`] rather than duplicating its -/// logic — see that function's docs for the full parameter/behavior -/// contract, which applies verbatim here. -pub fn cu_sketch_posterior_error_bound(row: &[u64], rows: u32, delta: f64) -> Option { - cms_posterior_error_bound(row, rows, delta) -} - -/// Count-Sketch posterior error estimator — Appendix A.1, Algorithm 3. -/// -/// Count-Sketch counters are signed (each row's hash also picks a random -/// sign, so a flow's contribution can subtract as well as add — "balanced/ -/// zero-mean-error" per `SketchAlgorithm::CountSketch`'s own doc), and a flow's -/// size is estimated as the *median*, not the minimum, of its `r` per-row -/// counters. That breaks Algorithm 1/2's simple `p = δ^(1/r)` derivation (a -/// union bound over "any row is bad"): the median needs *more than half* the -/// rows to be bad, so Algorithm 3 instead searches for the smallest -/// fractile `p₀ ∈ {2/w, 3/w, …}` whose two-sided binomial-tail probability — -/// the chance that more than half of `r` independent `Bernoulli(p₀/2)` -/// trials succeed — first reaches `δ`, then reports the `⌈w·p₀⌉`-th largest -/// *absolute* counter value at that `p₀` (`row` here is `A[1][1..w]`, -/// unsigned by absolute value, matching Algorithm 3's -/// `SortToDescendingOrder(|A[1][1]| … |A[1][w]|)`). -/// -/// Theorem A.1 states the optimal bound only for `r = 2k+1` (odd); the -/// paper's own footnote for the even case ("Similar equation for an even -/// r") does not spell out the formula. Per issue #239's instruction to -/// "only implement what you can read and verify" rather than guess, this -/// function requires odd `rows` and returns `None` for even `rows` — a -/// documented scope boundary, not an oversight. -/// -/// Returns `None` for: an empty `row`, `rows == 0`, even `rows`, or `delta` -/// outside `(0, 1]`. -pub fn count_sketch_posterior_error_bound(row: &[i64], rows: u32, delta: f64) -> Option { - let w = row.len(); - if w == 0 || rows == 0 || rows.is_multiple_of(2) || !(delta > 0.0 && delta <= 1.0) { - return None; - } - let r = rows as u64; - // Majority threshold: for r = 2k+1, this is k+1 — the smallest j for - // which "j of r rows" is a strict majority. Also correct (by the same - // "more than half" reading) for the even-r case this function declines - // to handle, but we never reach here with even r. - let j_start = r.div_ceil(2); - - // `C(r, j)` for every `j` in `j_start..=r`, computed once via the - // incremental recurrence below (O(r) total) instead of letting - // `binomial_tail` recompute `binomial_coeff` (itself O(r)) from - // scratch for every `j` on every fractile tried — the fractile search - // just below evaluates the tail up to `log2(w)` times, so hoisting - // this out turns each evaluation's cost from O(r²) into O(r). - let coeffs = binomial_coeffs_from(r, j_start); - - // `2 * binomial_tail(p0/2)` is monotonically non-decreasing in `p0` - // (raising each row's bad-probability can only raise the chance that a - // majority of rows are bad), so the smallest qualifying fractile - // `p0 = (i+1)/w` is a binary search over `i`, not a linear scan — - // O(log w) tail evaluations instead of O(w). - let satisfies = |i: usize| -> bool { - let p0 = ((i + 1) as f64 / w as f64).min(1.0); - 2.0 * binomial_tail_with_coeffs(&coeffs, r, j_start, p0 / 2.0) >= delta - }; - let mut lo = 1usize; - let mut hi = w; - while lo < hi { - let mid = lo + (hi - lo) / 2; - if satisfies(mid) { - hi = mid; - } else { - lo = mid + 1; - } - } - // `lo == hi`: either `satisfies(lo)`, or `lo == w` and the search - // never found one — matching the original linear scan's fallback, - // which left `chosen_p0` at its pre-loop-initialized `1.0` in that - // case (the same value `p0(w)` evaluates to below). - let chosen_p0 = ((lo + 1) as f64 / w as f64).min(1.0); - - let idx = ((w as f64) * chosen_p0).ceil() as usize; - let idx = idx.clamp(1, w); - let abs_row: Vec = row.iter().map(|v| v.unsigned_abs()).collect(); - Some(kth_largest(&abs_row, idx)) -} - -// ── Traditional a priori bound (§3.3), for comparison ────────────────────── - -/// `⌈x⌉` clamped to `[lo, hi]`; NaN / non-positive `x` saturate to `hi` (a -/// degenerate accuracy target means "as accurate as this family goes"). -/// Byte-for-byte the same policy as `implementation.rs`'s private -/// `saturating_ceil` — duplicated here, not imported, for the same -/// layering reason [`classic_cms_sizing`] itself is duplicated rather than -/// calling `implementation.rs` directly. -fn saturating_ceil(x: f64, lo: u32, hi: u32) -> u32 { - if !x.is_finite() || x <= 0.0 { - return hi; - } - (x.ceil() as u32).clamp(lo, hi) -} - -/// The classic CMS `(ε, δ)` sizing formula (§3.3, restated just before -/// Eq. 6; identical — formula *and* clamping — to -/// `crates/asap-aware-mapping/src/implementation.rs`'s private -/// `cms_width`/`cms_depth`, reimplemented here — deliberately, not by -/// accident — because `asap-types` sits below `asap-aware-mapping` in the -/// workspace's dependency layering and cannot import from it): `w = ⌈e/ε⌉` -/// counters/row, clamped to `[2, 2²⁶]`; `r = ⌈ln(1/δ)⌉` rows, clamped to -/// `[1, 32]`. -/// -/// Returns `(width, depth)`. Matching `implementation.rs`'s own clamp semantics -/// exactly (not just its in-range formula) matters here specifically: -/// this function's whole purpose is giving comparison/test code (and, -/// per issue #250, a future replan) the traditional bound to compare -/// this module's posterior bound against — an un-clamped reimplementation -/// would silently diverge from `implementation.rs`'s real sizing outside a -/// narrow "nothing saturates" range of `(eps, delta)`, exactly the range -/// most tests default to, making the divergence easy to miss. -pub fn classic_cms_sizing(eps: f64, delta: f64) -> (u32, u32) { - let width = saturating_ceil(std::f64::consts::E / eps, 2, 1 << 26); - let depth = saturating_ceil((1.0 / delta).ln(), 1, 32); - (width, depth) -} - -/// The traditional a priori bound value itself: `ε·|F|₁`, the classic CMS -/// guarantee's right-hand side (§3.3: "the original CM bound … guarantees -/// `Pr[𝕏ₑᵢ > ε|F|₁] < δ`"). Exists so a posterior bound (in the same -/// counter units as `total_flow_size`) can be compared directly against the -/// traditional worst-case bound it is meant to improve on — see -/// [`cms_posterior_bound_is_at_most_traditional_bound`]'s test below. -pub fn traditional_a_priori_bound(total_flow_size: u64, eps: f64) -> f64 { - eps * total_flow_size as f64 -} - -// ── Shared internals ───────────────────────────────────────────────────────── - -/// `⌊w·δ^(1/r)⌋`, clamped to `[1, w]` (1-indexed rank into a -/// descending-sorted row of `w` counters). `None` for degenerate inputs. -fn posterior_rank(w: usize, rows: u32, delta: f64) -> Option { - if w == 0 || rows == 0 || !(delta > 0.0 && delta <= 1.0) { - return None; - } - let p = delta.powf(1.0 / rows as f64); - let idx = ((w as f64) * p).floor() as i64; - Some((idx.max(1) as usize).min(w)) -} - -/// The `k`-th largest value in `values` (1-indexed): sorts a copy in -/// descending order and returns `sorted[k-1]`. `k` is expected already -/// clamped to `[1, values.len()]` by the caller. -/// The `k`-th largest value in `values` (1-indexed: `k=1` is the max). -/// `select_nth_unstable_by` partitions in O(w) average instead of fully -/// sorting in O(w log w) — this only ever needs one rank, not a total -/// order, and both call sites (this module's per-query evaluation math) are -/// documented as meant to run on a future runtime's hot evaluation path. -fn kth_largest(values: &[u64], k: usize) -> u64 { - let mut buf: Vec = values.to_vec(); - let idx = k - 1; - let (_, &mut kth, _) = buf.select_nth_unstable_by(idx, |a, b| b.cmp(a)); - kth -} - -/// `Σ_{j=j_start}^{r} C(r, j) · p^j · (1-p)^(r-j)` — the upper binomial tail -/// probability, given `coeffs[i] = C(r, j_start + i)` already computed by -/// [`binomial_coeffs_from`]. Split out from the coefficient computation so -/// a caller trying several `p` values against the same `(r, j_start)` (as -/// [`count_sketch_posterior_error_bound`]'s fractile search does) pays for -/// the coefficients once, not once per `p`. -fn binomial_tail_with_coeffs(coeffs: &[f64], r: u64, j_start: u64, p: f64) -> f64 { - let p = p.clamp(0.0, 1.0); - coeffs - .iter() - .enumerate() - .map(|(offset, &c)| { - let j = j_start + offset as u64; - c * p.powi(j as i32) * (1.0 - p).powi((r - j) as i32) - }) - .sum() -} - -/// `C(r, j)` for every `j` in `j_start..=r`, in one O(r) pass via the -/// incremental recurrence `C(r,j) = C(r,j-1) · (r-j+1)/j` — instead of -/// calling [`binomial_coeff`] (itself O(r)) fresh for every `j`, which is -/// what made evaluating a single tail probability O(r²). -fn binomial_coeffs_from(r: u64, j_start: u64) -> Vec { - let mut coeffs = Vec::with_capacity((r - j_start + 1) as usize); - let mut c = binomial_coeff(r, j_start); - coeffs.push(c); - for j in (j_start + 1)..=r { - c = c * (r - j + 1) as f64 / j as f64; - coeffs.push(c); - } - coeffs -} - -/// `C(n, k)`, computed as an iterative running product in `f64` (avoids -/// factorial overflow; exact for the small `n` realistic sketch depths use, -/// and only ever used as a probability-mass weight so `f64` rounding is -/// immaterial). -fn binomial_coeff(n: u64, k: u64) -> f64 { - let k = k.min(n - k); - let mut result = 1.0_f64; - for i in 0..k { - result = result * (n - i) as f64 / (i + 1) as f64; - } - result -} - -#[cfg(test)] -mod tests { - use super::*; - - // ── Algorithm 1 (CM-Sketch) — hand-computable examples ────────────────── - - #[test] - fn cms_single_row_confidence_one_picks_the_largest_counter() { - // rows=1, delta=1 ⇒ p = 1^(1/1) = 1 ⇒ index = floor(w*1) = w ⇒ the - // w-th largest = the *smallest* counter (delta=1 means "no - // confidence required", so the loosest possible bound is fine — - // this pins the boundary behavior, not a meaningful confidence). - let row = [10u64, 4, 7, 1]; - assert_eq!(cms_posterior_error_bound(&row, 1, 1.0), Some(1)); - } - - #[test] - fn cms_hand_computed_example() { - // r=2, delta=0.25 ⇒ p = 0.25^(1/2) = 0.5. w=10 ⇒ index = floor(10*0.5) = 5. - // Descending-sorted row: [10,9,8,7,6,5,4,3,2,1] ⇒ 5th largest = 6. - let row: Vec = (1..=10).collect(); // [1..10] - assert_eq!(cms_posterior_error_bound(&row, 2, 0.25), Some(6)); - } - - #[test] - fn cms_rank_clamped_to_at_least_one() { - // Very small p (large r, small delta) floors to 0 — must clamp to - // rank 1 (the single largest counter), not panic / index -1. - let row = [5u64, 100, 1]; - let bound = cms_posterior_error_bound(&row, 50, 1e-9).unwrap(); - assert_eq!(bound, 100); // the largest counter - } - - #[test] - fn cms_all_zero_counters_bound_is_zero() { - let row = [0u64; 8]; - assert_eq!(cms_posterior_error_bound(&row, 3, 0.05), Some(0)); - } - - #[test] - fn cms_degenerate_inputs_return_none() { - assert_eq!(cms_posterior_error_bound(&[], 3, 0.05), None); - assert_eq!(cms_posterior_error_bound(&[1, 2, 3], 0, 0.05), None); - assert_eq!(cms_posterior_error_bound(&[1, 2, 3], 3, 0.0), None); - assert_eq!(cms_posterior_error_bound(&[1, 2, 3], 3, -0.1), None); - assert_eq!(cms_posterior_error_bound(&[1, 2, 3], 3, 1.5), None); - } - - #[test] - fn cms_monotonic_in_width_tighter_bound_as_w_grows() { - // Hold the *total* collided mass fixed and spread it over more - // counters: a wider sketch means less collision per counter for - // the same workload, so the reported bound should not increase. - // (Using row = 1..=w instead — growing *with* w — would grow the - // total mass too, which is a different, unrelated effect; the - // fixed-total-uniform-spread row below isolates width alone.) - let total = 20_160u64; // divisible by every width below - let mut previous = u64::MAX; - for w in [10usize, 20, 40, 80, 160] { - let row = vec![total / w as u64; w]; - let bound = cms_posterior_error_bound(&row, 4, 0.1).unwrap(); - assert!( - bound <= previous, - "bound grew from {previous} to {bound} as w increased to {w}" - ); - previous = bound; - } - } - - #[test] - fn cms_monotonic_in_rows_tighter_bound_as_r_grows() { - // Algorithm 1 computes its bound from *one* row's counters; `rows` - // (r) only feeds into p = delta^(1/r). For delta < 1, delta^(1/r) - // increases toward 1 as r grows (more rows ⇒ the union bound over - // "any row is bad" needs a looser per-row p to keep the same - // overall delta), which raises the rank index ⌊w·p⌋ — i.e. r is a - // confidence dial that monotonically raises the rank (and, on a - // descending-sorted row, that means an equal-or-tighter reported - // bound). We assert the rank itself grows monotonically with r, - // which is the exact, documented relationship. - let row: Vec = (1..=100).rev().collect(); - let mut previous_idx = 0usize; - for r in [1u32, 2, 4, 8, 16, 32] { - let idx = posterior_rank(row.len(), r, 0.1).unwrap(); - assert!( - idx >= previous_idx, - "rank shrank from {previous_idx} to {idx} as r grew to {r}" - ); - previous_idx = idx; - } - } - - // ── Algorithm 2 (CU-Sketch) — identical to Algorithm 1 ───────────────── - - #[test] - fn cu_sketch_matches_cms_exactly() { - let row: Vec = (1..=50).collect(); - for (r, delta) in [(1u32, 0.5), (3, 0.1), (7, 0.01)] { - assert_eq!( - cu_sketch_posterior_error_bound(&row, r, delta), - cms_posterior_error_bound(&row, r, delta) - ); - } - } - - // ── Algorithm 3 (Count-Sketch) ─────────────────────────────────────────── - - #[test] - fn count_sketch_rejects_even_rows() { - let row = [3i64, -5, 2, 8]; - assert_eq!(count_sketch_posterior_error_bound(&row, 4, 0.05), None); - } - - #[test] - fn count_sketch_uses_absolute_values() { - // Symmetric-magnitude row: signs shouldn't change the bound. - let row_pos: Vec = (1..=21).collect(); - let row_neg: Vec = (1..=21).map(|v| -v).collect(); - let a = count_sketch_posterior_error_bound(&row_pos, 5, 0.05); - let b = count_sketch_posterior_error_bound(&row_neg, 5, 0.05); - assert!(a.is_some()); - assert_eq!(a, b); - } - - #[test] - fn count_sketch_degenerate_inputs_return_none() { - assert_eq!(count_sketch_posterior_error_bound(&[], 3, 0.05), None); - assert_eq!( - count_sketch_posterior_error_bound(&[1, 2, 3], 0, 0.05), - None - ); - assert_eq!(count_sketch_posterior_error_bound(&[1, 2, 3], 3, 0.0), None); - assert_eq!(count_sketch_posterior_error_bound(&[1, 2, 3], 3, 1.5), None); - } - - #[test] - fn count_sketch_single_row_extreme_confidence() { - // r=1 (odd), delta=1: the loosest possible ask — should resolve to - // *some* valid rank in range without panicking. - let row: Vec = vec![9, -4, 7, -1, 3]; - let bound = count_sketch_posterior_error_bound(&row, 1, 1.0).unwrap(); - assert!(row.iter().any(|v| v.unsigned_abs() == bound)); - } - - #[test] - fn count_sketch_monotonic_in_width() { - // Same fixed-total-uniform-spread construction as the CMS - // monotonicity test above — isolates width's effect from total - // mass's. - let total = 20_160i64; - let mut previous = u64::MAX; - for w in [10usize, 20, 40, 80, 160] { - let row = vec![total / w as i64; w]; - let bound = count_sketch_posterior_error_bound(&row, 5, 0.1).unwrap(); - assert!( - bound <= previous, - "bound grew from {previous} to {bound} as w increased to {w}" - ); - previous = bound; - } - } - - // ── Traditional bound / classic sizing ────────────────────────────────── - - #[test] - fn classic_cms_sizing_matches_implementation_rs_formula() { - // Same worked example as - // `asap-aware-mapping::replacement::tests::epsilon_delta_sizes_cms_depth` - // (eps=0.001, delta=0.001 ⇒ width=2719, depth=7), pinned here too so - // the two independent (layering-forced) reimplementations can't - // silently drift apart undetected. - assert_eq!(classic_cms_sizing(0.001, 0.001), (2719, 7)); - assert_eq!(classic_cms_sizing(0.01, 0.01), (272, 5)); - } - - #[test] - fn classic_cms_sizing_degenerate_inputs_saturate_like_implementation_rs() { - // Degenerate width/depth saturate to their hi clamp (2^26 / 32), - // matching `implementation.rs`'s `saturating_ceil` exactly — not `0` (see - // the correctness fix on `classic_cms_sizing`'s doc comment: an - // earlier version returned `(0, 0)` here, silently diverging from - // `implementation.rs`'s real degenerate-input behavior). - assert_eq!(classic_cms_sizing(0.0, 0.01), (1 << 26, 5)); - assert_eq!(classic_cms_sizing(0.01, 0.0), (272, 32)); - assert_eq!(classic_cms_sizing(0.01, 1.0), (272, 32)); - assert_eq!(classic_cms_sizing(f64::NAN, 0.01), (1 << 26, 5)); - } - - /// Pinned extreme-range values — the clamp actually engaging, not just - /// the in-range formula — computed by hand against the same - /// `[2, 2²⁶]` / `[1, 32]` bounds `implementation.rs`'s `cms_width`/`cms_depth` - /// use, so a future edit that reintroduces the un-clamped bug (an - /// earlier version of this function silently diverged from - /// `implementation.rs` outside the narrow range most other tests exercise) - /// gets caught here. - #[test] - fn classic_cms_sizing_clamps_extreme_ranges_like_implementation_rs() { - // eps=1e-10: raw width e/eps ≈ 2.7e10, hi-clamped to 2^26. - assert_eq!(classic_cms_sizing(1e-10, 0.01), (1 << 26, 5)); - // eps=3.0: raw width e/3 < 1, lo-clamped to 2. - assert_eq!(classic_cms_sizing(3.0, 0.01), (2, 5)); - // delta=1e-20: raw depth ln(1e20) ≈ 46.05 → ⌈⌉ 47, hi-clamped to 32. - assert_eq!(classic_cms_sizing(0.01, 1e-20), (272, 32)); - } - - #[test] - fn traditional_bound_is_linear_in_total_and_eps() { - assert_eq!(traditional_a_priori_bound(1_000_000, 0.01), 10_000.0); - assert_eq!(traditional_a_priori_bound(0, 0.01), 0.0); - } - - // ── The correctness property this issue is actually about: the ──────── - // ── posterior bound (Algorithm 1) is always ≤ the traditional a ─────── - // ── priori bound (Eq. 6), for the same worst-case (w, r) sizing. ────── - - /// A tiny deterministic PRNG (xorshift64*) — enough to generate varied - /// synthetic counter distributions without adding a `rand` dependency - /// to this crate. - struct Xorshift64(u64); - impl Xorshift64 { - fn next(&mut self) -> u64 { - let mut x = self.0; - x ^= x << 13; - x ^= x >> 7; - x ^= x << 17; - self.0 = x; - x - } - /// A weight in `[1, max]`, skewed low (many small draws, occasional - /// large one) by squaring a uniform fraction — cheap stand-in for a - /// heavy-tailed/Zipf-like distribution shape. - fn skewed_weight(&mut self, max: u64) -> u64 { - let u = (self.next() % 1_000_000) as f64 / 1_000_000.0; - let skewed = u * u; // biases toward 0 - 1 + (skewed * max as f64) as u64 - } - } - - /// Distributes `total` across `w` non-negative counters honoring a CMS - /// row's real structure: each unit of `total` lands in exactly one of - /// the `w` counters (a counter is a sum of colliding flow weights), so - /// `Σ counters == total` always — the property Eq. 6's proof relies on. - fn synthetic_row(rng: &mut Xorshift64, w: usize, total: u64, skewed: bool) -> Vec { - let mut counters = vec![0u64; w]; - let mut remaining = total; - while remaining > 0 { - let bucket = (rng.next() as usize) % w; - let chunk = if skewed { - rng.skewed_weight(remaining.min(1000)) - } else { - 1 + rng.next() % remaining.clamp(1, 37) - } - .min(remaining); - counters[bucket] += chunk; - remaining -= chunk; - } - counters - } - - #[test] - fn cms_posterior_bound_is_at_most_traditional_bound() { - // The paper's Eq. 6 claim: at the standard worst-case sizing - // (w=classic width, r=classic depth for a target (eps,delta)), the - // posterior bound computed from real counters never exceeds the - // traditional a priori bound eps*|F|1 — regardless of how the - // total mass is actually distributed across counters. - let mut rng = Xorshift64(0x243F6A8885A308D3); - for (eps, delta) in [(0.05, 0.05), (0.02, 0.1), (0.1, 0.01), (0.03, 0.2)] { - let (w, r) = classic_cms_sizing(eps, delta); - let traditional = traditional_a_priori_bound(1_000_000, eps); - for skewed in [false, true] { - for trial in 0..20 { - rng.0 = rng.0.wrapping_add(0x9E3779B97F4A7C15).wrapping_add(trial); - let row = synthetic_row(&mut rng, w as usize, 1_000_000, skewed); - let posterior = - cms_posterior_error_bound(&row, r, delta).expect("valid inputs"); - assert!( - (posterior as f64) <= traditional + 1e-6, - "posterior bound {posterior} exceeded traditional bound \ - {traditional} for eps={eps} delta={delta} w={w} r={r} \ - skewed={skewed} trial={trial}" - ); - } - } - } - } - - #[test] - fn cms_posterior_bound_at_most_traditional_bound_worst_case_single_counter() { - // Degenerate worst case: all mass in one counter (maximum possible - // collision) — the pigeonhole argument underlying Eq. 6 still must - // hold: a single counter holding the entire total is itself only - // ever picked as the estimate when the rank lands on it, and - // whenever it isn't, the picked counter is 0 <= traditional bound. - for (eps, delta) in [(0.05, 0.05), (0.01, 0.01)] { - let (w, r) = classic_cms_sizing(eps, delta); - let traditional = traditional_a_priori_bound(1_000_000, eps); - let mut row = vec![0u64; w as usize]; - row[0] = 1_000_000; - let posterior = cms_posterior_error_bound(&row, r, delta).expect("valid inputs"); - assert!( - (posterior as f64) <= traditional + 1e-6, - "posterior bound {posterior} exceeded traditional bound {traditional}" - ); - } - } - - #[test] - fn kth_largest_pigeonhole_property() { - // The elementary fact Eq. 6's proof leans on: for w non-negative - // counters summing to T, the k-th largest is at most T/k. This is - // the general-purpose invariant behind the paper-specific test - // above, checked directly and unconditionally (no sketch sizing - // formula involved). - let mut rng = Xorshift64(0xD1B54A32D192ED03); - for _ in 0..50 { - let w = 5 + (rng.next() % 50) as usize; - let total = 1 + rng.next() % 100_000; - let row = synthetic_row(&mut rng, w, total, true); - let sum: u64 = row.iter().sum(); - assert_eq!(sum, total); - for k in 1..=w { - let kth = kth_largest(&row, k); - assert!( - (kth as f64) * (k as f64) <= (total as f64) + 1e-6, - "k={k}-th largest {kth} violates k*kth <= total ({total})" - ); - } - } - } -} diff --git a/crates/types/src/post_asap/query_time/mod.rs b/crates/types/src/post_asap/query_time/mod.rs deleted file mode 100644 index 44e979117..000000000 --- a/crates/types/src/post_asap/query_time/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -//! Code meant to run at **query execution time**, not planning time — -//! folder-separated from `post_asap`'s other modules ([`super::expr`], -//! [`super::schema`], [`super::sketch`]) on purpose. -//! -//! `asap-types`' crate doc states the invariant this workspace otherwise -//! holds to without exception: "no execution logic lives in this -//! workspace (issue #190) — a downstream deployment crate is expected to -//! supply that." Everything else under [`super`] is *planning*-time IR — -//! types the planner (`asap-aware-mapping`) constructs and commits to -//! before a query ever runs, describing *what* summary will be built, not -//! *computing over* one that has run. -//! -//! [`error_estimation`] is the one deliberate exception, and this -//! submodule exists so that exception is visible in the directory listing -//! itself, not just in prose: it holds pure, sketch-object-agnostic *math* -//! (given a sketch's real counter values, compute a tighter posterior -//! error bound) that only makes sense to invoke *after* a real sketch has -//! ingested data and is being read out — a downstream runtime's job, not -//! this crate's. Nothing in `asap-types` or `asap-aware-mapping` calls -//! into this module today; it is a library waiting for a runtime that -//! doesn't exist yet in this workspace (see [`error_estimation`]'s own -//! docs for exactly what's blocked and why). -//! -//! Contrast with `asap-aware-mapping::replacement::posterior_aware_size_params` -//! (issue #239, PR #248): that function is real, wired *planning*-time -//! code — it lives in the planning crate, not here, and does not call -//! into this module. It borrows the same underlying intuition (a -//! non-adversarial workload can use a smaller sketch than the worst case) -//! but as an explicit, caller-supplied planning-time assumption, not a -//! query-time measurement — the two are independent by construction. See -//! issue #250 for the still-unimplemented idea of actually connecting -//! them: recording this module's query-time observations over time and -//! feeding them into a future replan. - -pub mod error_estimation; - -// Glob, not a named list: this submodule exists only to hold -// `error_estimation` today, so re-exporting everything it makes public -// keeps this hop in sync automatically — a new `pub fn` there needs no -// matching edit here, only in `post_asap::mod`'s own list below (the -// actual curated short-path public surface, kept explicit like `expr`'s -// and `sketch`'s re-exports). -pub use error_estimation::*; diff --git a/crates/types/src/pre_asap/mod.rs b/crates/types/src/pre_asap/mod.rs deleted file mode 100644 index c309c7b30..000000000 --- a/crates/types/src/pre_asap/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! Shared vocabulary of the operator IR. The operators themselves live in -//! [`crate::ir`]; this module holds the field types they are built from. -//! -//! Operator parameters and schema derivation live in [`crate::ir`]. -//! - [`agg_intent`] — the aggregation-intent vocabulary ([`AggIntent`]). -//! - [`expr_ir`] — [`ColumnRef`] and the scalar literal / operator kinds -//! ([`ScalarValue`], [`CompareOpKind`], [`ArithmeticOpKind`]). -//! - [`schema`] — the per-edge [`Schema`] every node carries. -//! - [`column_resolution`] — turn a name-based `ColumnRef` into a positional -//! `ColumnId` against a [`Schema`] (used by front-end name resolution). -//! - [`scalar_type_rules`] — shared scalar type and nullability rules. - -pub mod agg_intent; -pub mod column_resolution; -pub mod expr_ir; -pub mod scalar_type_rules; -pub mod schema; - -pub use crate::ir::operator_properties::{ - AtModifier, BinaryOpKind, ColState, ConcatDiscriminatorKey, DataModel, GroupKeys, GroupSide, - InfoMatcher, JoinKind, PromQLVectorSetOpKind, Reduction, RelationalSetOpKind, SampleKind, - Source, TimeShift, VectorGrouping, VectorMatch, VectorMatchKind, WindowFrame, WindowFrameBound, - WindowFrameOffset, WindowFrameUnits, WindowFuncKind, -}; -pub use agg_intent::{ - agg_accuracy, agg_is_exact, agg_is_mergeable, default_cardinality, default_quantile, AggIntent, - MathFunc, TimeFunc, -}; -pub use column_resolution::{resolve_column_ref, resolve_column_refs, ResolveError}; -pub use expr_ir::{ArithmeticOpKind, ColumnRef, CompareOpKind, ScalarValue}; -pub use schema::{ColumnId, DataType, Field, FieldDataType, Schema}; - -pub use crate::ir::aggregate_schema::aggregate_output_schema; -pub use crate::ir::SchemaDerivationError; diff --git a/crates/types/src/workload.rs b/crates/types/src/workload/mod.rs similarity index 99% rename from crates/types/src/workload.rs rename to crates/types/src/workload/mod.rs index 5e1a5d48c..0289d2e38 100644 --- a/crates/types/src/workload.rs +++ b/crates/types/src/workload/mod.rs @@ -1,3 +1,6 @@ +pub mod parsed_workload; +pub mod resources; + use crate::types::AccuracyTarget; use serde::{Deserialize, Serialize}; diff --git a/crates/types/src/parsed_workload.rs b/crates/types/src/workload/parsed_workload.rs similarity index 100% rename from crates/types/src/parsed_workload.rs rename to crates/types/src/workload/parsed_workload.rs diff --git a/crates/types/src/resources.rs b/crates/types/src/workload/resources.rs similarity index 100% rename from crates/types/src/resources.rs rename to crates/types/src/workload/resources.rs diff --git a/crates/types/src/resources/cache.rs b/crates/types/src/workload/resources/cache.rs similarity index 100% rename from crates/types/src/resources/cache.rs rename to crates/types/src/workload/resources/cache.rs diff --git a/crates/types/src/resources/cpu.rs b/crates/types/src/workload/resources/cpu.rs similarity index 100% rename from crates/types/src/resources/cpu.rs rename to crates/types/src/workload/resources/cpu.rs diff --git a/crates/types/src/resources/measurement.rs b/crates/types/src/workload/resources/measurement.rs similarity index 100% rename from crates/types/src/resources/measurement.rs rename to crates/types/src/workload/resources/measurement.rs diff --git a/crates/types/src/resources/physical.rs b/crates/types/src/workload/resources/physical.rs similarity index 100% rename from crates/types/src/resources/physical.rs rename to crates/types/src/workload/resources/physical.rs diff --git a/crates/types/src/resources/physical_handoff.rs b/crates/types/src/workload/resources/physical_handoff.rs similarity index 100% rename from crates/types/src/resources/physical_handoff.rs rename to crates/types/src/workload/resources/physical_handoff.rs diff --git a/crates/types/src/resources/storage.rs b/crates/types/src/workload/resources/storage.rs similarity index 100% rename from crates/types/src/resources/storage.rs rename to crates/types/src/workload/resources/storage.rs diff --git a/crates/types/tests/physical_export.rs b/crates/types/tests/physical_export.rs index cacf23284..a50526afc 100644 --- a/crates/types/tests/physical_export.rs +++ b/crates/types/tests/physical_export.rs @@ -1,13 +1,16 @@ //! A timed plan exports as a PhysicalASAPDAG that keeps timing. +use asap_types::ir::operator::{Reduction, Source}; use asap_types::ir::physical_export::{ compile_physical_asap_dag, PhysicalASAPDAGDocument, PhysicalASAPDAGValidationError, }; +use asap_types::ir::properties::ExecutionTiming; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{DataType, Field, FieldDataType, Schema}; +use asap_types::ir::schema::{ExactKind, ExactParams, SummaryUpdate}; use asap_types::ir::{ apply_materialization_timings, ASAPOp, MaterializationAssignment, NonASAPOp, Operator, OperatorNode, TimingMemo, }; -use asap_types::post_asap::{ExactKind, ExactParams, ExecutionTiming, SummaryUpdate}; -use asap_types::pre_asap::{ColumnRef, DataType, Field, FieldDataType, Reduction, Schema, Source}; use std::rc::Rc; /// Scan(t) → SummaryAgg(sum by key) → FinalizeExactAccumulator, untimed. diff --git a/crates/types/tests/planner_vocabulary.rs b/crates/types/tests/planner_vocabulary.rs index 82f1cbc1a..bb04225d2 100644 --- a/crates/types/tests/planner_vocabulary.rs +++ b/crates/types/tests/planner_vocabulary.rs @@ -1,6 +1,6 @@ use asap_types::ir::physical_export::WindowEdgeCompatibility; -use asap_types::post_asap::{validate_pane_coverage, PaneLayout, WindowEdgeCoverage}; -use asap_types::resources::{PhysicalHandoffBytes, PhysicalHandoffKind}; +use asap_types::physical::{validate_pane_coverage, PaneLayout, WindowEdgeCoverage}; +use asap_types::workload::resources::{PhysicalHandoffBytes, PhysicalHandoffKind}; // Renamed pane APIs still read and emit the deployed wire contract. #[test] diff --git a/crates/types/tests/schema_rebuilding.rs b/crates/types/tests/schema_rebuilding.rs index bb9f07526..66c4e8bc6 100644 --- a/crates/types/tests/schema_rebuilding.rs +++ b/crates/types/tests/schema_rebuilding.rs @@ -1,10 +1,9 @@ +use asap_types::ir::operator::{AggIntent, Reduction, Source}; +use asap_types::ir::properties::{ExecutionTiming, ResultGuarantee}; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{DataType, Field, FieldDataType, Schema}; +use asap_types::ir::schema::{ExactKind, ExactParams, GroupingStrategy, SummaryUpdate}; use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}; -use asap_types::post_asap::{ - ExactKind, ExactParams, ExecutionTiming, GroupingStrategy, ResultGuarantee, SummaryUpdate, -}; -use asap_types::pre_asap::{ - AggIntent, ColumnRef, DataType, Field, FieldDataType, Reduction, Schema, Source, -}; use std::rc::Rc; fn scan(key_type: DataType, name: &str) -> Rc { @@ -122,7 +121,7 @@ fn validation_rejects_structural_overrides_for_both_categories() { /// Passthrough rewrites derive metadata and arity, but cannot guess alias positions. #[test] fn rebuilding_updates_metadata_and_requires_new_aliases_after_arity_changes() { - use asap_types::pre_asap::GroupKeys; + use asap_types::ir::operator::GroupKeys; let input = scan(DataType::Timestamp, "key"); let original = OperatorNode::new_shared(Operator::NonASAP(NonASAPOp::Limit { n: Some(10), @@ -159,8 +158,8 @@ fn rebuilding_updates_metadata_and_requires_new_aliases_after_arity_changes() { /// Maintaining membership and finalizing values preserve identity/time metadata. #[test] fn summary_transitions_preserve_structural_metadata() { - use asap_types::post_asap::maintained_population::{MaintainedPopulation, PopulationInput}; - use asap_types::pre_asap::GroupKeys; + use asap_types::ir::operator::maintained_population::{MaintainedPopulation, PopulationInput}; + use asap_types::ir::operator::GroupKeys; let mut schema = scan(DataType::Timestamp, "key").schema.clone(); schema.closed = true; schema.time_index = Some(0); diff --git a/crates/types/tests/structure_contract.rs b/crates/types/tests/structure_contract.rs index 181301237..850df5abe 100644 --- a/crates/types/tests/structure_contract.rs +++ b/crates/types/tests/structure_contract.rs @@ -1,7 +1,9 @@ +use asap_types::ir::operator::Source; +use asap_types::ir::scalar::ScalarValue; +use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::{ ExprSemantics, NonASAPOp, OperatorNode, OperatorResultKind, Predicate, ScalarExpr, }; -use asap_types::pre_asap::{DataType, Field, ScalarValue, Schema, Source}; use std::rc::Rc; fn scan() -> Rc { OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Scan { @@ -84,12 +86,13 @@ fn scalar_type_rules_fail_closed() { /// A state family is not interchangeable with another sketch or a scalar field. #[test] fn state_evaluations_and_passthrough_keep_their_contracts() { - use asap_types::ir::{ASAPOp, Operator, ProjectItem}; - use asap_types::post_asap::{ + use asap_types::ir::operator::Reduction; + use asap_types::ir::scalar::ColumnRef; + use asap_types::ir::schema::{ FieldDataType, GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SketchStatistic, SummaryUpdate, }; - use asap_types::pre_asap::{ColumnRef, Reduction}; + use asap_types::ir::{ASAPOp, Operator, ProjectItem}; let family = FieldDataType::Sketch( SketchKind::new(SketchAlgorithm::Kll, SketchParams::Kll { k: 100 }), GroupingStrategy::default(), @@ -138,8 +141,8 @@ fn state_evaluations_and_passthrough_keep_their_contracts() { /// Phase validation checks dependencies, without declaring a computation query-only. #[test] fn execution_timing_checks_edges_not_function_names() { + use asap_types::ir::properties::ExecutionTiming::{IngestionTime, QueryTime}; use asap_types::ir::ProjectItem; - use asap_types::post_asap::ExecutionTiming::{IngestionTime, QueryTime}; let input = Rc::new((*scan()).clone().with_timing(Some(IngestionTime))); let mut project = OperatorNode::new(asap_types::ir::Operator::NonASAP(NonASAPOp::Project { child: input, @@ -168,9 +171,11 @@ fn execution_timing_checks_edges_not_function_names() { /// Both operator categories use the same fallible schema-deriving constructor. #[test] fn shared_construction_derives_both_operator_categories() { + use asap_types::ir::operator::Reduction; + use asap_types::ir::scalar::ColumnRef; + use asap_types::ir::schema::FieldDataType; + use asap_types::ir::schema::{ExactKind, ExactParams, GroupingStrategy, SummaryUpdate}; use asap_types::ir::{ASAPOp, Operator, ProjectItem}; - use asap_types::post_asap::{ExactKind, ExactParams, GroupingStrategy, SummaryUpdate}; - use asap_types::pre_asap::{ColumnRef, FieldDataType, Reduction}; let input = scan(); let state = Rc::new( diff --git a/crates/types/tests/summary_coverage.rs b/crates/types/tests/summary_coverage.rs index 97be84b56..61793b249 100644 --- a/crates/types/tests/summary_coverage.rs +++ b/crates/types/tests/summary_coverage.rs @@ -5,17 +5,22 @@ use std::ops::Bound; use std::rc::Rc; use std::time::Duration; -use asap_types::ir::operator_properties::{Reduction, Source}; -use asap_types::ir::summary_coverage::{ColumnIdentity, Constraint, CoverageError, SelectionBox}; +use asap_types::ir::operator::TimeShift; +use asap_types::ir::operator::{Reduction, Source}; +use asap_types::ir::properties::summary_coverage::{ + ColumnIdentity, Constraint, CoverageError, SelectionBox, +}; +use asap_types::ir::properties::ExecutionTiming; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::scalar::{ArithmeticOpKind, CompareOpKind, ScalarValue}; +use asap_types::ir::schema::{DataType, Field, FieldDataType, Schema}; +use asap_types::ir::schema::{ + GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate, +}; use asap_types::ir::{ ASAPOp, ExprSemantics, NonASAPOp, Operator, OperatorNode, Predicate, ProjectItem, ScalarExpr, SchemaDerivationError, TimeRangeKind, }; -use asap_types::post_asap::{ - ExecutionTiming, GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate, -}; -use asap_types::pre_asap::expr_ir::{ArithmeticOpKind, CompareOpKind, ScalarValue}; -use asap_types::pre_asap::{ColumnRef, DataType, Field, FieldDataType, Schema, TimeShift}; const JOB: usize = 0; const REGION: usize = 1; diff --git a/crates/types/tests/summary_merge_structure.rs b/crates/types/tests/summary_merge_structure.rs index b621d8403..9a60c8d5a 100644 --- a/crates/types/tests/summary_merge_structure.rs +++ b/crates/types/tests/summary_merge_structure.rs @@ -1,10 +1,13 @@ //! Window composition merges compatible summary states without consuming raw rows. -use asap_types::{ - ir::operator_properties::{Reduction, Source}, - ir::{ASAPOp, ExprSemantics, NonASAPOp, Operator, OperatorNode, Predicate, ScalarExpr}, - post_asap::{GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate}, - pre_asap::expr_ir::{CompareOpKind, ScalarValue}, - pre_asap::{ColumnRef, DataType, Field, FieldDataType, Schema}, +use asap_types::ir::operator::{Reduction, Source}; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::scalar::{CompareOpKind, ScalarValue}; +use asap_types::ir::schema::{DataType, Field, FieldDataType, Schema}; +use asap_types::ir::schema::{ + GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate, +}; +use asap_types::ir::{ + ASAPOp, ExprSemantics, NonASAPOp, Operator, OperatorNode, Predicate, ScalarExpr, }; use std::rc::Rc; /// KLL over `value` for one `region`, so states of different regions are diff --git a/docs/design_docs/concepts/accuracy-models.md b/docs/design_docs/concepts/accuracy-models.md index baeadbe9e..1ee7502b2 100644 --- a/docs/design_docs/concepts/accuracy-models.md +++ b/docs/design_docs/concepts/accuracy-models.md @@ -320,5 +320,5 @@ not require a new selection rule for every sketch. Deployment extensions to metrics, assumptions and propagation. For implementation details, see the [accuracy module](../../../crates/asap-aware-mapping/src/accuracy/mod.rs), -[guarantee representation](../../../crates/types/src/post_asap/guarantee.rs), and +[guarantee representation](../../../crates/types/src/ir/properties/guarantee.rs), and [accuracy propagation companion](../../develop_docs/end-to-end-accuracy-guarantees.md). diff --git a/docs/design_docs/concepts/post-asap-ir.md b/docs/design_docs/concepts/post-asap-ir.md index 207ad227e..2401c491e 100644 --- a/docs/design_docs/concepts/post-asap-ir.md +++ b/docs/design_docs/concepts/post-asap-ir.md @@ -22,7 +22,7 @@ model or downstream runtime supports it. ## ASAP operators -Every variant of [`ASAPOp`](../../../crates/types/src/ir/asap.rs) operates +Every variant of [`ASAPOp`](../../../crates/types/src/ir/operator/asap.rs) operates over summary state rather than raw data. The summary family, kind/algorithm and parameters are committed in the node; the state itself is typed by the `FieldDataType` of the output field that carries it (`ExactAggregate`, @@ -104,7 +104,7 @@ not definitions of the operator. The logical DAG carries no timing: `OperatorNode::timing` is `None` on every front-end node and every candidate, and `map_children` clears it. Summary materialization chooses a timing per summary state and records it in a -[`MaterializationAssignment`](../../../crates/types/src/ir/timing.rs) (ingestion-time +[`MaterializationAssignment`](../../../crates/types/src/ir/properties/timing.rs) (ingestion-time maintenance or query-time computation per `SummaryAgg`). The default is `all_query_time()`; until Stage 2 materialization (#509) decides otherwise, the planner times every `SummaryAgg` at query time. diff --git a/docs/design_docs/decisions/concat-unique-keys.md b/docs/design_docs/decisions/concat-unique-keys.md index 9c0148abf..e84e25291 100644 --- a/docs/design_docs/decisions/concat-unique-keys.md +++ b/docs/design_docs/decisions/concat-unique-keys.md @@ -67,7 +67,7 @@ Both current `Concat`-constructing call sites, and every consumer of test fixtures) — none of them builds a fresh `Concat` with a `Dedup` on top that this feature could remove. - **Every consumer of `Schema::unique_keys`** in the DAG, to check for a - cost beyond "a literal `Dedup` node": `pre_asap::cse::share_common_sub_dags` + cost beyond "a literal `Dedup` node": `ir::cse::share_common_sub_dags` (gates CSE producer-sharing on `Schema::has_unique_key()`) and `asap_aware_mapping::rollup::is_legal_rollup_source` (gates rollup-source legality the same way, on an *`Aggregate`'s* own output schema). Neither diff --git a/docs/design_docs/decisions/cse-cost-model.md b/docs/design_docs/decisions/cse-cost-model.md index 7ada47bc5..1c20382d8 100644 --- a/docs/design_docs/decisions/cse-cost-model.md +++ b/docs/design_docs/decisions/cse-cost-model.md @@ -10,7 +10,7 @@ elimination) to identify eligible, structurally identical computations. A shared logical node records an opportunity for reuse; selecting maintained state or independent execution is a separate planning decision. -[`asap_types::pre_asap::cse::share_common_sub_dags`](../../../crates/types/src/pre_asap/cse.rs) +[`asap_types::ir::cse::share_common_sub_dags`](../../../crates/types/src/ir/cse.rs) (issue #223 stages 1-2, PR #235) already *detects* every structurally-identical, legally-shareable (`Schema::unique_keys`-gated) sub-DAG and shares it **unconditionally** — there is no cost gate on top of legality. This document diff --git a/docs/design_docs/proposals/asap-aware-mapping/analytical-resource-cost.md b/docs/design_docs/proposals/asap-aware-mapping/analytical-resource-cost.md index 6e270159e..7d0cd9d41 100644 --- a/docs/design_docs/proposals/asap-aware-mapping/analytical-resource-cost.md +++ b/docs/design_docs/proposals/asap-aware-mapping/analytical-resource-cost.md @@ -121,7 +121,7 @@ required: the result cache is filled by evaluations in this horizon. Buffer residency is a steady-state capacity/working-set model; it does not model cold-start warming or access order. -`asap_types::resources` is the single definition site for `CacheProfile`, +`asap_types::workload::resources` is the single definition site for `CacheProfile`, `CacheEvidence`, and `CacheCapacityEvidence` (implemented in `resources/cache.rs`). These schemas describe cache assumptions, not additive CPU or byte consumption. The mapping module re-exports the same types for existing import paths, while diff --git a/docs/design_docs/proposals/planner-layering.md b/docs/design_docs/proposals/planner-layering.md index 5d0e98912..86afa3341 100644 --- a/docs/design_docs/proposals/planner-layering.md +++ b/docs/design_docs/proposals/planner-layering.md @@ -149,7 +149,7 @@ ASAPPlanner relies on the assumptions below. ### ASAPPlanner System Overview: Planning Stages -ASAPPlanner takes a [query workload](https://github.com/ProjectASAP/ASAPPlanner/blob/main/crates/types/src/workload.rs), a [data workload](https://github.com/ProjectASAP/ASAPPlanner/blob/main/crates/types/src/workload.rs#L531) and the deployment's +ASAPPlanner takes a [query workload](https://github.com/ProjectASAP/ASAPPlanner/blob/main/crates/types/src/workload/mod.rs), a [data workload](https://github.com/ProjectASAP/ASAPPlanner/blob/main/crates/types/src/workload/mod.rs#L534) and the deployment's inputs (TODO: define this data structure, issue [#525](https://github.com/ProjectASAP/ASAPPlanner/issues/525)), and returns one optimal physical plan. It decides what is computed, how it is computed, and which plan is best. The deployment only supplies data and query inputs and executes the plan: it provides its empirical cost model, empirical accuracy model and capabilities, but never optimize queries. @@ -848,7 +848,7 @@ To see examples in DAG Viewer, following the instructions [here](TODO: write an Each example's workload is shown as tables. Field names in code font are the fields of -[`workload.rs`](https://github.com/ProjectASAP/ASAPPlanner/blob/main/crates/types/src/workload.rs). +[`workload/mod.rs`](https://github.com/ProjectASAP/ASAPPlanner/blob/main/crates/types/src/workload/mod.rs). Each query reads the event-time window [`as_of` − `lookback`, `as_of`] (fields of `TimeSelection`). `as_of` is the window's end; `lookback` is its length. An `as_of` of "evaluation time" means `as_of: None`: the window ends whenever the diff --git a/docs/develop_docs/end-to-end-accuracy-guarantees.md b/docs/develop_docs/end-to-end-accuracy-guarantees.md index 94c69d988..9478b6896 100644 --- a/docs/develop_docs/end-to-end-accuracy-guarantees.md +++ b/docs/develop_docs/end-to-end-accuracy-guarantees.md @@ -40,7 +40,7 @@ The main implementation locations are: | Concern | Location | | --- | --- | -| Guarantee and error vocabulary | `asap_types::post_asap::guarantee` | +| Guarantee and error vocabulary | `asap_types::ir::properties::guarantee` | | Accuracy model and built-in propagation | `asap_aware_mapping::accuracy` | | Candidate construction and legality filtering | `asap_aware_mapping::replacement` | | Parameter sizing hooks | `asap_aware_mapping::cost_model` | diff --git a/docs/develop_docs/library-api.md b/docs/develop_docs/library-api.md index 7e8b2768d..db0e618f5 100644 --- a/docs/develop_docs/library-api.md +++ b/docs/develop_docs/library-api.md @@ -646,5 +646,5 @@ cargo doc -p asap-aware-mapping -p asap-types --no-deps - [Frontend PromQL](../../crates/frontend-promql/src/lib.rs), [SQL](../../crates/frontend-sql/src/lib.rs), [MetricsQL](../../crates/frontend-metricsql/src/lib.rs) - [Search, ranking and selection](../../crates/asap-aware-mapping/src/replacement.rs) - [Cost models](../../crates/asap-aware-mapping/src/cost_model.rs) -- [Workload types](../../crates/types/src/workload.rs) +- [Workload types](../../crates/types/src/workload/mod.rs) - [Planner-runtime contract](../design_docs/architecture/planner-runtime-contract.md) diff --git a/docs/develop_docs/offline-sketch-evidence.md b/docs/develop_docs/offline-sketch-evidence.md index 4a6d0c2ca..558af4f88 100644 --- a/docs/develop_docs/offline-sketch-evidence.md +++ b/docs/develop_docs/offline-sketch-evidence.md @@ -12,7 +12,7 @@ wire format. `crates/asap-aware-mapping/tests/data/offline-evidence-synthetic.js is an explicitly fabricated format fixture, never benchmark evidence. Runtime validation additionally checks cross-field constraints and matching context. -Resource values share the internal `asap_types::resources::PhysicalResources` container. Its CPU payload preserves units: `ModeledCpu { cpu_ops: f64 }` represents modeled operations, while `MeasuredCpu` contains optional measured `build_cpu_ns`, `update_cpu_ns`, `merge_cpu_ns`, `prepare_cpu_ns`, and `read_cpu_ns` diff --git a/docs/develop_docs/physical-handoff-costs.md b/docs/develop_docs/physical-handoff-costs.md index dcd95e747..e22a15d65 100644 --- a/docs/develop_docs/physical-handoff-costs.md +++ b/docs/develop_docs/physical-handoff-costs.md @@ -1,6 +1,6 @@ # Physical handoff byte estimates -`asap_types::resources` owns the canonical `PhysicalHandoffBytes` and +`asap_types::workload::resources` owns the canonical `PhysicalHandoffBytes` and `PhysicalHandoffKind` definitions in `resources/physical_handoff.rs`. The mapping crate re-exports those same types from `physical_handoff_cost` for import compatibility; all estimator and export consumers therefore use shared definitions, not copies. diff --git a/docs/develop_docs/pre-asap-ir.md b/docs/develop_docs/pre-asap-ir.md index 04f71b15a..7a557ee96 100644 --- a/docs/develop_docs/pre-asap-ir.md +++ b/docs/develop_docs/pre-asap-ir.md @@ -23,7 +23,7 @@ Only operations that are semantically relevant to answering the query and select ## The node -A plan is a DAG of `Rc` (`crates/types/src/ir/node.rs`). Nodes are immutable +A plan is a DAG of `Rc` (`crates/types/src/ir/operator/node.rs`). Nodes are immutable and shared through `Rc`: a structurally identical sub-DAG referenced from several parents is one node, and that pointer identity is what CSE, target discovery and plan assembly key on. @@ -47,7 +47,7 @@ pub struct OperatorNode { retain a more specific schema through `OperatorNode::with_schema`. - `guarantee` is `None` until accuracy assessment establishes one; `None` never means exact. - `timing` is `None` in every front-end DAG and every candidate. It is written by - `ir::timing::apply_materialization_timings` (see the Post-ASAP IR document); export rejects an + `ir::properties::timing::apply_materialization_timings` (see the Post-ASAP IR document); export rejects an untimed node. `OperatorNode::children()` returns the operator's inputs in field order followed by the @@ -59,7 +59,7 @@ derived one. ## Schema -One `Schema` type (`crates/types/src/pre_asap/schema.rs`) describes every edge, whether it +One `Schema` type (`crates/types/src/ir/schema/mod.rs`) describes every edge, whether it carries rows or summary state: ```rust @@ -88,7 +88,7 @@ across consumers when its row identity is provable. ## Scalar expressions -Value computation lives in `ScalarExpr` (`crates/types/src/ir/scalar.rs`), owned **by value** +Value computation lives in `ScalarExpr` (`crates/types/src/ir/scalar/mod.rs`), owned **by value** by an operator field: `Scan.predicates`, `Filter.pred`, `Join.pred`, `Project.cols[i].expr`, `Aggregate.having`, `Sort.keys[i].expr`, `SQLWindowFunc.args`/`order_by`, `PromqlRelabel.value`, `Values.rows`, and `QueryRoot::Scalar` and `PromqlVectorFromScalar`. A scalar expression never diff --git a/docs/develop_docs/storage-operation-costs.md b/docs/develop_docs/storage-operation-costs.md index 999b79103..af7ad604c 100644 --- a/docs/develop_docs/storage-operation-costs.md +++ b/docs/develop_docs/storage-operation-costs.md @@ -43,7 +43,7 @@ profile and coefficients before ranking. Scan read extents must add up to the scan's authoritative `source_read_bytes`; explicit additional storage actions can be bound to other physical nodes. -Their sole data type is `asap_types::resources::StorageResources`, defined in +Their sole data type is `asap_types::workload::resources::StorageResources`, defined in the shared resources module alongside CPU and byte dimensions. The mapping crate re-exports it at `asap_aware_mapping::storage_io::StorageResources` for source compatibility; the four integer JSON fields are unchanged. Pure term