Skip to content

Conversation

@xiedeyantu
Copy link
Member

@xiedeyantu xiedeyantu marked this pull request as draft December 4, 2025 14:58
}
}

private List<SqlNode> expandRowStar(SqlIdentifier identifier, SelectScope scope) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Once we merge #4662 this should probably be enhanced to support EXCLUDE list in ROW(*) as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

Perhaps we can consider supporting this in the next PR, because there is currently a limitation: the EXCLUDE syntax is only enabled in Babel. Should we also keep ROW(* EXCLUDE(...)) supported in Babel?

Copy link
Contributor

Choose a reason for hiding this comment

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

They both probably need to be in the same parser

Copy link
Contributor

Choose a reason for hiding this comment

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

Doing it in a subsequent PR is fine.

Copy link
Member Author

Choose a reason for hiding this comment

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

They both probably need to be in the same parser

I want to confirm, are you suggesting that the ROW(*) capability should also be fully supported in Babel? I’ve read through all the comments, and it seems this is the only remaining issue to address, right?

Copy link
Contributor

@mihaibudiu mihaibudiu Dec 17, 2025

Choose a reason for hiding this comment

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

it is fine to support ROW(*) in the main parser and ROW(* EXCLUDE) only in Babel

new CallCopyingArgHandler(call, false);
call.getOperator().acceptCall(this, call, true, argHandler);
final SqlNode result = argHandler.result();
final SqlNode result = expandRow(argHandler.result());
Copy link
Contributor

Choose a reason for hiding this comment

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

I find is a bit weird to have expandRow happen as a side-effect of calculatePermuteOffset; maybe this is a sign that the function name should be updated.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have rename expandRow to expandStarInRow.

return node;
}
final SqlValidatorScope scope = getScope();
if (!(scope instanceof SelectScope)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

what happens if the scope is not Select? Will eventually an error be produced?
Or is this the right place to produce the error?

Copy link
Member Author

Choose a reason for hiding this comment

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

I added error here.

}

private void popRowValueStar() {
if (rowValueStarCount > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be false?
If not, maybe this can be an assert.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

LOOKAHEAD(3)
<ROW> {
s = span();
pushRowValueStar();
Copy link
Contributor

Choose a reason for hiding this comment

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

good point about nested ROW constructors.
I wonder what spark does.
It seems that ROW(*, ROW(*)) is legit

Copy link
Member Author

Choose a reason for hiding this comment

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

Pgsql can support this syntax, following:

SELECT ROW(DEPT.*, ROW(DEPT.*)) FROM DEPT;
                            row                            
-----------------------------------------------------------
 (10,ACCOUNTING,"NEW YORK","(10,ACCOUNTING,""NEW YORK"")")
 (20,RESEARCH,DALLAS,"(20,RESEARCH,DALLAS)")
 (30,SALES,CHICAGO,"(30,SALES,CHICAGO)")
 (40,OPERATIONS,BOSTON,"(40,OPERATIONS,BOSTON)")
(4 rows)

It doesn't support ROW(*, ROW(*)). But I think we can support this form.

Copy link
Member Author

Choose a reason for hiding this comment

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

I configured a Spark environment and tested the following SQL statements, all of which were executable.

spark-sql (mydb)> SELECT STRUCT(*) AS row_data FROM dept;
{"deptno":10,"dname":"ACCOUNTING","loc":"NEW YORK"}
{"deptno":40,"dname":"OPERATIONS","loc":"BOSTON"}
{"deptno":20,"dname":"RESEARCH","loc":"DALLAS"}
{"deptno":30,"dname":"SALES","loc":"CHICAGO"}
Time taken: 0.207 seconds, Fetched 4 row(s)
spark-sql (mydb)> SELECT STRUCT(*, STRUCT(*)) AS row_data FROM dept;
{"deptno":10,"dname":"ACCOUNTING","loc":"NEW YORK","col2":{"deptno":10,"dname":"ACCOUNTING","loc":"NEW YORK"}}
{"deptno":40,"dname":"OPERATIONS","loc":"BOSTON","col2":{"deptno":40,"dname":"OPERATIONS","loc":"BOSTON"}}
{"deptno":20,"dname":"RESEARCH","loc":"DALLAS","col2":{"deptno":20,"dname":"RESEARCH","loc":"DALLAS"}}
{"deptno":30,"dname":"SALES","loc":"CHICAGO","col2":{"deptno":30,"dname":"SALES","loc":"CHICAGO"}}
Time taken: 0.103 seconds, Fetched 4 row(s)
spark-sql (mydb)> SELECT STRUCT(*, STRUCT(dept.*)) AS row_data FROM dept;
{"deptno":10,"dname":"ACCOUNTING","loc":"NEW YORK","col2":{"deptno":10,"dname":"ACCOUNTING","loc":"NEW YORK"}}
{"deptno":40,"dname":"OPERATIONS","loc":"BOSTON","col2":{"deptno":40,"dname":"OPERATIONS","loc":"BOSTON"}}
{"deptno":20,"dname":"RESEARCH","loc":"DALLAS","col2":{"deptno":20,"dname":"RESEARCH","loc":"DALLAS"}}
{"deptno":30,"dname":"SALES","loc":"CHICAGO","col2":{"deptno":30,"dname":"SALES","loc":"CHICAGO"}}
Time taken: 0.075 seconds, Fetched 4 row(s)

e = ContextVariable()
|
e = CompoundIdentifier()
|
Copy link
Contributor

Choose a reason for hiding this comment

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

The natural question that follows is about ROW(T.*). But that can be part of a follow-up PR, including perhaps ROW(T.* EXCLUDE(list))

|
e = CompoundIdentifier()
|
LOOKAHEAD({ allowRowValueStar() })
Copy link
Contributor

Choose a reason for hiding this comment

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

didn't know that LOOKAHEAD allows a function call

@xiedeyantu
Copy link
Member Author

This PR was assisted by Copilot. While it basically meets the requirements, the implementation is not optimal and conflicts with #4662. Thank you very much for your review. I will carefully consider these issues and continue with this PR after #4662 is completed.

@xiedeyantu
Copy link
Member Author

Now that #4662 is merged, I plan to restart this work within the next few days.

@xiedeyantu xiedeyantu marked this pull request as ready for review December 17, 2025 14:02
@xiedeyantu xiedeyantu added the LGTM-will-merge-soon Overall PR looks OK. Only minor things left. label Dec 18, 2025
@sonarqubecloud
Copy link

@xiedeyantu xiedeyantu merged commit 1a4b00b into apache:main Dec 19, 2025
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

LGTM-will-merge-soon Overall PR looks OK. Only minor things left.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants