[
https://issues.apache.org/jira/browse/CALCITE-7763?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18118221#comment-18118221
]
Guanyu Chen commented on CALCITE-7763:
--------------------------------------
Thank you for the detailed description about the bug.
If I'm understanding this correctly, the issue stems from the fact that
{{performUnconditionalRewrites}} rewrites child operands *before* it rewrites
the node itself. When the child of a {{SqlOrderBy}} gets rewritten into
something new, the code tries to write the result back via {{call.setOperand(i,
newOperand)}} - but {{SqlOrderBy}} is immutable (final fields, no
{{setOperand}}).
I'm thinking about a potential fix to override {{setOperand}} in {{SqlOrderBy}}
- make it mutable, like {{SqlSelect}} does. However, I'm not sure if it's the
desired way to fix this.
Feel free to let me know what you think and I can help on this.
> "TABLE t ORDER BY c" and "(SELECT ... LIMIT n) ORDER BY c" fail with
> UnsupportedOperationException
> --------------------------------------------------------------------------------------------------
>
> Key: CALCITE-7763
> URL: https://issues.apache.org/jira/browse/CALCITE-7763
> Project: Calcite
> Issue Type: Bug
> Reporter: Julian Hyde
> Priority: Major
>
> {{TABLE t ORDER BY c}} and {{(SELECT ... LIMIT n) ORDER BY c}} fail with
> {{{}UnsupportedOperationException{}}}.
>
> {{SqlOrderBy}} has final fields and does not override
> {{{}setOperand{}}}, so {{SqlCall.setOperand}} throws. But
> {{SqlValidatorImpl.performUnconditionalRewrites}} rewrites operands before
> the node itself and writes the result back with {{{}call.setOperand(i,
> newOperand){}}}. Any query whose {{ORDER BY}} / {{LIMIT}} / {{OFFSET}} /
> {{FETCH}} wraps a node that is itself rewritten — an
> EXPLICIT_TABLE, or a nested {{SqlOrderBy}} from a parenthesized query —
> therefore fails validation with an internal error.
>
> Here is a test case, {{test.iq}}:
> {code:java}
> !use scott
> select * from emp;
> !ok
> table emp order by empno;
> !ok
> table emp limit 5;
> !ok
> (select * from emp limit 5) order by empno;
> !ok
> (select * from emp order by ename) limit 5;
> !ok
> (select * from emp limit 5) order by empno;
> !ok {code}
> The first query succeeds and the rest all throw
> {noformat}
> java.lang.UnsupportedOperationException
> at org.apache.calcite.sql.SqlCall.setOperand(SqlCall.java:71)
> at
> org.apache.calcite.sql.validate.SqlValidatorImpl.performUnconditionalRewrites(SqlValidatorImpl.java:1853)
> {noformat}
> The query "{{{}values (1), (2) order by 1{}}}" survives only because
> {{VALUES}} is explicitly exempted from rewriting.
> Discovered while investigating CALCITE-7761.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)