diff --git a/Cargo.lock b/Cargo.lock index 1d5067e24..9cf7c069a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -313,16 +313,6 @@ dependencies = [ "regex-syntax", ] -[[package]] -name = "asap-aware-mapping" -version = "0.1.0" -dependencies = [ - "asap-logical-optimizer", - "asap-plan-selection", - "asap-types", - "thiserror 2.0.18", -] - [[package]] name = "asap-devtools" version = "0.1.0" @@ -458,7 +448,6 @@ dependencies = [ name = "asap-planner" version = "0.1.0" dependencies = [ - "asap-aware-mapping", "asap-frontend-metricsql", "asap-frontend-promql", "asap-frontend-sql", diff --git a/Cargo.toml b/Cargo.toml index 655de7b59..b8798fe8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,6 @@ members = [ "crates/types", "crates/frontend-common", "crates/sql-function-catalog", - "crates/asap-aware-mapping", "crates/logical-optimizer", "crates/physical-optimizer", "crates/plan-selection", diff --git a/crates/asap-aware-mapping/Cargo.toml b/crates/asap-aware-mapping/Cargo.toml deleted file mode 100644 index 44dca7631..000000000 --- a/crates/asap-aware-mapping/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "asap-aware-mapping" -version = "0.1.0" -edition = "2021" - -# The planner facade (pass/) over the #509 stage crates: Stage 1 -# asap-logical-optimizer and Stage 3 asap-plan-selection (which brings Stage 2). -# Never depends on a front end. -[dependencies] -asap-types = { path = "../types" } -asap-logical-optimizer = { path = "../logical-optimizer" } -asap-plan-selection = { path = "../plan-selection" } -thiserror = "2" - diff --git a/crates/asap-aware-mapping/src/lib.rs b/crates/asap-aware-mapping/src/lib.rs deleted file mode 100644 index 0ae67ff63..000000000 --- a/crates/asap-aware-mapping/src/lib.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! `asap-aware-mapping` — the planner facade over the #509 stage crates: -//! Stage 1 [`asap_logical_optimizer`], Stage 2 `asap-physical-optimizer` and -//! Stage 3 [`asap_plan_selection`]. -//! -//! It is being retired (#572): the facade (`pass`) moves to `asap-planner`. -//! -//! ## Planning workflows -//! -//! - Run the #509 stage pipeline through [`optimize`] with [`StagePipeline`]: -//! Stage 1 local alternatives, Stage 2 physical candidates, and Stage 3 -//! selection, the only stage that prices plans. -//! - Legacy: search the workload with -//! [`asap_logical_optimizer::search_workload`], then rank with -//! [`cost_sorted`](asap_plan_selection::candidate_selection::cost_sorted) or -//! select with -//! [`global_selection`](asap_plan_selection::candidate_selection::global_selection) -//! and assemble each query root with -//! [`GlobalSelection::assemble_selected_dag`](asap_logical_optimizer::GlobalSelection::assemble_selected_dag). -//! Every summary runs at query time until Stage 2 materialization (#509) -//! owns that choice. This path is deleted under #580. -//! -//! Physical operator binding, placement, storage, deployment, and execution -//! remain downstream responsibilities. - -pub mod pass; - -pub use pass::{ - optimize, OptimizationInput, OptimizationInputError, OptimizationPass, OptimizeError, - PassNameConflict, PassRegistry, PlanOutput, QueryPlan, StagePipeline, -}; diff --git a/crates/devtools/src/bin/show_post_asap_ir.rs b/crates/devtools/src/bin/show_post_asap_ir.rs index c3699c708..838bfd104 100644 --- a/crates/devtools/src/bin/show_post_asap_ir.rs +++ b/crates/devtools/src/bin/show_post_asap_ir.rs @@ -2,7 +2,7 @@ // (or pipe via stdin: cargo run -p asap-devtools --bin show_post_asap_ir < queries.txt) // // Lowers a batch of ad-hoc SQL/PromQL queries to pre-ASAP IR, then runs the -// `asap-aware-mapping` pre-ASAP → post-ASAP binding pass and prints the +// `asap-logical-optimizer` pre-ASAP → post-ASAP binding pass and prints the // resulting **post-ASAP IR** (the sketch-bound IR: an `OperatorNode` DAG in // which `ASAPOp` operators — the concrete summary family/params committed per // aggregate — replace the bound aggregates, while whatever the pass left diff --git a/crates/frontend-promql/tests/observability/promql_corpus.rs b/crates/frontend-promql/tests/observability/promql_corpus.rs index 8af5af79b..606b2dbab 100644 --- a/crates/frontend-promql/tests/observability/promql_corpus.rs +++ b/crates/frontend-promql/tests/observability/promql_corpus.rs @@ -88,7 +88,7 @@ fn tally(corpus: &str) -> Tally { } /// Every query that lowers, additionally run through the pre-ASAP → -/// post-ASAP `asap-aware-mapping` binding pass (issue #98), at an +/// post-ASAP `asap-logical-optimizer` binding pass (issue #98), at an /// approximate accuracy target so the sketch-selection boundary actually /// fires (an `Exact` target would only ever exercise the exact-accumulator /// arm). diff --git a/crates/integration-tests/tests/cse.rs b/crates/integration-tests/tests/cse.rs index 6b5d5a826..e1b35029c 100644 --- a/crates/integration-tests/tests/cse.rs +++ b/crates/integration-tests/tests/cse.rs @@ -4,7 +4,7 @@ //! Drives the full staged pipeline this issue lands: two independently //! lowered `OperatorNode` DAGs → `share_common_sub_dags` (stage 1, //! `asap-types::ir::cse`, run internally by `search_workload`) → -//! `search_workload` (stage 2, `asap-aware-mapping`) — and asserts the +//! `search_workload` (stage 2, `asap-logical-optimizer`) — and asserts the //! sharing that stage 1 decides survives into stage 2's discovered //! `CandidateLogicalASAPDAGs` as one genuinely shared `TargetSubDAGCandidates`, not just one shared //! `Rc`. This is the "real caller" the issue's landing plan @@ -15,9 +15,9 @@ //! Committing to one final, physically-materialized answer for a whole //! workload (the former `implement_workload`/`implement_workload_with`, //! which this test file used to drive instead of `search_workload`) is out -//! of `asap-aware-mapping`'s scope — see that crate's `lib.rs` `## Status` +//! of `asap-logical-optimizer`'s scope — see that crate's `lib.rs` `## Status` //! section — so these tests assert on the discovered `CandidateLogicalASAPDAGs` shape -//! directly, the same way `asap-aware-mapping::replacement`'s own +//! directly, the same way `asap-logical-optimizer::pass1::replacement`'s own //! `shared_aggregate_across_two_roots_gets_both_strategies_candidates` test //! does, just exercised through the crate's public API from this external //! integration-test crate. @@ -70,7 +70,7 @@ fn duplicate_workload_queries_collapse_onto_one_memo_group() { // TargetSubDAGCandidates with consumer_count 2 — ASAPStrategies's one // ExactAggregate candidate *and* SharedSubDAGStrategy's share-vs- // recompute pair, exactly as `shared_aggregate_across_two_roots_gets_both_strategies_candidates` - // (asap-aware-mapping::replacement's own equivalent, internal test) + // (asap-logical-optimizer::pass1::replacement's own equivalent, internal test) // pins for the same fixture shape. let group = space .candidates_for_target(&space.roots[0].1) diff --git a/crates/logical-optimizer/src/accuracy/mod.rs b/crates/logical-optimizer/src/accuracy/mod.rs index 2ea64d7f4..08ec27471 100644 --- a/crates/logical-optimizer/src/accuracy/mod.rs +++ b/crates/logical-optimizer/src/accuracy/mod.rs @@ -29,7 +29,7 @@ use asap_types::types::AccuracyTarget; use crate::pass1::exact_composition::ExactOperation; -/// The deployment-extensible accuracy algebra. `asap-aware-mapping` ships +/// The deployment-extensible accuracy algebra. `asap-logical-optimizer` ships /// [`DefaultAccuracyModel`]; a deployment with a proof for a composition the /// default rejects (a registered cross-metric conversion, say) implements /// this trait and passes it to diff --git a/crates/logical-optimizer/src/pass1/rollup.rs b/crates/logical-optimizer/src/pass1/rollup.rs index 07c551e0a..5b8bb59e4 100644 --- a/crates/logical-optimizer/src/pass1/rollup.rs +++ b/crates/logical-optimizer/src/pass1/rollup.rs @@ -87,7 +87,7 @@ //! own set through [`RollupStrategy::new`]. //! - **No materialized roll-up operator.** Actually building a pre-aggregated //! summary/scan leaf at execution time is separate, larger work outside -//! `asap-aware-mapping`'s scope (see issue #254's own "Non-goal" section) +//! `asap-logical-optimizer`'s scope (see issue #254's own "Non-goal" section) //! — this module only constructs the pre-ASAP `NonASAPOp::Aggregate` //! rewrite; a `CostModel`/search engine decides whether to prefer it. //! - **No cross-schema reconciliation** (see "`ColumnId` comparability" diff --git a/crates/logical-optimizer/tests/stage1_cost_independence.rs b/crates/logical-optimizer/tests/stage1_cost_independence.rs index ca28321dc..2c1203a74 100644 --- a/crates/logical-optimizer/tests/stage1_cost_independence.rs +++ b/crates/logical-optimizer/tests/stage1_cost_independence.rs @@ -10,7 +10,7 @@ const FORBIDDEN_MODULES: &[&str] = &["cost_model", "recurrence"]; const FORBIDDEN_CRATES: &[&str] = &[ "asap-physical-optimizer", "asap-plan-selection", - "asap-aware-mapping", + "asap-planner", "asap-physical-operators", ]; diff --git a/crates/physical-optimizer/tests/stage2_dependencies.rs b/crates/physical-optimizer/tests/stage2_dependencies.rs index 0efde379c..e6a1c7b14 100644 --- a/crates/physical-optimizer/tests/stage2_dependencies.rs +++ b/crates/physical-optimizer/tests/stage2_dependencies.rs @@ -6,7 +6,7 @@ use std::path::Path; /// Crates Stage 2 must not depend on: Stage 3, the facade and the executor. const FORBIDDEN_CRATES: &[&str] = &[ "asap-plan-selection", - "asap-aware-mapping", + "asap-planner", "asap-physical-operators", ]; diff --git a/crates/plan-selection/tests/stage3_dependencies.rs b/crates/plan-selection/tests/stage3_dependencies.rs index f221ec892..967bdbe33 100644 --- a/crates/plan-selection/tests/stage3_dependencies.rs +++ b/crates/plan-selection/tests/stage3_dependencies.rs @@ -4,11 +4,7 @@ use std::path::Path; /// Crates Stage 3 must not depend on: the facade and the executor. -const FORBIDDEN_CRATES: &[&str] = &[ - "asap-aware-mapping", - "asap-planner", - "asap-physical-operators", -]; +const FORBIDDEN_CRATES: &[&str] = &["asap-planner", "asap-physical-operators"]; /// The manifest names neither the facade nor the executor crate, so Cargo /// rejects any import of them. diff --git a/crates/planner/Cargo.toml b/crates/planner/Cargo.toml index 56ff74f50..694b62c4c 100644 --- a/crates/planner/Cargo.toml +++ b/crates/planner/Cargo.toml @@ -6,12 +6,11 @@ edition = "2021" # The library facade (issue #429): one entry point that takes prepared input and # returns the selected DAG. It is the only crate that depends on every frontend # — before it, the sole facade re-exporting more than one was `asap-devtools`, -# a developer-tools crate. Everything below the frontend boundary lives in -# `asap-aware-mapping`, so a third party writing an optimization pass (issue -# #430) depends on that crate alone and never pulls in DataFusion. +# a developer-tools crate. It also owns the optimization pass (pass/, issue +# #430) that runs the #509 stage crates. [dependencies] asap-types = { path = "../types" } -asap-aware-mapping = { path = "../asap-aware-mapping" } +asap-logical-optimizer = { path = "../logical-optimizer" } asap-plan-selection = { path = "../plan-selection" } asap-frontend-sql = { path = "../frontend-sql" } asap-frontend-promql = { path = "../frontend-promql" } @@ -22,4 +21,3 @@ thiserror = "2" # The SQL frontend plans through DataFusion, which is async; `e2e_plan` is # therefore async and its tests need a runtime. tokio = { version = "1", features = ["rt", "macros", "rt-multi-thread"] } -asap-logical-optimizer = { path = "../logical-optimizer" } diff --git a/crates/planner/src/lib.rs b/crates/planner/src/lib.rs index 3e2650a0e..de71cbbf4 100644 --- a/crates/planner/src/lib.rs +++ b/crates/planner/src/lib.rs @@ -3,13 +3,12 @@ //! //! ```text //! PlanningWorkload ──lowering──▶ ParsedWorkload ──optimization pass──▶ PlanOutput -//! (this crate) (asap-aware-mapping) +//! (front ends) ([`pass`]: #509 Stages 1–3) //! ``` //! //! [`e2e_plan`] runs both stages. A caller who already holds pre-ASAP IR — a //! new frontend, a deserialized plan, a test that does not want to build SQL -//! and a catalog — skips this crate and calls -//! [`asap_aware_mapping::optimize`] directly. +//! and a catalog — calls [`optimize`] directly. use asap_types::workload::parsed_workload::{ParsedWorkload, ParsedWorkloadError}; use asap_types::workload::{PlanningWorkload, QueryLanguage, SqlDialect, WorkloadError}; @@ -21,14 +20,16 @@ use asap_frontend_promql::{ }; use asap_frontend_sql::{lower_sql_dialect, SqlCatalog, SqlError}; +pub mod pass; + // The optimization stage's vocabulary is this facade's vocabulary too: a caller // configures the same models and reads the same output whether it goes through // `e2e_plan` or straight to `optimize`. -pub use asap_aware_mapping::pass::{ - optimize, OptimizationInput, OptimizationPass, OptimizeError, PassRegistry, PlanOutput, - QueryPlan, StagePipeline, -}; pub use asap_plan_selection::PlanningModels; +pub use pass::{ + optimize, OptimizationInput, OptimizationInputError, OptimizationPass, OptimizeError, + PassNameConflict, PassRegistry, PlanOutput, QueryPlan, StagePipeline, +}; // ── Input ──────────────────────────────────────────────────────────────── diff --git a/crates/asap-aware-mapping/src/pass/mod.rs b/crates/planner/src/pass/mod.rs similarity index 100% rename from crates/asap-aware-mapping/src/pass/mod.rs rename to crates/planner/src/pass/mod.rs diff --git a/crates/asap-aware-mapping/src/pass/stage_pipeline.rs b/crates/planner/src/pass/stage_pipeline.rs similarity index 100% rename from crates/asap-aware-mapping/src/pass/stage_pipeline.rs rename to crates/planner/src/pass/stage_pipeline.rs diff --git a/crates/planner/tests/e2e_plan.rs b/crates/planner/tests/e2e_plan.rs index 59d92ac53..2a31ac100 100644 --- a/crates/planner/tests/e2e_plan.rs +++ b/crates/planner/tests/e2e_plan.rs @@ -3,10 +3,10 @@ use std::rc::Rc; -use asap_aware_mapping::pass::{OptimizationInput, OptimizationPass, OptimizeError, PlanOutput}; use asap_frontend_sql::{lower_sql_dialect, SqlCatalog}; use asap_logical_optimizer::pass1::logical_candidates::enumerate_local_logical_candidates; use asap_plan_selection::{select_exhaustive, PlanningModels, MAX_ENUMERATED_CANDIDATES}; +use asap_planner::pass::{OptimizationInput, OptimizationPass, OptimizeError, PlanOutput}; use asap_planner::{e2e_plan, FrontendInput, PlanError, UserInput, UserInputError}; use asap_types::ir::schema::{DataType, Field, Schema}; use asap_types::ir::QueryRoot; @@ -242,7 +242,7 @@ async fn harness_rejects_a_pass_that_mislabels_entry_indices() { "mangling" } fn optimize(&self, input: OptimizationInput<'_>) -> Result { - let mut output = asap_aware_mapping::StagePipeline.optimize(input)?; + let mut output = asap_planner::StagePipeline.optimize(input)?; for plan in output.plans.iter_mut() { plan.entry_index += 1; } diff --git a/crates/planner/tests/summary_sharing.rs b/crates/planner/tests/summary_sharing.rs index 654d6c4bb..5aee0c3db 100644 --- a/crates/planner/tests/summary_sharing.rs +++ b/crates/planner/tests/summary_sharing.rs @@ -5,7 +5,6 @@ use asap_types::ir::cse::share_common_sub_dags; use asap_types::ir::{ASAPOp, OperatorNode}; use std::rc::Rc; -use asap_aware_mapping::pass::{PlanOutput, QueryPlan}; use asap_frontend_promql::lower_promql_workload; use asap_frontend_sql::SqlCatalog; use asap_logical_optimizer::accuracy::{ @@ -19,6 +18,7 @@ use asap_logical_optimizer::{ use asap_plan_selection::candidate_selection::global_selection; use asap_plan_selection::PlanningModels; use asap_plan_selection::{CostModel, DefaultCostModel}; +use asap_planner::pass::{PlanOutput, QueryPlan}; use asap_planner::{e2e_plan, FrontendInput, UserInput}; use asap_types::ir::operator::agg_intent::default_quantile; use asap_types::ir::operator::AggIntent; diff --git a/crates/types/src/dag_export.rs b/crates/types/src/dag_export.rs index 4094d2390..6390ac189 100644 --- a/crates/types/src/dag_export.rs +++ b/crates/types/src/dag_export.rs @@ -47,7 +47,7 @@ //! out of [`export`]. It exists so a *higher* layer — one that depends on //! `asap_types`, never the reverse — can annotate an already-exported DAG //! after the fact without this module needing to know anything about that -//! layer's concepts. Concretely: `asap-aware-mapping`'s `explanation` module +//! layer's concepts. Concretely: `asap-logical-optimizer`'s `explanation` module //! (issue #257) computes `structural_hash` over the same nodes this module //! does (via the identical function). The devtools exporter uses that hash //! to narrow candidates, then compares its target with @@ -118,7 +118,7 @@ pub struct DAGNode { /// Arbitrary reporting-layer annotations for this node — e.g. why a /// replacement exists here. `asap_types` never populates this itself /// (it has no notion of a "replacement" at all — see the module doc's - /// layering note); a higher layer that does (`asap-aware-mapping`, via + /// layering note); a higher layer that does (`asap-logical-optimizer`, via /// the `dag_export` devtools binary) fills it in after the fact by /// matching [`DAGNode::hash`] and confirming structural equality. Empty /// by default, so every existing [`export`] caller and test is unaffected. @@ -134,7 +134,7 @@ pub struct DAGNode { /// One reporting-layer annotation attached to a [`DAGNode`] by a higher /// layer than `asap_types` — see [`DAGNode::notes`]. `asap_types` defines /// this shape (so the field has a concrete, serializable type) but never -/// constructs one: `asap_types` is a lower crate that `asap-aware-mapping` +/// constructs one: `asap_types` is a lower crate that `asap-logical-optimizer` /// depends on, never the reverse, so this type is deliberately generic and /// crate-agnostic rather than naming anything from that higher layer (e.g. /// its `ExplanationKind`/`ReplacementExplanation`). @@ -222,7 +222,7 @@ pub struct NamedDAG { /// Concrete post-ASAP replacement sites discovered for this query — see /// [`TargetReplacement`]. Always empty coming out of anything in this /// module (same layering rule as [`DAGNode::notes`]: `asap_types` never - /// runs `asap-aware-mapping`'s search itself); a higher layer populates + /// runs `asap-logical-optimizer`'s search itself); a higher layer populates /// this after the fact, e.g. the `dag_export` devtools binary's /// `--post-asap` flag. Omitted from the JSON entirely when empty, so /// every existing producer/consumer of `NamedDAG` (in particular every @@ -290,7 +290,7 @@ pub struct WorkloadDAG { // ── Post-ASAP replacement export — a layering-seam-shaped feature ────────── // // [`TargetReplacement`] is the generic, crate-agnostic "one replacement -// site, before and after" shape a higher layer (`asap-aware-mapping`, via +// site, before and after" shape a higher layer (`asap-logical-optimizer`, via // the `dag_export` devtools binary's `--post-asap` flag) populates after // running its own search — the exact same layering rule [`DAGNode::notes`]'s // doc above already states: this module never runs @@ -299,7 +299,7 @@ pub struct WorkloadDAG { // `ReplacementProvenance` or a cost model even is. It only defines shapes // concrete and serializable enough for a higher layer to fill in, and for // `tools/dag-viewer` to render without needing to know anything about -// `asap-aware-mapping`'s own vocabulary. +// `asap-logical-optimizer`'s own vocabulary. /// One flattened node of a [`SummaryDAG`] — the same node as a /// [`DAGNode`], in the shape the summary-maintenance consumers read: diff --git a/docs/design_docs/architecture/README.md b/docs/design_docs/architecture/README.md index c3a74f721..7f60d0932 100644 --- a/docs/design_docs/architecture/README.md +++ b/docs/design_docs/architecture/README.md @@ -53,7 +53,8 @@ an unsupported physical alternative into a deployable plan. | Shared IR | `asap-types` | The unified operator IR (`ir`: one `OperatorNode` before and after ASAP optimization), schemas, workloads, guarantees, and exported plan data | | Front-end common | `frontend-common` | Name-based `UnresolvedOp` tree shared by the front ends, and `resolve_root` into the operator IR | | Query frontends | `frontend-sql`, `frontend-promql`, `frontend-metricsql` | Parse source languages and produce canonical Pre-ASAP queries | -| ASAP-aware mapping | `asap-aware-mapping` | Candidate generation, CSE, legality, accuracy propagation, costing, and ranking | +| ASAP-aware mapping | `asap-logical-optimizer`, `asap-physical-optimizer`, `asap-plan-selection` | #509 Stages 1–3: candidate generation, CSE, legality and accuracy propagation; physical candidates; costing and selection | +| Planner facade | `asap-planner` | Lowering dispatch, the optimization pass (`OptimizationPass`, `StagePipeline`) and `optimize` | | Developer inspection | `devtools` | Expose planner DAGs, alternatives, decisions, and explanations for inspection | | End-to-end validation | `integration-tests` | Verify behavior across frontends, mapping, and output IR | diff --git a/docs/design_docs/architecture/updated_interface_with_pluggable_optimization.md b/docs/design_docs/architecture/updated_interface_with_pluggable_optimization.md index 56a5df003..c3daefe75 100644 --- a/docs/design_docs/architecture/updated_interface_with_pluggable_optimization.md +++ b/docs/design_docs/architecture/updated_interface_with_pluggable_optimization.md @@ -224,21 +224,20 @@ pass no longer runs these steps; another pass need not run any of them. | Crate | What it holds | |---|---| | `asap-types` | `ParsedWorkload` | -| `asap-aware-mapping` | `OptimizationPass`, `OptimizationInput`, `PlanOutput`, `PlanningModels`, `optimize`, `PassRegistry`, `StagePipeline` | -| `asap-planner` *(new)* | `e2e_plan`, `UserInput`, `FrontendInput`, lowering dispatch | +| `asap-plan-selection` | `PlanningModels` | +| `asap-planner` | `e2e_plan`, `UserInput`, `FrontendInput`, lowering dispatch; `OptimizationPass`, `OptimizationInput`, `PlanOutput`, `optimize`, `PassRegistry`, `StagePipeline` | ```text asap-planner ──┬──> asap-frontend-{sql, promql, metricsql} - └──> asap-aware-mapping ──> asap-types - ▲ - a pass depends only this far + └──> asap-plan-selection ──> asap-physical-optimizer ──> asap-logical-optimizer ──> asap-types ``` `asap-planner` is separate because it is the only crate depending on every frontend; before it, the sole facade re-exporting more than one was `asap-devtools`, a developer-tools crate. `PlanningModels` lives in -`asap-aware-mapping` (`plan_selection`) because both inputs use it, and -`asap-planner` re-exports it. +`asap-plan-selection` because both inputs use it, and `asap-planner` +re-exports it. Since #572 the pass lives in `asap-planner`, so a pass +implementation depends on the frontends too. --- diff --git a/docs/design_docs/concepts/accuracy-models.md b/docs/design_docs/concepts/accuracy-models.md index 8db6e9a8c..39e7c468b 100644 --- a/docs/design_docs/concepts/accuracy-models.md +++ b/docs/design_docs/concepts/accuracy-models.md @@ -280,7 +280,7 @@ rule or a different estimator configuration would be needed in those cases. ## Organization and extension contract -The `asap-aware-mapping::accuracy` module separates these responsibilities: +The `asap-logical-optimizer::accuracy` module separates these responsibilities: ```text accuracy/ diff --git a/docs/design_docs/decisions/concat-unique-keys.md b/docs/design_docs/decisions/concat-unique-keys.md index 8837bb86c..7d603e08f 100644 --- a/docs/design_docs/decisions/concat-unique-keys.md +++ b/docs/design_docs/decisions/concat-unique-keys.md @@ -129,7 +129,7 @@ for why it's fine to ship unused. caller upstream of `resolve_root`, even though no such caller exists yet. - Every other match/construction site touching `Concat` across the DAG (`canonicalize.rs`, `cse.rs`, `schema_resolver.rs`, `dag_export.rs`, - `asap-aware-mapping`'s `replacement.rs`/`explanation.rs`, and every + `asap-logical-optimizer`'s `replacement.rs`/`explanation.rs`, and every test/tooling AST walker) was mechanically updated to bind or ignore the new field — most just added `, ..`; the two places that *rebuild* a `Concat` node (`cse.rs`'s `rebuild_children`, part of CSE interning) thread diff --git a/docs/design_docs/decisions/cse-cost-model.md b/docs/design_docs/decisions/cse-cost-model.md index 7ad7afbd7..e4f9423a1 100644 --- a/docs/design_docs/decisions/cse-cost-model.md +++ b/docs/design_docs/decisions/cse-cost-model.md @@ -70,11 +70,11 @@ same way a real cost-based optimizer would. ## Layering constraint `share_common_sub_dags` lives in `asap-types::pre_asap` — a lower layer that -`asap-aware-mapping` (which owns `CostModel`) depends on, never the reverse. +`asap-plan-selection` (which owns `CostModel`) depends on, never the reverse. Detection therefore cannot consult cost even if it wanted to. This is why stage 1/2's detection stays unconditional (correctly, as a legality-only gate) and the cost-aware decision is applied downstream, in -`asap-aware-mapping`, after detection rather than fused into it. +`asap-plan-selection`, after detection rather than fused into it. ## Where it hooks in diff --git a/docs/develop_docs/asap-aware-mapping-architecture.md b/docs/develop_docs/asap-aware-mapping-architecture.md index a606bc296..5e400f194 100644 --- a/docs/develop_docs/asap-aware-mapping-architecture.md +++ b/docs/develop_docs/asap-aware-mapping-architecture.md @@ -17,7 +17,7 @@ defined in [mapping contracts](asap-aware-mapping-contracts.md). Names such as `MyStrategy`, `MyCostModel`, and `PreferDDSketch` are illustrative; they do not ship with this crate. Samples that use real public types and functions follow the APIs exported by `asap-logical-optimizer` -(Stage 1 candidate search) and `asap-aware-mapping` (cost models and selection). +(Stage 1 candidate search) and `asap-plan-selection` (cost models and selection). If you only need to find the right extension point, start with the [extension map](extend-asap-aware-mapping.md#7-current-extension-map). If you are implementing a strategy, read this mental model, the [mapping contracts](asap-aware-mapping-contracts.md), and the [extension guide](extend-asap-aware-mapping.md). diff --git a/docs/develop_docs/asap-aware-mapping-contracts.md b/docs/develop_docs/asap-aware-mapping-contracts.md index 1d5734fd6..f519d573e 100644 --- a/docs/develop_docs/asap-aware-mapping-contracts.md +++ b/docs/develop_docs/asap-aware-mapping-contracts.md @@ -205,7 +205,7 @@ see [code architecture §3](asap-aware-mapping-architecture.md#3-how-the-current `CostModel` covers deployment-specific preference and cost decisions. It is consulted only at selection time (`cost_sorted`, `global_selection` and their `_with_recurrence` variants), never during candidate generation: sketch parameters come from the analytical estimators (`accuracy::estimators::size_params`), and extension intents stay pass-through. -The crate cannot hardcode real deployment costs: `asap-aware-mapping` uses `asap-types` and the `asap_sketchlib` mapping +The crate cannot hardcode real deployment costs: `asap-plan-selection` uses `asap-types` and the `asap_sketchlib` mapping bounds, but does not execute workloads or own deployment measurements. Most hooks therefore provide the crate's built-in static behavior as a default. Override only the decisions your deployment needs to change. | Hook | Use it to | Default? | diff --git a/docs/develop_docs/library-api.md b/docs/develop_docs/library-api.md index 2936bf9c6..9dbd31f44 100644 --- a/docs/develop_docs/library-api.md +++ b/docs/develop_docs/library-api.md @@ -23,7 +23,7 @@ artifact, while preserving the checks required by its intended consumer. ## Dependencies Inside this workspace, depend on the frontend you need, -`asap-logical-optimizer` (Stage 1 candidate search), `asap-aware-mapping` +`asap-logical-optimizer` (Stage 1 candidate search), `asap-plan-selection` (cost models and selection) and `asap-types`. External users can use Git dependencies pinned to a compatible revision; use the same revision across these crates. For the example below: @@ -31,7 +31,7 @@ these crates. For the example below: ```toml [dependencies] asap-frontend-promql = { git = "https://github.com/ProjectASAP/ASAPPlanner", rev = "e7fdb2492c42c9f5b34760706a5162aa586d3025" } -asap-aware-mapping = { git = "https://github.com/ProjectASAP/ASAPPlanner", rev = "e7fdb2492c42c9f5b34760706a5162aa586d3025" } +asap-plan-selection = { git = "https://github.com/ProjectASAP/ASAPPlanner", rev = "e7fdb2492c42c9f5b34760706a5162aa586d3025" } asap-logical-optimizer = { git = "https://github.com/ProjectASAP/ASAPPlanner", rev = "e7fdb2492c42c9f5b34760706a5162aa586d3025" } asap-types = { git = "https://github.com/ProjectASAP/ASAPPlanner", rev = "e7fdb2492c42c9f5b34760706a5162aa586d3025" } ``` @@ -410,8 +410,8 @@ not waive semantic or accuracy requirements. ### Model and evidence options Traits permit custom implementations; the following are concrete built-in options. -Cost models are in `asap_aware_mapping` (module-qualified paths below are -relative to it); accuracy models and evidence are in `asap_logical_optimizer`. +Cost models are in `asap_plan_selection` (module-qualified paths below are +relative to `asap_plan_selection::cost`); accuracy models and evidence are in `asap_logical_optimizer`. | Parameter | Available value / constructor | Meaning | | --- | --- | --- | @@ -647,7 +647,7 @@ cost/guarantee evidence needed downstream instead of exporting only a bare DAG. For public symbol details, build local API documentation with: ```sh -cargo doc -p asap-aware-mapping -p asap-types --no-deps +cargo doc -p asap-logical-optimizer -p asap-plan-selection -p asap-types --no-deps ``` ## Source references diff --git a/docs/develop_docs/physical-handoff-costs.md b/docs/develop_docs/physical-handoff-costs.md index e22a15d65..1ccf3a2a8 100644 --- a/docs/develop_docs/physical-handoff-costs.md +++ b/docs/develop_docs/physical-handoff-costs.md @@ -94,7 +94,7 @@ a separate follow-up integration point. Verification: ```sh -cargo test -p asap-aware-mapping --test physical_handoff_cost +cargo test -p asap-plan-selection --test physical_handoff_cost cargo test -p asap-devtools --bin dag_export handoff_bytes_export_and_change_plan_selection python3 -m unittest discover -s tools/dag-viewer -p 'test_render.py' ``` diff --git a/docs/develop_docs/pre-asap-ir.md b/docs/develop_docs/pre-asap-ir.md index 7a557ee96..0f169eca4 100644 --- a/docs/develop_docs/pre-asap-ir.md +++ b/docs/develop_docs/pre-asap-ir.md @@ -364,7 +364,7 @@ Example for `filters`: `count(CASE WHEN p THEN x END)` (`p`, plus `x IS NOT NULL` when `x` is nullable), and from `count(expr)` over any other nullable `expr` (`expr IS NOT NULL`), because canonical `Count` counts rows and never consults its argument. A filtered measure has no summary binding yet: - `asap-aware-mapping` retains such an `Aggregate` as an ordinary exact sub-DAG, and canonicalization does + `asap-logical-optimizer` retains such an `Aggregate` as an ordinary exact sub-DAG, and canonicalization does not promote a filtered count ranking to a heavy-hitter `TopK`. Example for `having`: diff --git a/docs/develop_docs/storage-operation-costs.md b/docs/develop_docs/storage-operation-costs.md index 87cedd08b..e9f1f0e3e 100644 --- a/docs/develop_docs/storage-operation-costs.md +++ b/docs/develop_docs/storage-operation-costs.md @@ -82,7 +82,7 @@ cache-adjusted bytes and CPU with uncached operation counts. Verification: ```sh -cargo test -p asap-aware-mapping --test storage_io -cargo test -p asap-aware-mapping --lib storage_io +cargo test -p asap-plan-selection --test storage_io +cargo test -p asap-plan-selection --lib storage_io cargo test -p asap-devtools --bin dag_export storage_requests_export_and_change_plan_selection ```