From 52444970c900169f9ed10bfc0b4d85fb8f97de87 Mon Sep 17 00:00:00 2001 From: zz_y Date: Thu, 9 Jul 2026 20:44:00 -0600 Subject: [PATCH] test(sql): pin array_agg's rejection as a decision, not a gap (#111) `array_agg` has no test, so "deliberately rejected" and "not implemented yet" look identical in the code. Assert the rejection, with the reasoning inline. AggIntent is the vocabulary the planner binds sketches and mergeable accumulators to. array_agg pre-aggregates nothing (output is O(input rows)), has no bounded-memory approximate form, and its partial state is the data itself. Since plan::boundary::realize is an exhaustive match, an AggIntent::ArrayAgg would force boundary, bind and schema derivation to each handle a variant whose every answer is PassThrough. Contrast median (#117), from the same bucket in #111: it *is* Quantile{q:0.5} and feeds the sketch path, so it was implemented rather than rejected. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/frontend-sql/tests/sql_lowering.rs | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/crates/frontend-sql/tests/sql_lowering.rs b/crates/frontend-sql/tests/sql_lowering.rs index 038693e1..d8998140 100644 --- a/crates/frontend-sql/tests/sql_lowering.rs +++ b/crates/frontend-sql/tests/sql_lowering.rs @@ -1030,3 +1030,29 @@ async fn an_ambiguous_passthrough_column_is_rejected_only_when_projecting() { .expect_err("ambiguous passthrough must be rejected, not silently resolved"); assert!(format!("{err}").contains("ambiguous column"), "got {err}"); } + +// ── Issue #111: array_agg is deliberately not an intent (WONTFIX) ─────────── + +#[tokio::test] +async fn array_agg_is_deliberately_rejected() { + // Not a coverage gap. `AggIntent` exists so the planner can bind a sketch or + // a mergeable accumulator per node; `array_agg` pre-aggregates nothing (its + // output is O(input rows)), has no bounded-memory approximate form, and its + // partial state *is* the data. An `AggIntent::ArrayAgg` would force every + // arm of `plan::boundary::realize` — an exhaustive match — to answer + // `PassThrough`. Contrast `median`, which is `Quantile { q: 0.5 }` and does + // feed the sketch path. + // + // This test exists so the rejection reads as a decision rather than a gap. + let err = lower_sql( + "SELECT array_agg(service) FROM metrics", + &catalog(), + AccuracyTarget::Exact, + ) + .await + .expect_err("array_agg must not lower to an intent"); + assert!( + format!("{err}").contains("unsupported aggregate: array_agg"), + "expected a clean UnsupportedAggregate, got {err}" + ); +}