[ 
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)

Reply via email to