[CALCITE-7614] UNNEST of an unqualified struct-rooted array path fails validation: "Column 's.s' not found"#5033
Open
takaaki7 wants to merge 2 commits into
Open
[CALCITE-7614] UNNEST of an unqualified struct-rooted array path fails validation: "Column 's.s' not found"#5033takaaki7 wants to merge 2 commits into
takaaki7 wants to merge 2 commits into
Conversation
…s validation: "Column 's.s' not found" When the operand of UNNEST is an unqualified identifier whose leading component is a PEEK_FIELDS struct column (e.g. UNNEST(s.arr) where s is a PEEK_FIELDS struct containing array field arr), validation failed with "Column 's.s' not found in table 't'", while the table-qualified form UNNEST(r.s.arr) worked. While DelegatingScope.fullyQualify resolves the qualifying table for the unqualified operand, that resolution re-enters validation of the UNNEST namespace, which rewrites the very same operand identifier's names in place to the fully-qualified form. fullyQualify then re-qualified the already-qualified identifier, duplicating the struct-column segment and producing the doubled "s.s". Fix fullyQualify to qualify a snapshot of the identifier taken before the re-entrant resolution, so the PEEK_FIELDS branch always works from the original names. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Contributor
Author
|
@julianhyde could you review this small |
mihaibudiu
approved these changes
Jun 20, 2026
| int size = identifier.names.size(); | ||
| int i = size - 1; | ||
| // Snapshot: resolution below may rewrite identifier's names in place [CALCITE-7614] | ||
| final SqlIdentifier identifierSnapshot = |
Contributor
There was a problem hiding this comment.
I would call this "originalIdentifier"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Jira Link
CALCITE-7614
Changes Proposed
When the operand of
UNNESTis an unqualified identifier whose leading component is aPEEK_FIELDSstruct column, validation fails:Root cause
DelegatingScope.fullyQualifyqualifies the unqualified operand by first resolving the table that owns thePEEK_FIELDScolumn. That resolution re-enters validation of theUNNESTnamespace, which expands the same operandSqlIdentifierand rewrites its name list in place to the fully-qualified form (SqlValidatorImpl.validateIdentifier→SqlIdentifier.assignNamesFrom). Control then returns tofullyQualify, which re-qualifies the now-already-qualified identifier, prepending the table/struct segment a second time and producing the doubledS.S.The table-qualified form is unaffected because re-qualifying
r.s.arris idempotent.Fix
DelegatingScope.fullyQualifynow snapshots the identifier before the re-entrant resolution and builds the qualifiedPEEK_FIELDSidentifier from that snapshot, so it always works from the original names. The change is a no-op when no re-entrant rewrite occurs. The production change is confined toDelegatingScope.java.Tests
SqlValidatorTest.testUnnestPeekFieldsArrayColumncovering qualified/unqualified ×CROSS JOIN/comma-join.PEEK_FIELDSstruct type containing an array field (Fixture.peekArrayType) and aDEPT_NESTED_PEEK(DEPTNO, S)table in the mock catalog (MockCatalogReaderSimple), since no such column existed.SqlAdvisorTest's expected SALES completion list to include the new table../gradlew :core:testpasses (15649 tests, 0 failed).