Skip to content

test: add advanced dictionary test - #23483

Merged
kosiew merged 3 commits into
apache:mainfrom
Rich-T-kid:rich-T-kid/advanced-dictionary-aggreation-sqltest
Jul 20, 2026
Merged

test: add advanced dictionary test#23483
kosiew merged 3 commits into
apache:mainfrom
Rich-T-kid:rich-T-kid/advanced-dictionary-aggreation-sqltest

Conversation

@Rich-T-kid

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

follow up PR for #23280

Rationale for this change

see comment #23280 (comment)

What changes are included in this PR?

Adds SQL logic tests to verify that GROUP BY on dictionary-encoded columns resolves on values rather than raw dictionary key integers. The tests use UNION ALL between independently-encoded subqueries (mixing Int32/Int16/Int8 key types and Utf8/LargeUtf8 value types)

Are these changes tested?

the test cover

  • Correct grouping when the same value maps to different keys in different batches
  • No false merging of distinct values that happen to share the same key number
  • Null handling across batches with mismatched key assignments

Are there any user-facing changes?

no

@Rich-T-kid

Copy link
Copy Markdown
ContributorAuthor

cc @kosiew

@github-actionsgithub-actionsBot added the sqllogictest SQL Logic Tests (.slt) label Jul 11, 2026

@kosiewkosiew 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.

@Rich-T-kid
Thanks for working on this. I think the regression test is headed in the right direction, but I don't think it currently exercises the case we want to protect against. In addition, I have one small suggestion to simplify the coverage.

FROM (VALUES ('west'), ('east'), ('west'), (NULL)) AS t(column1)
),
second_batch AS (
SELECT arrow_cast(column1, 'Dictionary(Int16, LargeUtf8)') AS region

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.

I don't think these new regression cases are exercising dictionary grouping at the aggregation boundary.

Because the UNION inputs use different dictionary key/value types, for example Dictionary(Int32, Utf8) unioned with Dictionary(Int16, LargeUtf8) here, the physical plan coerces both branches back to LargeUtf8 before UnionExec and AggregateExec: CAST(CAST(column1 AS Dictionary(...)) AS LargeUtf8).

That means the GROUP BY sees plain strings, so an implementation that incorrectly hashed dictionary key ids would still pass these tests.

Could you construct the inputs using the same dictionary type while varying the dictionary value order instead? Alternatively, if there's another approach, could you verify through the plan or test setup that AggregateExec is actually consuming separate dictionary arrays with different dictionaries?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

🤔 I didn't consider that datafusion would cast them before reaching the aggregation stage. Ive updated the test to use the same key/value types while varying the order.

Comment threaddatafusion/sqllogictest/test_files/dictionary.slt Outdated
@Rich-T-kid

Copy link
Copy Markdown
ContributorAuthor

the test in 4ca86a1
arrow_cast builds the dictionary by encoding values in first-seen order. So:

┌──────────────┬────────┬────────┐
│ batch │ key 0 │ key 1 │
├──────────────┼────────┼────────┤
│ first_batch │ 'west' │ 'east' │
├──────────────┼────────┼────────┤
│ second_batch │ 'east' │ 'west' │
└──────────────┴────────┴────────┘

Key id 0 means 'west' in the first batch but 'east' in the second. A buggy implementation that groups by raw key id would put those together:

so west (group 0) would be seen 6 times while east (group 1) would be seen 2 times. this would be incorrect.
A correct implementation looks up the actual string value for each row and groups by that, producing 4 and 4 regardless of what key id was used in each batch.

@Rich-T-kid
Rich-T-kid requested a review from kosiewJuly 14, 2026 15:24

@kosiewkosiew 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.

@Rich-T-kid

Thanks for the iteration.

Looks 👍 to me

@Rich-T-kid

Copy link
Copy Markdown
ContributorAuthor

thanks @kosiew

@kosiew
kosiew added this pull request to the merge queueJul 20, 2026
Merged via the queue into apache:main with commit 3b1ce16Jul 20, 2026
37 checks passed
kosiew pushed a commit to kosiew/datafusion that referenced this pull request Aug 12, 2026
## Which issue does this PR close?
<!--
We generally require a GitHub issue to be filed for all bug fixes and
enhancements and this helps us generate change logs for our releases.
You can link an issue to this PR using the GitHub syntax. For example
`Closesapache#123` indicates that this PR will close issue apache#123.
-->
follow up PR for apache#23280
## Rationale for this change
see comment
apache#23280 (comment)
<!--
Why are you proposing this change? If this is already explained clearly
in the issue then this section is not needed.
Explaining clearly why changes are proposed helps reviewers understand
your changes and offer better suggestions for fixes.
-->
## What changes are included in this PR?
Adds SQL logic tests to verify that GROUP BY on dictionary-encoded
columns resolves on values rather than raw dictionary key integers. The
tests use UNION ALL between independently-encoded subqueries (mixing
Int32/Int16/Int8 key types and Utf8/LargeUtf8 value types)
<!--
There is no need to duplicate the description in the issue here but it
is sometimes worth providing a summary of the individual changes in this
PR.
-->
## Are these changes tested?
the test cover
- Correct grouping when the same value maps to different keys in
different batches
- No false merging of distinct values that happen to share the same key
number
- Null handling across batches with mismatched key assignments
<!--
We typically require tests for all PRs in order to:
1. Prevent the code from being accidentally broken by subsequent changes
2. Serve as another way to document the expected behavior of the code
If tests are not included in your PR, please explain why (for example,
are they covered by existing tests)?
-->
## Are there any user-facing changes?
no
<!--
If there are user-facing changes then we may require documentation to be
updated before approving the PR.
-->
<!--
If there are any breaking changes to public APIs, please add the `api
change` label.
-->
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sqllogictestSQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@Rich-T-kid@kosiew