Skip to content

feat(extensions)!: deprecate std_dev and variance using function options#1019

Merged
nielspardon merged 2 commits into
substrait-io:mainfrom
nielspardon:par-depr-stddev
Apr 8, 2026
Merged

feat(extensions)!: deprecate std_dev and variance using function options#1019
nielspardon merged 2 commits into
substrait-io:mainfrom
nielspardon:par-depr-stddev

Conversation

@nielspardon

@nielspardon nielspardon commented Mar 23, 2026

Copy link
Copy Markdown
Member

BREAKING CHANGE: deprecates the function signatures for std_dev and variance using function options in favor of the versions using enum arguments

Follow-up to and depending on #1011 main change in commit d20dde3


This change is Reviewable

@yongchul yongchul left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for deprecation.

BREAKING CHANGE: deprecates the function signatures for std_dev and variance
using function options in favor of the versions using enum arguments

Signed-off-by: Niels Pardon <par@zurich.ibm.com>
Signed-off-by: Niels Pardon <par@zurich.ibm.com>
@nielspardon

Copy link
Copy Markdown
Member Author

rebased on latest main which fixed conflicts and update the deprecation version to 0.88.0 since this PR missed the 0.87.0 release

@nielspardon
nielspardon merged commit fc6ab3c into substrait-io:main Apr 8, 2026
13 checks passed
@nielspardon
nielspardon deleted the par-depr-stddev branch April 15, 2026 08:47
andrew-coleman pushed a commit to substrait-io/substrait-java that referenced this pull request Jul 15, 2026
This PR implements the bidirectional conversion between Calcite and
Substrait for the
statistical aggregate functions standard deviation and variance
(`STDDEV_POP`,
`STDDEV_SAMP`, `VAR_POP`, `VAR_SAMP`).

### Problem

Substrait uses a single function name for both the population and sample
variants:

- `std_dev` for both `STDDEV_POP` and `STDDEV_SAMP`
- `variance` for both `VAR_POP` and `VAR_SAMP`

The population (n denominator) vs. sample (n-1 denominator) distinction
is captured by a
`distribution` value (`POPULATION` or `SAMPLE`). Previously these
functions were not mapped,
so the existing TPC-DS test cases using them were silently mis-mapped to
`AVG` (Calcite
represents these statistical functions with `SqlAvgAggFunction`).

### Solution

This uses the **non-deprecated** signatures introduced in
substrait-io/substrait#1011
(Substrait v0.87.0), which carry the distinction as an **enum function
argument** (the
leading `distribution` argument, e.g. `std_dev:req_fp64`), rather than
the deprecated
function-option form (substrait-io/substrait#1019). 

Resolves #803
Resolves #807 

Since the input arguments are cast to `FP64` when necessary, the
integer-based signatures
proposed in substrait-io/substrait#1012 are not required.

**Calcite → Substrait:**

- Added function mappings in `FunctionMappings` for all four statistical
operators.
- `AggregateFunctionConverter` synthesizes the leading `distribution`
enum operand based on
the Calcite `SqlKind`, so the generic function matcher resolves the
enum-arg variant and
  builds the `EnumArg` automatically (no bespoke option plumbing).
- Statistical inputs are cast to `FP64` where necessary.

**Substrait → Calcite:**

- `FunctionConverter.getSqlOperatorFromSubstraitFunc` disambiguates the
population/sample
  operator from the `distribution` enum argument.
- `SubstraitRelNodeConverter` and `PreCalciteAggregateValidator` skip
the non-value enum
  argument when building Calcite aggregate operands.

**DSL & shared enum:**

- A shared `StatisticalDistribution` enum (in `:core`) is the single
source of truth for the
`SAMPLE` / `POPULATION` values used by both the DSL builder and isthmus.
- `SubstraitBuilder` gains `stddevPopulation`, `stddevSample`,
`variancePopulation`, and
  `varianceSample` convenience methods.

### Non-floating-point inputs

`std_dev` / `variance` only define `fp32` / `fp64` signatures, so a
statistical aggregate
over an integer (or other non-fp) column is rewritten in
`SubstraitRelVisitor` to cast the
argument to `fp64` (appending a cast column so other aggregates over the
same column are
unaffected) and cast the result back to the type Calcite inferred. The
rewrite is
idempotent, so the converted plan is stable under further round trips.

### Testing

- `AggregationFunctionsTest` exercises full round trips (POJO ⇄ proto
and Substrait ⇄
  Calcite) for all four functions, with and without grouping.
- `StatisticalFunctionTest` verifies the SQL round trip, asserts that
each SQL operator
maps to the enum-arg signature (`std_dev:req_fp64` etc.) with the
correct `distribution`
`EnumArg` and no function options, and covers non-fp (integer) inputs —
including a
  column shared with a non-statistical aggregate, and with grouping.

🤖 Generated with AI

---------

Signed-off-by: Niels Pardon <par@zurich.ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PMC Ready PRs ready for review by PMCs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants