Skip to content

Streaming aggregation implementation of ARRAY_AGG() - #4463

Open
robert-brunel wants to merge 4 commits into
mainfrom
apple/robert-brunel/array_agg-1
Open

Streaming aggregation implementation of ARRAY_AGG()#4463
robert-brunel wants to merge 4 commits into
mainfrom
apple/robert-brunel/array_agg-1

Conversation

@robert-brunel

@robert-brunel robert-brunel commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

This change implements the ArrayAggValue built-in to evaluate the ARRAY_AGG() aggregate function, as a StreamableAggregateValue (as opposed to an IndexableAggregateValue; indexing would require a new index type or maintainer and is not in scope).

The DISTINCT and ORDER BY clauses are not yet supported. The {RESPECT|IGNORE} NULLS clause is, in principle, supported, but subject to the limitation that nulls in arrays cannot currently be represented (Issue #3646).

The accumulator collects elements into a list and (since OneOfTypedState has no list slot) serializes that list for continuations through a wrapper record with a single repeated field.

@robert-brunel robert-brunel self-assigned this Aug 17, 2026
@robert-brunel robert-brunel added the enhancement New feature or request label Aug 17, 2026
@robert-brunel
robert-brunel force-pushed the apple/robert-brunel/array_agg-1 branch from c4bc382 to 6951560 Compare August 17, 2026 19:10
@robert-brunel
robert-brunel changed the base branch from main to apple/robert-brunel/nullable-arrays-tweaks August 17, 2026 19:14
@robert-brunel robert-brunel changed the title Streaming aggregation support for ARRAY_AGG() Streaming aggregation implementation of ARRAY_AGG() Aug 17, 2026
@robert-brunel
robert-brunel marked this pull request as ready for review August 17, 2026 19:14
@robert-brunel
robert-brunel force-pushed the apple/robert-brunel/array_agg-1 branch from 6951560 to 31f7c37 Compare August 18, 2026 10:14
Base automatically changed from apple/robert-brunel/nullable-arrays-tweaks to main August 18, 2026 18:33
This change implements the `ArrayAggValue` built-in to evaluate the `ARRAY_AGG()` aggregate function, as a `StreamableAggregateValue` (as opposed to an `IndexableAggregateValue`; indexing would require a new index type or maintainer and is not in scope).

The `DISTINCT` and `ORDER BY` clauses are not yet supported. The `{RESPECT|IGNORE} NULLS` clause is, in principle, supported, but subject to the limitation that nulls in arrays cannot currently be represented (Issue #3646).

The accumulator collects elements into a list and (since `OneOfTypedState` has no list slot) serializes that list for continuations through a wrapper record with a single `repeated` field.
@robert-brunel
robert-brunel force-pushed the apple/robert-brunel/array_agg-1 branch from 31f7c37 to 18da484 Compare August 18, 2026 18:33
Type.Record.Field.of(new Type.Array(false, elementType),
Optional.of(NullableArrayTypeUtils.getRepeatedFieldName()))));
final TypeRepository localRepository = TypeRepository.newBuilder().addTypeIfNeeded(wrapperType).build();
return Verify.verifyNotNull(localRepository.getMessageDescriptor(wrapperType));

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.

are you trying to reuse some logics in TypeRepository here? is it possible to extract the logic as some static method and call the static method here instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do you mean the construction of that wrapperType? Except for nullability, it’s indeed the same wrapper type that also gets constructed in Type.java. So I’ve now introduced a NullableArrayTypeUtils.wrapperTypeFor() helper and am calling it from here and from Type.java. What do you think?

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.

adding NullableArrayTypeUtils.wrapperTypeFor() makes sense, but what looks weird to me is the localRepository object, the only reason it is created is that you want to get a messageDescriptor, not that you need a typeRepository, so I'm wondering if it is possible to extract the logic that creates a messageDescriptor into a static method, and call it from here.

Comment thread yaml-tests/src/test/resources/array-agg-tests.yamsql
Brings in the 20-odd commits that landed since this branch was opened, in particular the removal of `RecordQueryStreamingAggregationPlan.SerializationMode` (#4468) and the 4.13.2.0/4.13.3.0 release cuts.

Three resolutions:

* `FDBStreamAggregationTest` — `SerializationMode` is gone, so `partialAggregateArrayAgg()` becomes a plain `@Test` calling the one-argument `build()`, as `main` has already done for the scalar-aggregate tests it was modelled on.
* `array-agg-tests.yamsql` — restore `supported_version: !current_version`. The 4.13.1.0 release cut had literalized it, which claims these tests run against a released server; since the executing form of `ARRAY_AGG()` is unreleased they cannot, and the mixed-version configurations against 4.13.3.0 failed accordingly.
* `array-agg-tests.metrics.{yaml,binpb}` — regenerate. Only task counts and timings move, no explain strings, so this is the planner evolution on `main` rather than a change in these plans.
Brings the branch up to date with the 15 commits that landed since the previous merge, among them the gRPC 1.83.0 bump and the `MetaDataEvolutionValidator` fix for renamed types (#4475). The merge is clean, and no expectations needed adjusting.
@github-actions

Copy link
Copy Markdown

📊 Metrics Diff Analysis Report

Summary

  • New queries: 4
  • Dropped queries: 0
  • Plan changed + metrics changed: 0
  • Plan unchanged + metrics changed: 0
ℹ️ About this analysis

This automated analysis compares query planner metrics between the base branch and this PR. It categorizes changes into:

  • New queries: Queries added in this PR
  • Dropped queries: Queries removed in this PR. These should be reviewed to ensure we are not losing coverage.
  • Plan changed + metrics changed: The query plan has changed along with planner metrics.
  • Metrics only changed: Same plan but different metrics

The last category in particular may indicate planner regressions that should be investigated.

New Queries

Count of new queries by file:

  • yaml-tests/src/test/resources/array-agg-tests.metrics.yaml: 4

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants