You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "Weihua Zhang (Jira)" <ji...@apache.org> on 2026/05/23 03:37:00 UTC

[jira] (CALCITE-7543) RelFieldTrimmer should preserve Join nodes instead of rebuilding them through RelBuilder.join

    [ https://issues.apache.org/jira/browse/CALCITE-7543 ]


    Weihua Zhang deleted comment on CALCITE-7543:
    ---------------------------------------

was (Author: JIRAUSER312348):
[~julianhyde] Thanks for the suggestion. I updated the fix to make RelBuilder.join handle this case directly. It now only converts a join with variablesSet to Correlate when that join type can be represented as a Correlate; for RIGHT / FULL / ASOF joins it falls back to creating a regular Join while preserving variablesSet. Therefore rules such as RelFieldTrimmer can continue to use RelBuilder.join instead of bypassing it with join.copy. I also added RelBuilderTest coverage for RIGHT and FULL joins with variablesSet.

>  RelFieldTrimmer should preserve Join nodes instead of rebuilding them through RelBuilder.join
> ----------------------------------------------------------------------------------------------
>
>                 Key: CALCITE-7543
>                 URL: https://issues.apache.org/jira/browse/CALCITE-7543
>             Project: Calcite
>          Issue Type: Bug
>            Reporter: Weihua Zhang
>            Priority: Major
>              Labels: pull-request-available
>
> Problem
> RelFieldTrimmer.trimFields(Join, ...) currently rebuilds a trimmed Join by calling RelBuilder.join(...).
> This is problematic because field trimming is expected to be a shape-preserving transformation. It should trim the inputs, remap the join condition, and preserve the original Join semantics as much as possible.
> However, RelBuilder.join(...) is a high-level construction API. If the original join has a non-empty variablesSet, RelBuilder.join(...) may try to interpret the join as a correlated join construction. For RIGHT and FULL joins, this can trigger the following errors:
> {code:sql}
> !use scott
> SELECT empno
> FROM emp e
> RIGHT JOIN dept d
>   ON e.deptno = d.deptno
>  AND e.sal < (
>     SELECT MAX(e2.sal)
>     FROM emp e2
>     WHERE e2.deptno = d.deptno
>   )
> ORDER BY empno;
> java.sql.SQLException: Error while executing SQL "SELECT empno
> FROM emp e
> RIGHT JOIN dept d
>   ON e.deptno = d.deptno
>  AND e.sal < (
>     SELECT MAX(e2.sal)
>     FROM emp e2
>     WHERE e2.deptno = d.deptno
>   )
> ORDER BY empno": Correlated RIGHT join is not supported
> 	at org.apache.calcite.avatica.Helper.createException(Helper.java:56)
> 	at org.apache.calcite.avatica.Helper.createException(Helper.java:41)
> 	at org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:164)
> 	at org.apache.calcite.avatica.AvaticaStatement.executeQuery(AvaticaStatement.java:228)
> 	at net.hydromatic.quidem.Quidem.checkResult(Quidem.java:317)
> 	at net.hydromatic.quidem.Quidem.access$2600(Quidem.java:54)
> 	at net.hydromatic.quidem.Quidem$ContextImpl.checkResult(Quidem.java:1778)
> 	at net.hydromatic.quidem.Quidem$CheckResultCommand.execute(Quidem.java:985)
> 	at net.hydromatic.quidem.Quidem$CompositeCommand.execute(Quidem.java:1522)
> 	at net.hydromatic.quidem.Quidem.execute(Quidem.java:204)
> 	at org.apache.calcite.test.QuidemTest.checkRun(QuidemTest.java:353)
> 	at org.apache.calcite.test.QuidemTest.test(QuidemTest.java:543)
> 	at org.apache.calcite.test.CoreQuidemTest.main(CoreQuidemTest.java:54)
> Caused by: java.lang.IllegalArgumentException: Correlated RIGHT join is not supported
> 	at org.apache.calcite.tools.RelBuilder.checkIfCorrelated(RelBuilder.java:4493)
> 	at org.apache.calcite.tools.RelBuilder.join(RelBuilder.java:3309)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.trimFields(RelFieldTrimmer.java:1011)
> 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
> 	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
> 	at org.apache.calcite.util.ReflectUtil$2.invoke(ReflectUtil.java:533)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.dispatchTrimFields(RelFieldTrimmer.java:343)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.trimChild(RelFieldTrimmer.java:233)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.trimFields(RelFieldTrimmer.java:555)
> 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
> 	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
> 	at org.apache.calcite.util.ReflectUtil$2.invoke(ReflectUtil.java:533)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.dispatchTrimFields(RelFieldTrimmer.java:343)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.trimChild(RelFieldTrimmer.java:233)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.trimFields(RelFieldTrimmer.java:727)
> 	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
> 	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
> 	at org.apache.calcite.util.ReflectUtil$2.invoke(ReflectUtil.java:533)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.dispatchTrimFields(RelFieldTrimmer.java:343)
> 	at org.apache.calcite.sql2rel.RelFieldTrimmer.trim(RelFieldTrimmer.java:178)
> 	at org.apache.calcite.sql2rel.SqlToRelConverter.trimUnusedFields(SqlToRelConverter.java:584)
> 	at org.apache.calcite.prepare.Prepare.trimUnusedFields(Prepare.java:397)
> 	at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:309)
> 	at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:221)
> 	at org.apache.calcite.prepare.CalcitePrepareImpl.prepare2_(CalcitePrepareImpl.java:675)
> 	at org.apache.calcite.prepare.CalcitePrepareImpl.prepare_(CalcitePrepareImpl.java:526)
> 	at org.apache.calcite.prepare.CalcitePrepareImpl.prepareSql(CalcitePrepareImpl.java:494)
> 	at org.apache.calcite.jdbc.CalciteConnectionImpl.parseQuery(CalciteConnectionImpl.java:246)
> 	at org.apache.calcite.jdbc.CalciteMetaImpl.prepareAndExecute(CalciteMetaImpl.java:654)
> 	at org.apache.calcite.avatica.AvaticaConnection.prepareAndExecuteInternal(AvaticaConnection.java:678)
> 	at org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:157)
> 	... 10 more
> !ok
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)