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 da7562c1c..1afd31134 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) @@ -500,8 +503,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 ──────────────────────────────────────────────── @@ -523,7 +526,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( @@ -637,7 +640,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), @@ -681,7 +684,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), @@ -727,7 +730,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 a46005c63..2f8446c85 100644 --- a/crates/asap-aware-mapping/src/logical_candidates.rs +++ b/crates/asap-aware-mapping/src/logical_candidates.rs @@ -7,15 +7,16 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::rc::Rc; -use asap_types::ir::summary_coverage::{CoverageRegion, SummaryCoverage}; -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::properties::summary_coverage::{CoverageRegion, SummaryCoverage}; +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; @@ -275,7 +276,7 @@ fn realize( fn single_source( node: &Rc, -) -> Result { +) -> Result { let mut sources = Vec::new(); for node in OperatorNode::reachable(node) { if let Some(NonASAPOp::Scan { source, .. }) = node.non_asap() { @@ -332,7 +333,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 }) @@ -400,6 +401,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 d37c31c11..db502a48e 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,7 +334,7 @@ mod tests { use crate::test_support::lower_promql; use asap_types::ir::cse::share_common_sub_dags; use asap_types::ir::export::compile_physical_asap_dag as export_timed; - use asap_types::ir::timing::{ + use asap_types::ir::properties::timing::{ apply_materialization_timings, MaterializationAssignment, TimingMemo, }; @@ -475,7 +478,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 6355b8915..095ad422d 100644 --- a/crates/asap-aware-mapping/src/pass/mod.rs +++ b/crates/asap-aware-mapping/src/pass/mod.rs @@ -18,12 +18,12 @@ use std::collections::BTreeMap; use std::rc::Rc; use asap_types::ir::export::compile_physical_asap_workload; -use asap_types::ir::timing::{ +use asap_types::ir::properties::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::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 094adda17..21d618595 100644 --- a/crates/asap-aware-mapping/src/physical_candidates.rs +++ b/crates/asap-aware-mapping/src/physical_candidates.rs @@ -12,14 +12,14 @@ use std::collections::HashMap; use std::rc::Rc; use asap_types::ir::export::{compile_physical_asap_workload_with_node_ids, PhysicalASAPDAG}; +use asap_types::ir::operator::{AggIntent, Reduction}; +use asap_types::ir::properties::ExecutionDataStateError; +use asap_types::ir::scalar::column_resolution::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. @@ -156,8 +156,8 @@ mod tests { use crate::test_support::lower_promql; use asap_types::ir::export::PhysicalASAPOperatorPayload as Payload; use asap_types::ir::export::{NonASAPOpKind, PhysicalASAPNodeId}; + 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 fd0ce9a81..077fc8b39 100644 --- a/crates/asap-aware-mapping/src/plan_selection.rs +++ b/crates/asap-aware-mapping/src/plan_selection.rs @@ -17,11 +17,12 @@ use std::collections::{BTreeMap, HashMap}; use asap_types::ir::export::{ NonASAPOpKind, PhysicalASAPDAG, PhysicalASAPNodeId, PhysicalASAPOperatorPayload as Payload, }; -use asap_types::ir::{ASAPOp, Operator, OperatorNode}; -use asap_types::post_asap::{ +use asap_types::ir::operator::Reduction; +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 240d35746..01e973c65 100644 --- a/crates/asap-aware-mapping/src/replacement.rs +++ b/crates/asap-aware-mapping/src/replacement.rs @@ -151,8 +151,8 @@ //! targets are just two different entries in two different groups, //! 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 +//! 2. **Dedup by structural hash + `PartialEq`, reusing `ir::cse`'s own +//! 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,31 +343,34 @@ 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::summary_coverage::{CoverageRegion, SummaryCoverage}; -use asap_types::ir::timing::validate_maintained; +use asap_types::ir::operator::agg_intent::{agg_is_mergeable, AggIntent}; +use asap_types::ir::operator::operator_properties::{BinaryOpKind, JoinKind, Reduction}; +use asap_types::ir::properties::summary_coverage::{CoverageRegion, SummaryCoverage}; +use asap_types::ir::properties::timing::validate_maintained; +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::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}; @@ -1091,12 +1094,9 @@ pub fn default_size_params( /// [`posterior_aware_size_params`]. /// /// This is **not** derived from Chen et al.'s posterior-error-estimation -/// technique (issue #239, `asap_types::post_asap::query_time::error_estimation`) -/// — that technique computes a tighter bound *at query time* from a -/// sketch's real counter values, and this repo has no sketch runtime yet -/// for a real counter array to size against (see that module's docs, and -/// `asap_types::post_asap::query_time`'s module doc for why it's a -/// deliberately separate folder from this crate's own *plan-time* code). +/// technique (issue #239) — that technique computes a tighter bound *at +/// query time* from a sketch's real counter values, and this repo has no +/// sketch runtime yet for a real counter array to size against. /// This struct is this crate's own *plan-time* analogue of the same /// underlying intuition — an expected-case (skewed / non-adversarial) /// workload needs a smaller sketch than the adversarial worst case — @@ -1124,8 +1124,7 @@ pub struct ExpectedCaseSizing { /// **The tradeoff, spelled out:** [`default_size_params`]'s width guarantees /// `Pr[error > ε·|F|₁] < δ` for *any* input, including an adversarial one /// built to maximize collisions (§3.3 of the posterior-error-estimation -/// paper this issue is about — see -/// `asap_types::post_asap::query_time::error_estimation`'s module docs). +/// paper issue #239 is about). /// Shrinking /// width below that only keeps the same `(ε,δ)` guarantee if the real /// workload's collision load stays within `width_relaxation` of the @@ -1401,10 +1400,11 @@ 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::properties::timing::apply_materialization_timings( node, - &asap_types::ir::timing::MaterializationAssignment::all_ingestion_time(), - &mut asap_types::ir::timing::TimingMemo::new(), + &asap_types::ir::properties::timing::MaterializationAssignment::all_ingestion_time( + ), + &mut asap_types::ir::properties::timing::TimingMemo::new(), ) .ok() .and_then(|timed| asap_types::ir::export::compile_physical_asap_dag(&timed).ok()) @@ -2760,7 +2760,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()) } @@ -3169,7 +3169,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()) @@ -3351,7 +3351,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 @@ -3389,7 +3389,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)) @@ -3402,7 +3402,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 @@ -5155,7 +5157,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, })) @@ -6491,12 +6493,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, ), @@ -6900,12 +6902,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_intent::{ 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::operator_properties::{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; @@ -7124,7 +7126,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, }) @@ -7307,7 +7309,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::operator_properties::JoinKind::Inner, pred: equi_pred(0, 2), left, right, @@ -7938,7 +7940,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"]), ); @@ -8183,7 +8185,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:?}"), @@ -8513,8 +8515,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 @@ -9080,8 +9082,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 { @@ -9230,8 +9232,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 { @@ -9264,8 +9266,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 { @@ -9328,8 +9330,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 { @@ -9567,8 +9569,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 = @@ -9671,8 +9673,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))), @@ -10182,8 +10184,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)), @@ -10203,8 +10205,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)], @@ -10231,7 +10233,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 @@ -10681,7 +10683,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 @@ -11296,7 +11298,7 @@ mod tests { let right = crate::test_support::scan("n", left.schema.clone()); assert!(whole_source_coverage(&left).is_some()); let join = OperatorNode::new_shared(asap_types::ir::Operator::NonASAP(NonASAPOp::Join { - kind: asap_types::ir::operator_properties::JoinKind::Inner, + kind: asap_types::ir::operator::operator_properties::JoinKind::Inner, pred: equi_pred(0, 2), left, right, 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 f410f915f..368b5234b 100644 --- a/crates/asap-aware-mapping/src/test_support.rs +++ b/crates/asap-aware-mapping/src/test_support.rs @@ -50,13 +50,13 @@ pub(crate) fn lower_promql(query: &str, accuracy: AccuracyTarget) -> Rc, ) -> Result< asap_types::ir::export::PhysicalASAPDAG, - asap_types::post_asap::execution_data_state::ExecutionDataStateError, + asap_types::ir::properties::execution::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 fa4c7d28d..af93507ac 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 { @@ -205,7 +203,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 afc674418..286956baa 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 { @@ -445,7 +445,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); @@ -475,7 +475,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]); @@ -484,7 +484,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 2bd57bf21..6197df233 100644 --- a/crates/asap-physical-operators/src/physical_planner/mod.rs +++ b/crates/asap-physical-operators/src/physical_planner/mod.rs @@ -12,13 +12,10 @@ use planner_types::ir::export::{ NonASAPOpKind, PhysicalASAPDAG, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload as Payload, WireScalarExpr, }; +use planner_types::ir::operator::{AggIntent, GroupKeys, Reduction as PlannerReduction}; +use planner_types::ir::scalar::{ColumnRef, CompareOpKind}; +use planner_types::ir::schema::{DataType, 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}, @@ -291,7 +288,7 @@ fn compile_internal( continue; } if let Payload::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", @@ -324,7 +321,7 @@ fn compile_internal( continue; } if let Payload::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 { @@ -453,7 +450,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")); @@ -631,7 +628,8 @@ fn bind_operation(node: &PhysicalASAPDAGNode, inputs: &[SchemaRef]) -> Result Result { let columns = schema .fields @@ -639,7 +637,7 @@ fn bind_operation(node: &PhysicalASAPDAGNode, inputs: &[SchemaRef]) -> Result>(); @@ -681,7 +679,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, @@ -866,10 +864,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 2771465a9..fc9c9c14c 100644 --- a/crates/asap-physical-operators/src/physical_planner/precompute.rs +++ b/crates/asap-physical-operators/src/physical_planner/precompute.rs @@ -1,18 +1,16 @@ //! 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::post_asap::FieldDataType as SummaryFamilyType; -use planner_types::{ - post_asap::{ExecutionTiming, GroupingStrategy, Schema}, - pre_asap::DataType, -}; +use planner_types::ir::properties::ExecutionTiming; +use planner_types::ir::schema::FieldDataType as SummaryFamilyType; +use planner_types::ir::schema::{DataType, GroupingStrategy, Schema}; /// 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), @@ -22,13 +20,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, @@ -88,7 +86,7 @@ pub fn boundary_schema(node: &PhysicalASAPDAGNode) -> Result { &node.payload, Payload::Relational { operator: NonASAPOpKind::Scan { - source: planner_types::pre_asap::Source::TimeSeries { .. }, + source: planner_types::ir::operator::Source::TimeSeries { .. }, .. } | NonASAPOpKind::TimeRange { .. } } @@ -262,7 +260,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 +351,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, _ => { @@ -415,10 +413,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) { @@ -431,8 +429,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 } ) { @@ -441,10 +439,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")); @@ -514,7 +512,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, @@ -626,7 +624,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 f85d187d5..a2b24a4bb 100644 --- a/crates/asap-physical-operators/src/physical_planner/promql_rows.rs +++ b/crates/asap-physical-operators/src/physical_planner/promql_rows.rs @@ -4,12 +4,12 @@ use super::*; use planner_types::ir::export::{ compile_physical_asap_dag, compile_physical_asap_dag_with_node_ids, }; -use planner_types::post_asap::FieldDataType as SummaryFamilyType; -use planner_types::pre_asap::DataType; +use planner_types::ir::schema::DataType; +use planner_types::ir::schema::FieldDataType as SummaryFamilyType; 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. @@ -85,9 +85,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, @@ -101,7 +100,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::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 @@ -190,12 +189,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::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::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 10fc036e7..f1df7ce8e 100644 --- a/crates/asap-physical-operators/tests/current_series_heap.rs +++ b/crates/asap-physical-operators/tests/current_series_heap.rs @@ -12,11 +12,11 @@ use asap_physical_operators::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::export::PhysicalASAPOperatorPayload; -use planner_types::{post_asap::*, pre_asap::DataType}; +use planner_types::ir::schema::{DataType, *}; 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 +171,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 0eecf2f5a..0395aaa06 100644 --- a/crates/asap-physical-operators/tests/deployment_computation.rs +++ b/crates/asap-physical-operators/tests/deployment_computation.rs @@ -10,7 +10,7 @@ use asap_physical_operators::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::export::{PhysicalASAPDAG, PhysicalASAPOperatorPayload}; -use planner_types::{post_asap::*, types::AccuracyTarget, workload::*}; +use planner_types::{ir::schema::*, types::AccuracyTarget, workload::*}; use std::{collections::BTreeMap, rc::Rc, sync::Arc}; fn lower(query: &str) -> Rc { @@ -84,7 +84,7 @@ fn raw_inputs(dag: &PhysicalASAPDAG) -> Vec<(u64, Arc, String)> { if let PhysicalASAPOperatorPayload::Relational { operator: planner_types::ir::export::NonASAPOpKind::Scan { - source: planner_types::pre_asap::Source::TimeSeries { metric }, + source: planner_types::ir::operator::Source::TimeSeries { metric }, .. }, } = &n.payload @@ -331,7 +331,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 { @@ -376,7 +376,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.)) @@ -538,7 +539,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 { @@ -550,7 +551,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, @@ -564,7 +565,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 93a8b7a86..511cd44cf 100644 --- a/crates/asap-physical-operators/tests/physical_dag.rs +++ b/crates/asap-physical-operators/tests/physical_dag.rs @@ -13,15 +13,12 @@ use planner_types::ir::export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::schema::{DataType, ExactKind, ExactParams, Field, FieldDataType}; use planner_types::ir::BinaryOperator; 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 @@ -306,7 +303,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()); @@ -316,7 +313,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( @@ -408,7 +405,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(), @@ -431,7 +428,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 { @@ -493,10 +490,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 { @@ -514,7 +509,7 @@ fn bind_post_asap_before_execution() { PhysicalASAPOperatorPayload::Relational { operator: ValueOperation::Values { rows: vec![vec![planner_types::ir::export::WireScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Float64(1.), + planner_types::ir::scalar::ScalarValue::Float64(1.), )]], schema: (*schema).clone(), }, @@ -613,7 +608,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, @@ -653,7 +648,7 @@ fn source_batches_must_match_the_bound_schema() { payload: PhysicalASAPOperatorPayload::Relational { operator: ValueOperation::Values { rows: vec![vec![planner_types::ir::export::WireScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Float64(1.), + planner_types::ir::scalar::ScalarValue::Float64(1.), )]], schema: (*expected).clone(), }, @@ -722,10 +717,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), @@ -761,7 +756,7 @@ fn planner_semijoin_sort_limit_contract_at_both_phases() { PhysicalASAPOperatorPayload::Relational { operator: ValueOperation::Values { rows: vec![vec![planner_types::ir::export::WireScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Float64(0.), + planner_types::ir::scalar::ScalarValue::Float64(0.), )]], schema: (*rows_schema).clone(), }, @@ -773,7 +768,7 @@ fn planner_semijoin_sort_limit_contract_at_both_phases() { PhysicalASAPOperatorPayload::Relational { operator: ValueOperation::Values { rows: vec![vec![planner_types::ir::export::WireScalarExpr::Literal( - planner_types::pre_asap::ScalarValue::Float64(0.), + planner_types::ir::scalar::ScalarValue::Float64(0.), )]], schema: (*keys_schema).clone(), }, @@ -897,7 +892,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", @@ -973,8 +968,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 { @@ -1055,7 +1051,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), @@ -1087,7 +1083,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], @@ -1181,15 +1177,14 @@ fn grouped_temporal_schema_compiles_and_executes_topk() { compile_node, CompiledPhysicalDAG, InputContract, Source, }; use planner_types::ir::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, @@ -1292,10 +1287,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] { @@ -1407,10 +1402,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 498e8b3f0..d9a7d4543 100644 --- a/crates/asap-physical-operators/tests/physical_semantics.rs +++ b/crates/asap-physical-operators/tests/physical_semantics.rs @@ -11,16 +11,15 @@ use asap_physical_operators::{ use futures::{executor::block_on, StreamExt}; use planner_types::ir::export::NonASAPOpKind as ValueOperation; use planner_types::ir::export::{PhysicalASAPDAGNode, PhysicalASAPOperatorPayload}; +use planner_types::ir::operator::JoinKind; +use planner_types::ir::scalar::CompareOpKind; +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::{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 +347,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), @@ -556,7 +554,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( @@ -605,7 +603,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(), @@ -674,7 +672,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 d1ea3dbf1..2fa0ca770 100644 --- a/crates/asap-physical-operators/tests/precompute_candidates.rs +++ b/crates/asap-physical-operators/tests/precompute_candidates.rs @@ -15,7 +15,9 @@ use asap_physical_operators::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::export::{PhysicalASAPDAG, PhysicalASAPOperatorPayload}; -use planner_types::{post_asap::*, pre_asap::DataType, types::AccuracyTarget, workload::*}; +use planner_types::ir::schema::{DataType, *}; +use planner_types::types::AccuracyTarget; +use planner_types::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 002cf63c5..59ffaa5d3 100644 --- a/crates/asap-physical-operators/tests/precompute_population.rs +++ b/crates/asap-physical-operators/tests/precompute_population.rs @@ -12,18 +12,18 @@ use planner_types::ir::export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::operator::{BinaryOpKind, GroupKeys, Reduction}; +use planner_types::ir::properties::*; +use planner_types::ir::scalar::{ArithmeticOpKind, ColumnRef}; +use planner_types::ir::schema::{DataType, *}; 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 { @@ -45,7 +45,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, }); @@ -230,7 +230,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 { @@ -360,9 +360,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 793f82a43..ac93414b9 100644 --- a/crates/asap-physical-operators/tests/promql_binary.rs +++ b/crates/asap-physical-operators/tests/promql_binary.rs @@ -10,15 +10,15 @@ use planner_types::ir::export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::operator::BinaryOpKind; +use planner_types::ir::properties::ExecutionDataState; +use planner_types::ir::scalar::ArithmeticOpKind; +use planner_types::ir::schema::{DataType, Field, FieldDataType}; 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 +164,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 +301,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 +332,17 @@ 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::scalar::CompareOpKind; + use planner_types::ir::schema::PROMQL_SERIES_IDENTITY; + use planner_types::{ir::properties::*, 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 c8aef869c..65272844c 100644 --- a/crates/asap-physical-operators/tests/promql_fallback.rs +++ b/crates/asap-physical-operators/tests/promql_fallback.rs @@ -11,9 +11,9 @@ use asap_physical_operators::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::export::PhysicalASAPDAG; -use planner_types::{ - post_asap::execution_data_state::lift_plain, types::AccuracyTarget, workload::*, -}; +use planner_types::physical::execution_data_state::lift_plain; +use planner_types::types::AccuracyTarget; +use planner_types::workload::*; use std::{collections::BTreeMap, rc::Rc}; /// Bare selectors look back one ingestion interval: 60s. @@ -86,7 +86,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 44cdb6a6b..4bacafec0 100644 --- a/crates/asap-physical-operators/tests/raw_scan.rs +++ b/crates/asap-physical-operators/tests/raw_scan.rs @@ -11,11 +11,10 @@ use planner_types::ir::export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; +use planner_types::ir::operator::{GroupKeys, Source}; +use planner_types::ir::properties::*; +use planner_types::ir::schema::{DataType, Field, *}; use planner_types::ir::Predicate; -use planner_types::{ - post_asap::*, - pre_asap::{DataType, Field, GroupKeys, Source}, -}; use std::{ collections::BTreeMap, sync::{ @@ -25,12 +24,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 { @@ -325,7 +325,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 f48b9c210..f5e71e2b0 100644 --- a/crates/asap-physical-operators/tests/summary_projection.rs +++ b/crates/asap-physical-operators/tests/summary_projection.rs @@ -13,10 +13,9 @@ use planner_types::ir::export::{ EdgeRole, GroupingEdgeCompatibility, PhysicalASAPDAG, PhysicalASAPDAGEdge, PhysicalASAPDAGNode, PhysicalASAPOperatorPayload, WindowEdgeCompatibility, }; -use planner_types::{ - post_asap::*, - pre_asap::{ColumnRef, DataType}, -}; +use planner_types::ir::properties::*; +use planner_types::ir::scalar::ColumnRef; +use planner_types::ir::schema::{DataType, *}; use std::{collections::BTreeMap, sync::Arc}; // A Post-ASAP projection may reorder/rename summary columns; recovery must retain @@ -24,7 +23,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![ @@ -43,7 +42,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 c14d16979..31ab8ed4b 100644 --- a/crates/asap-physical-operators/tests/weighted_topk_binding.rs +++ b/crates/asap-physical-operators/tests/weighted_topk_binding.rs @@ -16,7 +16,9 @@ use asap_physical_operators::dag::{ use common::compile_physical_asap_dag; use futures::{executor::block_on, StreamExt}; use planner_types::ir::export::{PhysicalASAPDAG, PhysicalASAPOperatorPayload}; -use planner_types::{post_asap::*, pre_asap::DataType, types::AccuracyTarget}; +use planner_types::ir::properties::*; +use planner_types::ir::schema::{DataType, *}; +use planner_types::types::AccuracyTarget; use std::{collections::BTreeMap, rc::Rc, sync::Arc}; struct Evidence; impl AccuracyEvidenceProvider for Evidence { @@ -245,9 +247,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, }, @@ -292,13 +294,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 4565657f9..7599ce14f 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::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 84cbad1c5..d284e4806 100644 --- a/crates/devtools/src/bin/stage_pipeline.rs +++ b/crates/devtools/src/bin/stage_pipeline.rs @@ -29,9 +29,9 @@ use asap_aware_mapping::{PlanningModels, Realization}; use asap_types::ir::export::{ compile_logical_asap_workload, LogicalASAPDAG, LogicalASAPDAGDocument, }; +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 fd43c9954..8e21e732e 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::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 c095eae2d..1123c6c35 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 3faf9c306..33cfb52c4 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, }) } @@ -317,7 +317,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 285dfe942..f156c480f 100644 --- a/crates/frontend-sql/tests/maintained_population.rs +++ b/crates/frontend-sql/tests/maintained_population.rs @@ -1,16 +1,15 @@ //! 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::{ - apply_materialization_timings, cse::share_common_sub_dags, - 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 asap_types::ir::cse::share_common_sub_dags; +use asap_types::ir::export::compile_physical_asap_dag; +use asap_types::ir::operator::maintained_population::{MaintainedPopulation, PopulationInput}; +use asap_types::ir::schema::{DataType, Field, Schema}; +use asap_types::ir::{ + apply_materialization_timings, ASAPOp, MaterializationAssignment, NonASAPOp, Operator, + OperatorNode, TimingMemo, }; +use asap_types::types::AccuracyTarget; use std::rc::Rc; async fn aggregate(q: &str) -> 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 560da2b48..71a107935 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, 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 8e88d0742..2347db63c 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 af9598cd3..5435730f6 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 f8e069a3d..25679a94b 100644 --- a/crates/integration-tests/tests/exact_composition.rs +++ b/crates/integration-tests/tests/exact_composition.rs @@ -28,14 +28,13 @@ 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::export::{NonASAPOpKind, PhysicalASAPOperatorPayload}; -use asap_types::ir::operator_properties::{Reduction, Source}; -use asap_types::ir::timing::data_state; +use asap_types::ir::operator::agg_intent::{default_quantile, AggIntent}; +use asap_types::ir::operator::operator_properties::{Reduction, Source}; +use asap_types::ir::properties::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 3c4c028d6..3f469619d 100644 --- a/crates/integration-tests/tests/operator_design_examples.rs +++ b/crates/integration-tests/tests/operator_design_examples.rs @@ -1,11 +1,13 @@ //! #511 examples: source text → unified dag → summary rewrite → flat export. use asap_frontend_sql::{lower_sql, SqlCatalog}; -use asap_types::ir::summary_coverage::{CoverageRegion, SummaryCoverage}; -use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, ScalarExpr}; -use asap_types::post_asap::{ +use asap_types::ir::operator::AggIntent; +use asap_types::ir::properties::summary_coverage::{CoverageRegion, SummaryCoverage}; +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; @@ -88,7 +90,7 @@ async fn sql_sum_projection_before_and_after_summary_rewrite() { .unwrap() // Whole-source coverage, as the planner declares it today (#570). .with_coverage(SummaryCoverage { - source: asap_types::pre_asap::Source::Table { + source: asap_types::ir::operator::Source::Table { table_ref: "requests".into(), }, regions: vec![CoverageRegion { 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 e497caa77..49d1671c0 100644 --- a/crates/integration-tests/tests/planner_layering_example1.rs +++ b/crates/integration-tests/tests/planner_layering_example1.rs @@ -15,8 +15,8 @@ use std::collections::{BTreeMap, BTreeSet, HashSet}; use asap_aware_mapping::PlanningModels; use asap_types::ir::export::{LogicalASAPDAG, LogicalASAPNodeId, LogicalASAPOperatorPayload}; -use asap_types::post_asap::sketch::{GroupingStrategy, HydraKind, SketchAlgorithm}; -use asap_types::pre_asap::schema::FieldDataType; +use asap_types::ir::schema::state_type::{GroupingStrategy, HydraKind, SketchAlgorithm}; +use asap_types::ir::schema::FieldDataType; use asap_types::types::AccuracyTarget; use asap_types::workload::{ AccuracyRequirement, DataArrival, DataDistribution, DataWorkload, DurationMs, Evidence, @@ -260,7 +260,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 f0a270b0d..1e2328e38 100644 --- a/crates/integration-tests/tests/precompute_raw_samples.rs +++ b/crates/integration-tests/tests/precompute_raw_samples.rs @@ -21,11 +21,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}; @@ -319,7 +320,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; @@ -511,10 +512,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) }; @@ -595,9 +594,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 24c4209ec..bae63fef5 100644 --- a/crates/integration-tests/tests/promql_to_post_asap.rs +++ b/crates/integration-tests/tests/promql_to_post_asap.rs @@ -23,15 +23,15 @@ use asap_integration_tests::post_asap::{ maintained, maintained_post_asap_dag, post_asap_dag, timed, }; use asap_types::ir::export::{NonASAPOpKind, PhysicalASAPOperatorPayload}; -use asap_types::ir::operator_properties::Reduction; -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::operator::operator_properties::Reduction; +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!( @@ -300,7 +300,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::SummaryAgg { input, .. } = &node.payload else { unreachable!() @@ -480,8 +480,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(); @@ -493,8 +493,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))); } } @@ -727,7 +727,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() @@ -1039,7 +1039,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 }] )); @@ -1082,7 +1082,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(), @@ -1107,7 +1107,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. @@ -1256,7 +1256,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 3bd253748..722d375b6 100644 --- a/crates/integration-tests/tests/sql_to_physical.rs +++ b/crates/integration-tests/tests/sql_to_physical.rs @@ -9,11 +9,8 @@ use asap_physical_operators::{ values::{Batch, Value}, }; use asap_types::ir::export::PhysicalASAPOperatorPayload; -use asap_types::{ - post_asap::FieldDataType, - pre_asap::{DataType, Field, Schema}, - types::AccuracyTarget, -}; +use asap_types::ir::schema::{DataType, Field, FieldDataType, 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 673d939ec..062015900 100644 --- a/crates/integration-tests/tests/sql_to_post_asap.rs +++ b/crates/integration-tests/tests/sql_to_post_asap.rs @@ -30,14 +30,14 @@ use asap_types::ir::export::{ EdgeRole, NonASAPOpKind, PhysicalASAPNodeId, PhysicalASAPOperatorPayload, WirePredicate, WireScalarExpr, }; -use asap_types::ir::operator_properties::Reduction; -use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode, Predicate, ScalarExpr}; -use asap_types::post_asap::{ +use asap_types::ir::operator::operator_properties::Reduction; +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; @@ -327,7 +327,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, .. } )); @@ -343,12 +343,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/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 d9a0034a4..daf1d45e1 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). @@ -405,12 +405,12 @@ fn find_scalar_subquery(expr: &ScalarExpr) -> Option<&Rc> { #[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 eb6fc4bf7..15715b55b 100644 --- a/crates/types/src/ir/cse.rs +++ b/crates/types/src/ir/cse.rs @@ -55,9 +55,9 @@ use std::collections::HashMap; use std::hash::{Hash, Hasher}; use std::rc::Rc; -use super::node::{Operator, OperatorNode}; -use super::non_asap::NonASAPOp; -use crate::pre_asap::schema::Schema; +use crate::ir::operator::node::{Operator, OperatorNode}; +use crate::ir::operator::non_asap::NonASAPOp; +use crate::ir::schema::Schema; /// [`structural_hash`]'s memoization cache: an already-hashed node's `Rc` /// pointer to its hash. A fresh cache is always correct; what matters is @@ -299,17 +299,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::BinaryOperator; - use crate::ir::ScalarExpr; - use crate::post_asap::guarantee::ResultGuarantee; - use crate::post_asap::sketch::{ + use crate::ir::operator::agg_intent::AggIntent; + use crate::ir::operator::asap::ASAPOp; + use crate::ir::operator::operator_properties::{BinaryOpKind, GroupKeys, Reduction, Source}; + use crate::ir::properties::guarantee::ResultGuarantee; + use crate::ir::scalar::{ColumnRef, CompareOpKind}; + use crate::ir::schema::state_type::{ 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::schema::{DataType, Field, FieldDataType, Schema}; + use crate::ir::BinaryOperator; + use crate::ir::ScalarExpr; use crate::types::AccuracyTarget; @@ -554,7 +554,7 @@ mod tests { #[test] fn evaluations_share_their_producer_but_not_each_other() { - use crate::post_asap::sketch::SketchStatistic; + use crate::ir::schema::state_type::SketchStatistic; let evaluation = |q: f64| { Rc::new(OperatorNode::with_schema( Operator::ASAP(ASAPOp::SummaryEstimate { diff --git a/crates/types/src/ir/export.rs b/crates/types/src/ir/export.rs index 9fa6496de..b297586ac 100644 --- a/crates/types/src/ir/export.rs +++ b/crates/types/src/ir/export.rs @@ -9,16 +9,18 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; use thiserror::Error; -pub use super::physical_export::*; -pub use super::wire::NonASAPOpKind; -use super::wire::{grouping_compatibility, input_edges, payload_of}; -pub use super::wire::{ +pub use crate::ir::physical_export::*; +use crate::ir::properties::guarantee::ResultGuarantee; +use crate::ir::schema::{FieldDataType, Schema}; +pub use crate::ir::wire::NonASAPOpKind; +use crate::ir::wire::{grouping_compatibility, input_edges, payload_of}; +pub use crate::ir::wire::{ EdgeRole, GroupingEdgeCompatibility, LogicalASAPNodeId, LogicalASAPOperatorPayload, WirePredicate, WireProjectItem, WireScalarExpr, WireSortKey, }; -use super::{ASAPOp, Operator, OperatorNode, OperatorResultKind, QueryRoot, SchemaDerivationError}; -use crate::post_asap::guarantee::ResultGuarantee; -use crate::pre_asap::{FieldDataType, Schema}; +use crate::ir::{ + ASAPOp, Operator, OperatorNode, OperatorResultKind, QueryRoot, SchemaDerivationError, +}; /// Independent envelope version: this replaces the older phase-assigned format. pub const LOGICAL_ASAP_DAG_WIRE_VERSION: u32 = 1; @@ -32,7 +34,7 @@ pub struct LogicalASAPDAGNode { pub output_schema: Schema, pub guarantee: Option, #[serde(default)] - pub coverage: Option, + pub coverage: Option, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -186,7 +188,10 @@ impl LogicalASAPDAG { .ok_or(LogicalASAPDAGValidationError::InvalidCoverage(node.id)) }) .collect::, _>>()?; - let merged = super::summary_coverage::SummaryCoverage::merge_disjoint(&coverage) + let merged = + crate::ir::properties::summary_coverage::SummaryCoverage::merge_disjoint( + &coverage, + ) .map_err(|_| LogicalASAPDAGValidationError::InvalidCoverage(node.id))?; if node.coverage.as_ref() != Some(&merged) { return Err(LogicalASAPDAGValidationError::InvalidCoverage(node.id)); diff --git a/crates/types/src/ir/mod.rs b/crates/types/src/ir/mod.rs index 01d1da021..fb5e97847 100644 --- a/crates/types/src/ir/mod.rs +++ b/crates/types/src/ir/mod.rs @@ -1,32 +1,33 @@ //! 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. +//! - [`export`], [`physical_export`], [`cse`], [`canonicalize`] — DAG passes and +//! wire 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 export; /// Physical ASAP DAG transport: the logical payloads 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, }; -/// Semantic observation coverage, separate from field layout and physical timing. -pub mod summary_coverage; mod wire; pub mod schema_support; 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 92% rename from crates/types/src/ir/asap.rs rename to crates/types/src/ir/operator/asap.rs index b1c2297c1..23a7fb9b7 100644 --- a/crates/types/src/ir/asap.rs +++ b/crates/types/src/ir/operator/asap.rs @@ -5,13 +5,13 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; -use super::node::{OperatorNode, OperatorResultKind}; -use super::summary_coverage::{CoverageError, SummaryCoverage}; -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::operator_properties::Reduction; +use crate::ir::properties::summary_coverage::{CoverageError, SummaryCoverage}; +use crate::ir::schema::state_type::{GroupingStrategy, SketchStatistic, SummaryUpdate}; +use crate::ir::schema::{ColumnId, DataType, Field, FieldDataType, Schema}; 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 = @@ -30,7 +30,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. @@ -116,7 +116,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, @@ -235,15 +235,15 @@ impl ASAPOp { reduction, .. } => { - let mut schema = crate::ir::aggregate_schema::aggregate_output_schema( + let mut schema = crate::ir::schema::aggregate_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()))?, @@ -293,11 +293,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, ) @@ -320,7 +320,7 @@ impl ASAPOp { }; measure .map(|measure| { - super::NonASAPOp::Aggregate { + crate::ir::NonASAPOp::Aggregate { child: Rc::clone(source), reduction: reduction.clone(), measures: vec![measure], @@ -359,8 +359,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, @@ -413,7 +413,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], @@ -511,7 +511,7 @@ impl ASAPOp { query, } => { needs_state(summary_input, "SummaryEstimate")?; - use crate::post_asap::sketch::SketchCategory as C; + use crate::ir::schema::state_type::SketchCategory as C; let states: Vec<_> = summary_input .schema .fields @@ -583,13 +583,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()) })?; } @@ -629,8 +629,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::state_type::ExactKind; match kind { ExactKind::Count => DataType::Int64, _ => DataType::Float64, @@ -641,11 +641,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 94% rename from crates/types/src/ir/node.rs rename to crates/types/src/ir/operator/node.rs index 15431962f..d368d4a37 100644 --- a/crates/types/src/ir/node.rs +++ b/crates/types/src/ir/operator/node.rs @@ -8,15 +8,15 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; -use super::asap::ASAPOp; -use super::non_asap::NonASAPOp; -use super::operator_properties::Reduction; -use super::summary_coverage::{CoverageError, SummaryCoverage}; +use crate::ir::operator::asap::ASAPOp; +use crate::ir::operator::non_asap::NonASAPOp; +use crate::ir::operator::operator_properties::Reduction; +use crate::ir::properties::execution::ExecutionTiming; +use crate::ir::properties::guarantee::ResultGuarantee; +use crate::ir::properties::summary_coverage::{CoverageError, SummaryCoverage}; +use crate::ir::schema::Schema; +use crate::ir::schema::SummaryUpdate; use crate::ir::SchemaDerivationError; -use crate::post_asap::execution_data_state::ExecutionTiming; -use crate::post_asap::guarantee::ResultGuarantee; -use crate::post_asap::SummaryUpdate; -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. @@ -293,9 +293,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( @@ -315,10 +315,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 0daf3a0ce..3b71c3bfe 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)] @@ -761,8 +761,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( @@ -1087,11 +1087,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 cc38ddf7c..3e8caa36a 100644 --- a/crates/types/src/ir/physical_export.rs +++ b/crates/types/src/ir/physical_export.rs @@ -2,7 +2,7 @@ //! //! Same operator payloads as the logical export, 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 +//! ([`crate::ir::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,16 +11,16 @@ use std::rc::Rc; use serde::{Deserialize, Serialize}; use thiserror::Error; -use super::asap::ASAPOp; -use super::node::{Operator, OperatorNode}; -use super::timing::data_state; -use super::wire::{grouping_compatibility, input_edges, payload_of}; -use super::wire::{EdgeRole, GroupingEdgeCompatibility, LogicalASAPOperatorPayload}; -use crate::post_asap::execution_data_state::{ +use crate::ir::operator::asap::ASAPOp; +use crate::ir::operator::node::{Operator, OperatorNode}; +use crate::ir::properties::execution::{ ExecutionDataState, ExecutionDataStateError, ExecutionTiming, }; -use crate::post_asap::guarantee::ResultGuarantee; -use crate::pre_asap::schema::{FieldDataType, Schema}; +use crate::ir::properties::guarantee::ResultGuarantee; +use crate::ir::properties::timing::data_state; +use crate::ir::schema::{FieldDataType, Schema}; +use crate::ir::wire::{grouping_compatibility, input_edges, payload_of}; +use crate::ir::wire::{EdgeRole, GroupingEdgeCompatibility, LogicalASAPOperatorPayload}; pub const PHYSICAL_ASAP_DAG_WIRE_VERSION: u32 = 8; @@ -37,7 +37,7 @@ pub enum WindowEdgeCompatibility { } /// Node ids are shared with the logical export, since payloads embed them. -pub type PhysicalASAPNodeId = super::wire::LogicalASAPNodeId; +pub type PhysicalASAPNodeId = crate::ir::wire::LogicalASAPNodeId; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] @@ -50,7 +50,7 @@ pub struct PhysicalASAPDAGNode { pub output_schema: Schema, pub guarantee: Option, #[serde(default)] - pub coverage: Option, + pub coverage: Option, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -315,7 +315,7 @@ impl PhysicalASAPNodeIdentityMap { self.nodes_by_id .iter() .position(|candidate| Rc::ptr_eq(candidate, node)) - .map(|id| super::wire::LogicalASAPNodeId(id as u32)) + .map(|id| crate::ir::wire::LogicalASAPNodeId(id as u32)) } pub fn operator_node(&self, id: PhysicalASAPNodeId) -> Option<&Rc> { @@ -336,7 +336,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 [`crate::ir::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, @@ -413,7 +413,7 @@ impl Exporter { } } } - let id = super::wire::LogicalASAPNodeId(self.nodes.len() as u32); + let id = crate::ir::wire::LogicalASAPNodeId(self.nodes.len() as u32); let payload = { let ids = &self.ids; let mut id_of = |n: &Rc| ids[&Rc::as_ptr(n)]; 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 99% rename from crates/types/src/ir/summary_coverage.rs rename to crates/types/src/ir/properties/summary_coverage.rs index 747f87f76..19ae10eb8 100644 --- a/crates/types/src/ir/summary_coverage.rs +++ b/crates/types/src/ir/properties/summary_coverage.rs @@ -1,7 +1,7 @@ //! Joint time/population coverage for summary composition, independent of schema. //! Equality predicates are a deliberately narrow proof vocabulary. Unsupported //! predicates cannot be declared disjoint merely by giving them different names. -use crate::pre_asap::Source; +use crate::ir::operator::Source; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::ops::Range; 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 eb6f5a9d5..3d2154ee8 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 @@ -505,7 +505,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) @@ -520,8 +520,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))) }) }; @@ -539,14 +538,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) @@ -656,13 +655,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), @@ -679,15 +678,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 682c59465..56c469cb3 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 c1a0b90a1..6877b3456 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 @@ -489,7 +495,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 @@ -559,7 +566,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) @@ -603,7 +610,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")) @@ -611,7 +618,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), @@ -747,9 +754,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/ir/wire.rs b/crates/types/src/ir/wire.rs index a36243c3c..eb6dd6423 100644 --- a/crates/types/src/ir/wire.rs +++ b/crates/types/src/ir/wire.rs @@ -4,19 +4,19 @@ use std::time::Duration; use serde::{Deserialize, Serialize}; -use super::asap::ASAPOp; -use super::node::{Operator, OperatorNode}; -use super::non_asap::{BinaryOperator, NonASAPOp, TimeRangeKind}; -use super::scalar::{ExprSemantics, Predicate, ProjectItem, ScalarExpr, SortKey}; -use crate::ir::operator_properties::{ +use crate::ir::operator::agg_intent::AggIntent; +use crate::ir::operator::asap::ASAPOp; +use crate::ir::operator::maintained_population::{MaintainedPopulation, PopulationStatistic}; +use crate::ir::operator::node::{Operator, OperatorNode}; +use crate::ir::operator::non_asap::{BinaryOperator, NonASAPOp, TimeRangeKind}; +use crate::ir::operator::operator_properties::{ ConcatDiscriminatorKey, GroupKeys, InfoMatcher, JoinKind, Reduction, RelationalSetOpKind, SampleKind, Source, TimeShift, WindowFrame, WindowFuncKind, }; -use crate::post_asap::maintained_population::{MaintainedPopulation, PopulationStatistic}; -use crate::post_asap::sketch::{GroupingStrategy, SketchStatistic, SummaryUpdate}; -use crate::pre_asap::agg_intent::AggIntent; -use crate::pre_asap::expr_ir::{ArithmeticOpKind, CompareOpKind, ScalarValue}; -use crate::pre_asap::schema::{ColumnId, DataType, FieldDataType, Schema}; +use crate::ir::scalar::{ArithmeticOpKind, CompareOpKind, ScalarValue}; +use crate::ir::scalar::{ExprSemantics, Predicate, ProjectItem, ScalarExpr, SortKey}; +use crate::ir::schema::state_type::{GroupingStrategy, SketchStatistic, SummaryUpdate}; +use crate::ir::schema::{ColumnId, DataType, FieldDataType, Schema}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum EdgeRole { diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index 9252ac806..3f666d8a6 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -1,26 +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) and the wire export ([`ir::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/logical_export.rs b/crates/types/tests/logical_export.rs index 95c812cec..f490733a3 100644 --- a/crates/types/tests/logical_export.rs +++ b/crates/types/tests/logical_export.rs @@ -1,8 +1,6 @@ //! Logical transport must accept plans with no execution timing assigned, before materialization. -use asap_types::{ - ir::{NonASAPOp, Operator, OperatorNode}, - pre_asap::Schema, -}; +use asap_types::ir::schema::Schema; +use asap_types::ir::{NonASAPOp, Operator, OperatorNode}; #[test] fn logical_export_accepts_unassigned_timing() { @@ -15,16 +13,18 @@ fn logical_export_accepts_unassigned_timing() { assert!(asap_types::ir::export::compile_logical_asap_dag(&root).is_ok()); } -use asap_types::{ - ir::export::{ - compile_logical_asap_dag_with_node_ids, EdgeRole, LogicalASAPDAGDocument, - LogicalASAPDAGValidationError, LogicalASAPNodeId, LogicalASAPOperatorPayload, - }, - ir::operator_properties::Reduction, - ir::{ASAPOp, OperatorResultKind, ProjectItem, ScalarExpr}, - post_asap::{GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate}, - pre_asap::{ColumnRef, DataType, Field, FieldDataType, ScalarValue, Source}, +use asap_types::ir::export::{ + compile_logical_asap_dag_with_node_ids, EdgeRole, LogicalASAPDAGDocument, + LogicalASAPDAGValidationError, LogicalASAPNodeId, LogicalASAPOperatorPayload, +}; +use asap_types::ir::operator::operator_properties::Reduction; +use asap_types::ir::operator::Source; +use asap_types::ir::scalar::{ColumnRef, ScalarValue}; +use asap_types::ir::schema::{ + DataType, Field, FieldDataType, GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, + SummaryUpdate, }; +use asap_types::ir::{ASAPOp, OperatorResultKind, ProjectItem, ScalarExpr}; use std::rc::Rc; fn values() -> Rc { @@ -99,14 +99,16 @@ fn merged_summary_preserves_typed_state() { let root = OperatorNode::new_shared(Operator::ASAP(ASAPOp::SummaryMerge { children: (0..2) .map(|start| { - let coverage = asap_types::ir::summary_coverage::SummaryCoverage { + let coverage = asap_types::ir::properties::summary_coverage::SummaryCoverage { source: Source::Table { table_ref: "values".into(), }, - regions: vec![asap_types::ir::summary_coverage::CoverageRegion { - time_ms: Some(start..start + 1), - population: Default::default(), - }], + regions: vec![ + asap_types::ir::properties::summary_coverage::CoverageRegion { + time_ms: Some(start..start + 1), + population: Default::default(), + }, + ], }; std::rc::Rc::new((*state).clone().with_coverage(coverage).unwrap()) }) diff --git a/crates/types/tests/physical_export.rs b/crates/types/tests/physical_export.rs index f69cc5c9b..a3397e2f0 100644 --- a/crates/types/tests/physical_export.rs +++ b/crates/types/tests/physical_export.rs @@ -2,13 +2,16 @@ use asap_types::ir::export::{ compile_physical_asap_dag, PhysicalASAPDAGDocument, PhysicalASAPDAGValidationError, }; -use asap_types::ir::summary_coverage::{CoverageRegion, SummaryCoverage}; +use asap_types::ir::operator::{Reduction, Source}; +use asap_types::ir::properties::summary_coverage::{CoverageRegion, SummaryCoverage}; +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 2ba817861..4d98e8c7e 100644 --- a/crates/types/tests/planner_vocabulary.rs +++ b/crates/types/tests/planner_vocabulary.rs @@ -1,6 +1,6 @@ use asap_types::ir::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 fc7a3f145..69c51a36d 100644 --- a/crates/types/tests/schema_rebuilding.rs +++ b/crates/types/tests/schema_rebuilding.rs @@ -1,11 +1,10 @@ -use asap_types::ir::summary_coverage::{CoverageRegion, SummaryCoverage}; +use asap_types::ir::operator::{AggIntent, Reduction, Source}; +use asap_types::ir::properties::summary_coverage::{CoverageRegion, SummaryCoverage}; +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 coverage() -> SummaryCoverage { @@ -152,7 +151,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), @@ -189,8 +188,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 bebdadb18..6561e74b9 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 { @@ -14,8 +16,8 @@ fn scan() -> Rc { .unwrap() } /// Tabular coverage for a whole-table summary. -fn whole_table() -> asap_types::ir::summary_coverage::SummaryCoverage { - use asap_types::ir::summary_coverage::{CoverageRegion, SummaryCoverage}; +fn whole_table() -> asap_types::ir::properties::summary_coverage::SummaryCoverage { + use asap_types::ir::properties::summary_coverage::{CoverageRegion, SummaryCoverage}; SummaryCoverage { source: Source::Table { table_ref: "t".into(), @@ -97,12 +99,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(), @@ -153,8 +156,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, @@ -183,9 +186,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 3b99e9bba..b1a8149dd 100644 --- a/crates/types/tests/summary_coverage.rs +++ b/crates/types/tests/summary_coverage.rs @@ -1,10 +1,9 @@ //! Coverage composition preserves gaps and rejects duplicate observations. -use asap_types::{ - ir::operator_properties::Reduction, - ir::summary_coverage::*, - post_asap::SummaryUpdate, - pre_asap::{ColumnRef, Source}, -}; +use asap_types::ir::operator::operator_properties::Reduction; +use asap_types::ir::operator::Source; +use asap_types::ir::properties::summary_coverage::*; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::SummaryUpdate; fn table(name: &str) -> Source { Source::Table { table_ref: name.into(), @@ -88,11 +87,10 @@ fn overlap_and_identity_fail_closed() { /// Coverage is logical state metadata, and input rewrites invalidate its proof. #[test] fn node_coverage_is_required_checked_and_cleared_by_rewrites() { - use asap_types::{ - ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}, - post_asap::{SketchAlgorithm, SketchKind, SketchParams}, - pre_asap::{DataType, Field, FieldDataType, Schema}, + use asap_types::ir::schema::{ + DataType, Field, FieldDataType, Schema, SketchAlgorithm, SketchKind, SketchParams, }; + use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}; let raw = OperatorNode::new_shared(Operator::NonASAP(NonASAPOp::Scan { source: table("flows"), predicates: vec![], diff --git a/crates/types/tests/summary_coverage_examples.rs b/crates/types/tests/summary_coverage_examples.rs index bfaa28483..5e2a7c05a 100644 --- a/crates/types/tests/summary_coverage_examples.rs +++ b/crates/types/tests/summary_coverage_examples.rs @@ -1,17 +1,18 @@ //! The examples in docs/design_docs/proposals/asap-primitive-schema.md, built as real //! SummaryAgg -> SummaryMerge plans. Every input has the same schema //! `(job: Utf8, state: KLL{k=200})`; only coverage differs. -use asap_types::ir::summary_coverage::{CoverageError, CoverageRegion, SummaryCoverage}; -use asap_types::ir::{ - ASAPOp, ExprSemantics, NonASAPOp, Operator, OperatorNode, Predicate, ScalarExpr, - SchemaDerivationError, +use asap_types::ir::operator::{Reduction, Source}; +use asap_types::ir::properties::summary_coverage::{ + CoverageError, CoverageRegion, SummaryCoverage, }; -use asap_types::post_asap::{ +use asap_types::ir::scalar::{ColumnRef, CompareOpKind, ScalarValue}; +use asap_types::ir::schema::{DataType, Field, FieldDataType, Schema}; +use asap_types::ir::schema::{ GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate, }; -use asap_types::pre_asap::{ - ColumnRef, CompareOpKind, DataType, Field, FieldDataType, Reduction, ScalarValue, Schema, - Source, +use asap_types::ir::{ + ASAPOp, ExprSemantics, NonASAPOp, Operator, OperatorNode, Predicate, ScalarExpr, + SchemaDerivationError, }; use std::rc::Rc; diff --git a/crates/types/tests/summary_merge_structure.rs b/crates/types/tests/summary_merge_structure.rs index 383b2bfbd..27bfcf908 100644 --- a/crates/types/tests/summary_merge_structure.rs +++ b/crates/types/tests/summary_merge_structure.rs @@ -1,10 +1,11 @@ //! Window composition merges compatible summary states without consuming raw rows. -use asap_types::{ - ir::operator_properties::{Reduction, Source}, - ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}, - post_asap::{GroupingStrategy, SketchAlgorithm, SketchKind, SketchParams, SummaryUpdate}, - pre_asap::{ColumnRef, DataType, Field, FieldDataType, Schema}, +use asap_types::ir::operator::operator_properties::{Reduction, Source}; +use asap_types::ir::scalar::ColumnRef; +use asap_types::ir::schema::{ + DataType, Field, FieldDataType, GroupingStrategy, Schema, SketchAlgorithm, SketchKind, + SketchParams, SummaryUpdate, }; +use asap_types::ir::{ASAPOp, NonASAPOp, Operator, OperatorNode}; use std::rc::Rc; fn state(k: u32) -> Rc { let scan = OperatorNode::new_shared(Operator::NonASAP(NonASAPOp::Scan { @@ -29,15 +30,19 @@ fn state(k: u32) -> Rc { .unwrap(); std::rc::Rc::new( summary - .with_coverage(asap_types::ir::summary_coverage::SummaryCoverage { - source: Source::Table { - table_ref: "latencies".into(), + .with_coverage( + asap_types::ir::properties::summary_coverage::SummaryCoverage { + source: Source::Table { + table_ref: "latencies".into(), + }, + regions: vec![ + asap_types::ir::properties::summary_coverage::CoverageRegion { + time_ms: Some(0..1), + population: Default::default(), + }, + ], }, - regions: vec![asap_types::ir::summary_coverage::CoverageRegion { - time_ms: Some(0..1), - population: Default::default(), - }], - }) + ) .unwrap(), ) } 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 aad13359a..d9f56a38c 100644 --- a/docs/design_docs/proposals/planner-layering.md +++ b/docs/design_docs/proposals/planner-layering.md @@ -56,7 +56,7 @@ In order to achieve the goals, ASAPPlanner needs to abstract the modeling the fo | Deployment inputs | Empirical cost model, empirical accuracy model and execution capabilities | | ASAP replacement strategies | Rules that replace a sub-DAG of the query expression with summary expressions, and the summary families each computation may use | -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, [#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 inputs and executes the plan: it provides its empirical cost model, empirical accuracy @@ -439,7 +439,7 @@ given: it does not choose among summaries or decide what to materialize. 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