Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[workspace]
members = [
"crates/types",
"crates/l2",
"crates/asap-aware-mapping",
"crates/frontend-promql",
"crates/frontend-sql",
Expand Down
7 changes: 4 additions & 3 deletions crates/asap-aware-mapping/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
//! invariant (arrows point up) holds here too.
//!
//! Post-lowering **canonicalization** is *not* here: it landed in
//! `asap_l2::canonicalize`, run inside the shared `convert_root` so every
//! front end normalizes before L3 leaves the converter (issue #34, closed).
//! `asap_types::pre_asap::canonicalize`, run inside the shared `resolve_root`
//! so every front end normalizes before L3 leaves resolution (issue #34,
//! closed).
//!
//! ## Status
//!
Expand Down Expand Up @@ -45,7 +46,7 @@
//! | Term | Layer | Meaning | Lives in |
//! |---|---|---|---|
//! | **Parse** | L1 | text (PromQL/SQL) → AST | `asap-frontend-promql` / `asap-frontend-sql` |
//! | **Bind #1** | L2 | *name resolution*: `ColumnRef` (a name) → `ColumnId` (a concrete schema column) — the classic RDBMS "Parse → **Bind** → Optimize" pipeline sense (e.g. SQL Server's query-processor terminology) | [`asap_l2::binder::Binder`](https://docs.rs/asap-l2) |
//! | **Bind #1** | L2 | *name resolution*: `ColumnRef` (a name) → `ColumnId` (a concrete schema column) — the classic RDBMS "Parse → **Bind** → Optimize" pipeline sense (e.g. SQL Server's query-processor terminology) | [`asap_types::pre_asap::binder::Binder`](https://docs.rs/asap-types) |
//! | **Implementation** — [`boundary::implementation_for`] | L3→L4, *one node* | choosing a concrete physical realization (a sketch family, an exact accumulator, or pass-through) for one [`AggIntent`](asap_types::pre_asap::agg_intent::AggIntent) | [`boundary`] |
//! | **`implement_tree`** — [`bind::implement_tree`] | L3→L4, *whole tree* | walk a whole `QueryExpr` tree, calling [`boundary::implementation_for`] per node, and emit the complete L4 [`SummaryExpr`](asap_types::post_asap::SummaryExpr)/`L4Node` DAG — named after "implementation" too rather than reusing "bind" a second time | [`bind`] |
//! | **Bind #2** (downstream, not in this crate) | L4→L5 | a *deployment's* own physical binder, additionally deciding **placement** (edge vs. backend, wire format, …) — a genuinely different, deployment-specific decision this crate doesn't model at all | e.g. `control_plane::sketch_algebra::rules::bind_*` (as of this writing; expected to fold into that deployment's cost-model layer rather than stay a separate "bind" concept) |
Expand Down
2 changes: 1 addition & 1 deletion crates/devtools/tests/cross_language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Semantically equivalent SQL and PromQL queries must lower to the **same
//! canonical intent algebra**, so an L4 rule matching on `AggIntent` sees one
//! spelling regardless of source language. These tests are the executable spec
//! for the shared [`canonicalize`](asap_l2::canonicalize) pass: they pin the
//! for the shared [`canonicalize`](asap_types::pre_asap::canonicalize) pass: they pin the
//! canonical heavy-hitter shape and assert both front ends reach it.
//!
//! A literal `lower_sql(S) == lower_promql(P)` cannot hold — the two count
Expand Down
3 changes: 1 addition & 2 deletions crates/frontend-promql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ version = "0.1.0"
edition = "2021"

# PromQL front end: L1 (parse) → L2 relational, then the shared L2→L3 converter
# in asap-types. Pulls the PromQL parser only — never DataFusion.
# — both in asap-types. Pulls the PromQL parser only — never DataFusion.
[dependencies]
asap-types = { path = "../types" }
asap-l2 = { path = "../l2" }

# Public GreptimeTeam/promql-parser (Apache-2.0) from crates.io. 0.10 upstreamed
# the experimental functions we used to carry as local patches (mad_over_time,
Expand Down
17 changes: 10 additions & 7 deletions crates/frontend-promql/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::fmt;

use asap_l2::ConvertError;
use asap_types::pre_asap::ResolveTreeError;

/// Errors from lowering a PromQL query (L1 parse → L2 → shared L2→L3 convert).
/// Errors from lowering a PromQL query (L1 parse → canonical L2, built
/// directly → [`resolve_root`](asap_types::pre_asap::resolve_root) binds it
/// to L3, issue #179).
///
/// Carries no DataFusion type — the PromQL front end never depends on the SQL
/// stack. The language-neutral variants (`UnsupportedFeature` / `WrongLanguage`
Expand All @@ -25,8 +27,9 @@ pub enum PromqlError {
InvalidParameter(String),
/// The workload's query language is not PromQL.
WrongLanguage(String),
/// The L2→L3 converter failed (name resolution against the bound schema).
Convert(ConvertError),
/// Resolving the canonical L2 tree to L3 failed (name resolution against
/// the bound schema).
Convert(ResolveTreeError),
}

impl fmt::Display for PromqlError {
Expand All @@ -39,15 +42,15 @@ impl fmt::Display for PromqlError {
Self::MissingArgument(m) => write!(f, "missing argument: {m}"),
Self::InvalidParameter(m) => write!(f, "invalid parameter: {m}"),
Self::WrongLanguage(l) => write!(f, "unsupported query language: {l}"),
Self::Convert(e) => write!(f, "L2→L3 conversion failed: {e}"),
Self::Convert(e) => write!(f, "L2→L3 resolution failed: {e}"),
}
}
}

impl std::error::Error for PromqlError {}

impl From<ConvertError> for PromqlError {
fn from(e: ConvertError) -> Self {
impl From<ResolveTreeError> for PromqlError {
fn from(e: ResolveTreeError) -> Self {
Self::Convert(e)
}
}
Expand Down
21 changes: 11 additions & 10 deletions crates/frontend-promql/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//! PromQL front end: L1 (parse via `promql-parser`) → L2 relational, then the
//! shared L2→L3 [`convert_root`](asap_l2::convert_root).
//! PromQL front end: L1 (parse via `promql-parser`) → the canonical L2 shape,
//! built directly (issue #179) → [`resolve_root`].
//!
//! Emits the per-language
//! [`relational::QueryExpr`](asap_l2::relational); the shared
//! converter runs the [`Binder`](asap_l2::Binder) for
//! positional name resolution. Depends on the PromQL parser only — never on the
//! SQL / DataFusion stack.
//! Emits [`L2QueryExpr`](asap_types::pre_asap::L2QueryExpr) itself — the
//! canonical `QueryExpr`, generic over an unresolved
//! [`ColumnRef`](asap_types::pre_asap::ColumnRef) — directly, rather than a
//! separate per-language relational tree; `resolve_root` runs the
//! [`Binder`](asap_types::pre_asap::Binder) for positional name resolution.
//! Depends on the PromQL parser only — never on the SQL / DataFusion stack.

pub mod error;
pub mod histogram;
pub mod promql;

use asap_l2::convert_root;
use asap_types::pre_asap::resolve_root;
use asap_types::pre_asap::QueryExpr;
use asap_types::types::AccuracyTarget;
use asap_types::workload::{QueryLanguage, QueryWorkload};
Expand All @@ -29,8 +30,8 @@ pub use promql::PromqlLowerer;
/// `histogram_quantile` discrimination uses the structural heuristic; to drive
/// it from declared sample types instead, use [`lower_promql_with_histograms`].
pub fn lower_promql(query: &str, accuracy: AccuracyTarget) -> Result<QueryExpr, PromqlError> {
let l2 = PromqlLowerer::lower(query)?;
let l3 = convert_root(&l2, &accuracy)?;
let l2 = PromqlLowerer::lower(query, &accuracy)?;
let l3 = resolve_root(&l2)?;
Ok(l3)
}

Expand Down
Loading
Loading