Skip to content

fix(isthmus): preserve declared aggregate output types#1017

Draft
rkondakov wants to merge 1 commit into
substrait-io:mainfrom
rkondakov:pr-1016-preserve-declared-aggregate-output-types
Draft

fix(isthmus): preserve declared aggregate output types#1017
rkondakov wants to merge 1 commit into
substrait-io:mainfrom
rkondakov:pr-1016-preserve-declared-aggregate-output-types

Conversation

@rkondakov

Copy link
Copy Markdown
Contributor

Fixes #1016.

Problem

SubstraitToCalcite reads each measure's declared output_type, resolves the aggregate function, and then rebuilds the AggregateCalls through Calcite, which re-infers each call's type from the operator's own inference rule. Any declared output type that differs from that inference — in width or in nullability — is silently replaced during transport. A conversion should preserve the plan's declaration exactly rather than substitute another inference policy; #1016 has the end-to-end description.

Change

  • AggregateFunctions.withOutputType(aggFunction, outputType) wraps the resolved aggregate in a per-invocation variant whose return-type inference is ReturnTypes.explicit(declaredType). All non-type behavior delegates to the wrapped function.
  • SubstraitRelNodeConverter.fromMeasure first creates the call with the resolved function and applies the wrapper only when the declared type differs from what Calcite infers, so plans whose declarations already match convert exactly as before.
  • AggregateFunctions.withoutDeclaredOutputType unwraps the variant, and AggregateFunctionConverter uses it when matching Calcite calls back to Substrait functions, so the Calcite→Substrait direction and full round trips are unaffected.
  • The wrapper's equals/hashCode deliberately follow the wrapped function only. Whether two invocations with different declared types should be considered equivalent is a consumer policy; it does not belong in Calcite operator identity.

Testing

SubstraitRelNodeConverterTest.declaredMeasureOutputTypes builds an aggregate whose measures declare output types Calcite would not infer (SUM declared as i64, AVG declared as fp32), asserts the declared types survive Substrait→Calcite, and asserts the full round trip back to Substrait.

🤖 Generated with Claude Code

@rkondakov
rkondakov marked this pull request as draft July 18, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[isthmus][SubstraitToCalcite] Preserve declared aggregate output types

1 participant