Skip to content

isthmus: the order of an aggregate's grouping sets is not preserved, so the grouping-set index column reports a different set after a round trip #1209

Description

@nielspardon

An aggregate's grouping sets are ordered, and the spec ties meaning to that order: "an aggregate relation with more than one grouping set receives an extra i32 column on the right-hand side. The value of this field will be the zero-based index of the grouping set that yielded the record" (logical relations, spec v0.101.0). Converting to Calcite discards it. Calcite's Aggregate constructor requires its groupSets strictly ordered by ImmutableBitSet.ORDERING, and RelBuilder.aggregate funnels them through an ImmutableSortedMultiset(ImmutableBitSet.COMPARATOR), so whatever order the producer chose is normalized to ascending and the trip back returns the sets sorted.

Measured on main at 7310fc8, for aggregates over foo(a i64, b i64, c string) with no measures:

declared sets   round-tripped sets
{c}, {a}     -> {a}, {c}
{a}, {a,b}   -> {a,b}, {a}

The first converts to LogicalAggregate(group=[{0, 2}], groups=[[{0}, {2}]]) — already sorted, with nothing left to record that the producer declared {c} first. original.equals(roundTripped) is false in both cases, and the round-tripped aggregate's emit mapping comes back as the identity with the grouping-set index dropped.

Because the index column holds the set's zero-based index, reordering the sets changes the value every row reports: rows grouped by c report 0 before the trip and 1 after. A consumer that filters or branches on that column selects the wrong rows.

ComplexAggregateTest.anAggregateOverOutOfOrderGroupingSetsRoundTrips compares only subList(0, 2) of the record types and never getGroupings() or the emit mapping, so it passes while the sets are swapped.

Distinct from #1162, which is the index column's type, and #1182, which is the value the conversion puts in it — this is the set order that value indexes into. Found while reviewing #1161.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions