Skip to content

feat(isthmus): support GROUPING / GROUPING_ID via CASE over the grouping-set-index column #993

Description

@nielspardon

Background

Isthmus already supports GROUPING SETS / ROLLUP / CUBE and GROUP_ID() (see #527 / #565). The one remaining piece of #71 is the SQL GROUPING(expr) / GROUPING_ID(expr, …) aggregate functions, which have no direct Substrait equivalent (there is no grouping function in substrait/extensions/*.yaml).

Because of this, TpcdsQueryTest runs TPC-DS queries 27, 36, 70, 86 via rewritten alternate forms (27a/36a/70a/86a.sql, added in #513) that strip out GROUPING. The original queries do not convert.

Why not add a Substrait grouping function?

That was proposed upstream in substrait#824 but stalled without consensus and was auto-closed as stale. The maintainer-preferred alternative there does not require any spec change: GROUPING can be derived from the extra i32 grouping-set-index ("disambiguation") column that an Aggregate with more than one grouping set already emits, using a CASE expression. See tokoko's worked examples.

Proposed approach (forward: Calcite → Substrait)

Extend the existing project-wrapper in SubstraitRelVisitor.visit(Aggregate) (which already substitutes LITERAL_AGG literals and remaps GROUP_ID onto the disambiguation column). Add a third case: replace each Calcite GROUPING/GROUPING_ID call position with a CASE over the grouping-set-index column, where each arm is the bit/bitmask value computed from which grouping sets contain the referenced field(s).

Open sub-problems

  1. Reverse direction (Substrait → Calcite GROUPING) — reconstructing a GROUPING call from the CASE/index pattern. This is what blocked the earlier attempt.
  2. Duplicate grouping sets edge case (flagged in the PR discussion).

Acceptance

  • GROUPING/GROUPING_ID convert Calcite → Substrait (forward), with round-trip tests.
  • Ideally reverse direction too; if not feasible initially, scope it as a follow-up.
  • Remove 27/36/70/86 from alternateForms in TpcdsQueryTest and delete the *a.sql files once the originals pass.

Remaining work split out from #71.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions