[ https://issues.apache.org/jira/browse/CALCITE-2667?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16694642#comment-16694642 ]
Piotr Bojko edited comment on CALCITE-2667 at 11/21/18 12:19 PM: ----------------------------------------------------------------- I have found two solutions *Solution 1* This one is based on assumption that SqlToRelConverter.leaves are out of sync with a relational tree when RelBuilder pushes down join conditions (RelOptUtil.pushDownJoinConditions). In such case left or/and right inputs of a join could be merged into new projects. The solution was to resync SqlToRelConverter.leaves with a new merged project. But with this approach next problem occured. As in my previous comment - SqlToRelConverter.convertIdentifier assumes that looking an identifier through inputs based on an offset is the same as looking mentioned through union of inputs and leaves. Such assumption is not correct when in a relational tree would be a project with permutation in its expressions - such case can occur when new merged projects is synced! I have changed this logic a little bit - now identifier is being search through union of inputs and leaves and projected on to inputs (offset is being recalculated to match the proper coordinates in the inputs). However I've come to conclusion that my implementation (the second part) is a little bit naive and it takes only RexInputRefs into consideration when recalculated offset for inputs. Such prototype I've pushed into https://github.com/ptrbojko/calcite/tree/bug/CALCITE-2667 with an example of one failing tests showing RexInputRefs are not enough. *Side note* - I think that SqlToRelConverter.convertIdentifier is very fragile because of the mentioned assumption in its logic. In my honest opinion it should be rewritten, maybe as the proposed approach. See https://github.com/ptrbojko/calcite/tree/bug/CALCITE-2667 for details. *Solution 2* This one is based on assumption that we should prevent merging projects in RelOptUtil.pushDownJoinConditions when merged projects is a leaf in SqlToRelConverter. I've extended then RelBuilder to be configurable and SqlToRelConverter enriching RelBuilder with a check if a project is not a leaf and can be merged. This solution alters expected relational tree. I had to tune some tests which were checking expected plans, because of missing merge. Pull request is here - https://github.com/apache/calcite/pull/931 *Side note*: I've choose the second approach because it does not alter any assumptions and was less invasive. was (Author: ptrbojko): I have found two solutions *Solution 1* This one is based on assumption that SqlToRelConverter.leaves are out of sync with a relational tree when RelBuilder pushes down join conditions (RelOptUtil.pushDownJoinConditions). In such case left or/and right inputs of a join could be merged into new projects. The solution was to resync SqlToRelConverter.leaves with a new merged project. But with this approach next problem occured. As in my previous comment - SqlToRelConverter.convertIdentifier assumes that looking an identifier through inputs based on an offset is the same as looking mentioned through union of inputs and leaves. Such assumption is not correct when in a relational tree would be a project with permutation in its expressions - such case can occur when new merged projects is synced! I have changed this logic a little bit - now identifier is being search through union of inputs and leaves and projected on to inputs (offset is being recalculated to match the proper coordinates in the inputs). However I've come to conclusion that my implementation (the second part) is a little bit naive and it takes only RexInputRefs into consideration when recalculated offset for inputs. Such prototype I've pushed into https://github.com/ptrbojko/calcite/tree/bug/CALCITE-2667 with an example of one failing tests showing RexInputRefs are not enough. *Side note* - I think that SqlToRelConverter.convertIdentifier is very fragile because of the mentioned assumption in its logic. In my honest opinion it should be rewritten, maybe as the proposed approach. See https://github.com/ptrbojko/calcite/tree/bug/CALCITE-2667 for details. *Solution 2* This one is based on assumption that we should prevent merging projects in RelOptUtil.pushDownJoinConditions when merged projects is a leaf in SqlToRelConverter. I've extended then RelBuilder to be configurable and SqlToRelConverter enriching RelBuilder with a check if a project is not a leaf and can be merged. This solution alters expected relational tree. I had to tune some tests which were checking expected plans, because of missing merge. Pull request is here - https://github.com/apache/calcite/pull/931 > sql2rel fails on join between table function and other table > ------------------------------------------------------------ > > Key: CALCITE-2667 > URL: https://issues.apache.org/jira/browse/CALCITE-2667 > Project: Calcite > Issue Type: Bug > Reporter: Piotr Bojko > Assignee: Julian Hyde > Priority: Major > > Bug reproduction is here - > https://github.com/ptrbojko/calcite/tree/bug/CALCITE-2667 > {noformat} > > java.lang.AssertionError: Field ordinal 2 is invalid for type > > 'RecordType(VARCHAR TYPE, VARCHAR CODEVALUE)' > > at > > org.apache.calcite.rex.RexBuilder.makeFieldAccess(RexBuilder.java:188) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter.convertIdentifier(SqlToRelConverter.java:3616) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter.access$2100(SqlToRelConverter.java:215) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.visit(SqlToRelConverter.java:4691) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.visit(SqlToRelConverter.java:3987) > > at org.apache.calcite.sql.SqlIdentifier.accept(SqlIdentifier.java:334) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.convertExpression(SqlToRelConverter.java:4551) > > at > > org.apache.calcite.sql2rel.StandardConvertletTable.lambda$new$9(StandardConvertletTable.java:204) > > at > > org.apache.calcite.sql2rel.SqlNodeToRexConverterImpl.convertCall(SqlNodeToRexConverterImpl.java:63) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.visit(SqlToRelConverter.java:4682) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.visit(SqlToRelConverter.java:3987) > > at org.apache.calcite.sql.SqlCall.accept(SqlCall.java:138) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard.convertExpression(SqlToRelConverter.java:4551) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter.convertSelectList(SqlToRelConverter.java:3830) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter.convertSelectImpl(SqlToRelConverter.java:668) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter.convertSelect(SqlToRelConverter.java:625) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter.convertQueryRecursive(SqlToRelConverter.java:3074) > > at > > org.apache.calcite.sql2rel.SqlToRelConverter.convertQuery(SqlToRelConverter.java:561) > > at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:265) > > at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:231) > > at > > org.apache.calcite.prepare.CalcitePrepareImpl.prepare2_(CalcitePrepareImpl.java:772) > > at > > org.apache.calcite.prepare.CalcitePrepareImpl.prepare_(CalcitePrepareImpl.java:636) > > at > > org.apache.calcite.prepare.CalcitePrepareImpl.prepareSql(CalcitePrepareImpl.java:606) > > at > > org.apache.calcite.jdbc.CalciteConnectionImpl.parseQuery(CalciteConnectionImpl.java:229) > > at > > org.apache.calcite.jdbc.CalciteMetaImpl.prepareAndExecute(CalciteMetaImpl.java:550) > > at > > org.apache.calcite.avatica.AvaticaConnection.prepareAndExecuteInternal(AvaticaConnection.java:675) > > at > > org.apache.calcite.avatica.AvaticaStatement.executeInternal(AvaticaStatement.java:156) > > at > > org.apache.calcite.avatica.AvaticaStatement.executeQuery(AvaticaStatement.java:227) > > at net.hydromatic.quidem.Quidem.checkResult(Quidem.java:322) > > at net.hydromatic.quidem.Quidem.access$2800(Quidem.java:54) > > at > > net.hydromatic.quidem.Quidem$ContextImpl.checkResult(Quidem.java:1747) > > at > > net.hydromatic.quidem.Quidem$CheckResultCommand.execute(Quidem.java:1078) > > at > > net.hydromatic.quidem.Quidem$CompositeCommand.execute(Quidem.java:1548) > > at net.hydromatic.quidem.Quidem.execute(Quidem.java:216) > > at org.apache.calcite.test.QuidemTest.checkRun(QuidemTest.java:161) > > at org.apache.calcite.test.QuidemTest.test(QuidemTest.java:209) > > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > > at > > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > > at > > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > > at java.lang.reflect.Method.invoke(Method.java:498) > > at > > org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) > > at > > org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) > > at > > org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) > > at > > org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) > > at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) > > at > > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) > > at > > org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) > > at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) > > at > > org.apache.maven.surefire.junitcore.pc.Scheduler$1.run(Scheduler.java:410) > > at > > java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) > > at java.util.concurrent.FutureTask.run(FutureTask.java:266) > > at > > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) > > at > > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) > > at java.lang.Thread.run(Thread.java:748) > {noformat} > I think it worked pretty ok on CALCITE-1.17 version -- This message was sent by Atlassian JIRA (v7.6.3#76005)