You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit f830b03
Browse filesBrowse the repository at this point in the historyBrowse files
feat(sql): lower ClickHouse argMax/argMin to AggIntent::Extension (#242)
argMax(arg, val)/argMin(arg, val) ("arg's value from the row where val
is maximal/minimal") are two-column, row-selecting aggregates -- unlike
every existing AggIntent reducer (Sum/Min/Max/Avg/...), which folds one
column to a value derived from itself, these return a *different*
column's value, selected by which row extremizes a second column. No
existing AggIntent shape fits.
Design decision (issue #232 asked for research before picking):
a repo-wide grep for any existing arg-max/arg-min concept (PromQL front
end, other SQL dialects, docs) found nothing -- only the 3 corpus
occurrences this closes. sql-function-catalog's own
KNOWN_UNMAPPED_NATIVE_FUNCTIONS already documents the same "two-column
reducer" and "value from a particular row" gaps for corr/covar/regr_*
and first_value/last_value/nth_value, for the identical reason:
AggIntent's input_col()/resolve_agg_intent/aggregate_output_schema
machinery is single-column by construction. Per AggIntent::Extension's
own bar ("core only grows for intents >= 2 deployment models actually
use"), with exactly one consumer found, this lowers to
AggIntent::Extension { ext_kind: "arg_max" | "arg_min", payload }
rather than earning first-class ArgMax/ArgMin core variants. This
required zero changes to crates/types: Extension already has complete
plumbing (resolve, output_column, requires/is_per_series, and
downstream PassThrough handling in asap-aware-mapping), which is itself
evidence the Extension escape hatch is doing its job.
Implementation:
- sql-function-catalog: new RewriteKind::PassThrough for a
CLICKHOUSE_BUILTINS entry with no native DataFusion shape to rewrite
to at all (argmax/argmin, arity 2) -- a new pattern alongside the
existing CountDistinct/CountIfToSum rewrite targets.
- frontend-sql: ClickHouseBuiltinRewrite treats PassThrough as a no-op,
so the call reaches lower_agg_intent under its own ClickHouse name.
New lower_arg_selector() validates both arguments as bare columns
(reducer_col's existing "no expression arguments" rule, issue #115,
generalized to 2 args) and builds the Extension node directly; core
never resolves Extension's payload, so both columns are kept as
ColumnRef names rather than positionally-bound ColumnIds.
- Documented, not fixed (matching #230's splitByChar-array-indexing
precedent): DerivedCols::rewrite_agg only special-cases an
aggregate's *first* argument, so val would be dropped from a Project
inserted for some unrelated reason in the same query. Does not affect
the corpus today -- all 3 argMax uses are bare columns.
Corpus tally (bgp_jan2024_workload): Lowered 145 -> 148, Plan 40 -> 37,
every other category unchanged -- all 3 argMax occurrences move
cleanly to Lowered with no companion gap.
Closes#232
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
0 commit comments