Skip to content

[CALCITE-7669] Uncollect should support the Trino semantics of UNNEST - #5118

Merged
mihaibudiu merged 2 commits into
apache:mainfrom
mihaibudiu:issue7669
Aug 2, 2026
Merged

[CALCITE-7669] Uncollect should support the Trino semantics of UNNEST#5118
mihaibudiu merged 2 commits into
apache:mainfrom
mihaibudiu:issue7669

Conversation

@mihaibudiu

Copy link
Copy Markdown
Contributor

Jira Link

CALCITE-7669

Changes Proposed

There are two separate commits, if independent interest. The first commit only strengthens the validator for rejecting UNNEST on the right side of some JOIN operators.

The semantics of the UNNEST operator changes depending on conformance: for Presto/Trino UNNEST(a) where a is a ROW ARRAY produces a single column; for other conformances it produces as many columns as there are fields in ROW.

This PR makes the choice of semantics explicit at all levels of the representation: the Uncollect operator, and the Enumerable representation by adding a new boolean flag to control the behavior. The flag clearly affects type inference too.

This PR is a stand-alone fragment extracted from #5031

@xuzifu666 xuzifu666 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the overall implementation is fine; I've left some comments for reference.

? typeFactory.enforceTypeWithNullability(componentType, true)
RelDataType elementType = componentType.isStruct()
? typeFactory.builder().kind(componentType.getStructKind())
.addAll(componentType.getFieldList()).build()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The return type here is NOT NULL, so the isNullable mentioned above(line 101) isn't actually used in this branch; it might be worth verifying whether this is appropriate.
In Trino, the output columns of UNNEST(array of nullable row) are nullable.

@SuppressWarnings({"rawtypes", "unchecked"})
private static final Function1<List<Object>, Enumerable<Object>> STRUCT_LIST_AS_ENUMERABLE =
a0 -> a0 == null ? Linq4j.emptyEnumerable()
: Linq4j.asEnumerable(a0).select(e -> (Object) ((List) e).toArray());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Arrays containing NULL elements, such as UNNEST(ARRAY[ROW(1,'x'), CAST(NULL AS ROW(...))]), trigger a direct NPE (the SCALAR path avoids this issue as it performs no conversion).
Trino currently produces a row of NULLs for this case.
It is recommended to change the logic to e == null ? null : ... and add a test case that includes NULL elements.

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.

An attempt to fix this bug has revealed some independent problems in RelToLixTranslator, which need to be fixed fix. I will file a separate issue and mark this as draft until the other one is fixed.

Comment thread core/src/main/java/org/apache/calcite/rel/core/Uncollect.java Outdated
@mihaibudiu
mihaibudiu marked this pull request as draft July 27, 2026 23:39
@mihaibudiu

Copy link
Copy Markdown
Contributor Author

Blocked by #5128

Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
@mihaibudiu
mihaibudiu marked this pull request as ready for review August 2, 2026 04:48
@mihaibudiu

Copy link
Copy Markdown
Contributor Author

@xuzifu666 I think that #5128 (merged) has fixed the two problems you have identified, so I have rebased this PR and marked it ready for review.

Signed-off-by: Mihai Budiu <mbudiu@feldera.com>
@sonarqubecloud

sonarqubecloud Bot commented Aug 2, 2026

Copy link
Copy Markdown

@xuzifu666 xuzifu666 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@mihaibudiu
mihaibudiu merged commit 3329471 into apache:main Aug 2, 2026
19 checks passed
@mihaibudiu
mihaibudiu deleted the issue7669 branch August 2, 2026 17:44
@xiedeyantu

Copy link
Copy Markdown
Member

You may have forgotten to squash the commits. Would it be possible to force-update the "main" branch? Since there haven't been any new merges yet, it should be safe to do so.

@mihaibudiu

Copy link
Copy Markdown
Contributor Author

No, I meant this as two separate commits, they have different functions

@xiedeyantu

Copy link
Copy Markdown
Member

I noticed the second commit didn't have the [CALCITE-xxxx] prefix, so I thought you might have forgotten it. If you've confirmed it's fine, then it's good to go.

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.

3 participants