Hi Benchao, Thank you so much for the help!
This rule looks very promising. I will also try to add this on my side and see whether it works. Best, Xiaoying On Tue, Mar 29, 2022 at 2:24 AM Benchao Li <[email protected]> wrote: > Hi Xiaoying, > > Sorry for the misleading. > (I was debugging this problem in Flink, and I did miss one rule[1] which > did the critical work. > It converts the join condition from `R.key = T.key and S.key = T.key` to > `R.key = S.key and R.key = T.key`. After that, the condition can be pushed > below.) > > Then I think `FilterJoinRule` in Calcite should be improved about this. > I will open a jira issue and try to fix this. > > [1] > > https://github.com/apache/flink/blob/master/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/plan/rules/logical/JoinConditionEqualityTransferRule.scala > > Xiaoying Wang <[email protected]> 于2022年3月29日周二 03:30写道: > > > Hi Julian, > > > > Oh, I see. Thank you for the hint! I just subscribed to the list. > > > > Best, > > Xiaoying > > > > On Mon, Mar 28, 2022 at 11:53 AM Julian Hyde <[email protected]> > > wrote: > > > > > Xiaoying, I know why you didn’t receive the email. Your reply went > > through > > > moderation, which indicates that you are not subscribed to dev@calcite. > > > Please subscribe. > > > > > > > On Mar 28, 2022, at 11:10 AM, Xiaoying Wang < > > [email protected]> > > > wrote: > > > > > > > > Hi Benchao, > > > > > > > > Thank you so much for the reply! I don't know why I didn't receive > the > > > > email but I found your answer at the archive website. > > > > > > > > I tried to add the `JoinConditionPushRule` as you suggested but the > > > > filter cannot be pushed from the second join to the first, and the > > > > code throws the same error. > > > > > > > > It is because the initial state of my query is `(R join1 S) join2 T`, > > > > and the conditions pushed to join2 by `FilterIntoJoinRule` are `R.key > > > > = T.key and S.key = T.key`. Neither `R.key = T.key` nor `S.key = > > > > T.key` can be pushed into join1 because they both require `T.key`. So > > > > both `leftBitmap.contains(inputBits)` and > > > > `rightBitmap.contains(inputBits)` at [1] are false and the condition > > > > cannot be pushed down into the first join. > > > > > > > > Do you think I need to add other rules to solve the problem? (I tried > > > > to add several rules to alter the join order including > > > > `JoinAssociateRule`, `JoinCommuteRule`, > > > > `JoinPushThroughJoinRule.RIGHT/LEFT` but none of them were fired.) > > > > > > > > Best, > > > > > > > > Xiaoying > > > > > > > > [1] > > > > > > https://github.com/apache/calcite/blob/master/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java#L2838 > > > > > > > > > > > > On 2022/03/27 00:41:57 Benchao Li wrote: > > > >> Hi Xiaoying, > > > >> > > > >> You can try to add `JoinConditionPushRule`[1] to solve the problem. > > > >> > > > >> According the rules you provide, you only have `FilterIntoJoinRule`, > > > >> hence the filters will only be push into the second Join. > > > >> The exception you see indicates that the first Join has no > condition, > > > >> and it cannot be handled by ENUMERABLE convention as you can see > > here[2] > > > >> > > > >> [1] > > > >> > > > > > > https://github.com/apache/calcite/blob/master/core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java#L281 > > > >> [2] > > > >> > > > > > > https://github.com/apache/calcite/blob/master/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java#L304 > > > >> > > > >> > > > >> Xiaoying Wang <[email protected]> 于2022年3月26日周六 04:46写道: > > > >> > > > >>> Hi all, > > > >>> > > > >>> > > > >>> I have a query joins three tables (star schema, T is the fact > > > >>> table): "select * from R, S, T where R.key = T.key and S.key = > T.key" > > > and > > > >>> want to use calcite to parse and generate the physical plan. > > > >>> > > > >>> > > > >>> When I pass the query to a volcano planner, it throws the > > > >>> CannotPlanException: > > > >>> > > > >>> > > > >>> Exception in thread "main" > > > >>> org.apache.calcite.plan.RelOptPlanner$CannotPlanException: There > are > > > not > > > >>> enough rules to produce a node with desired properties: > > > >>> convention=ENUMERABLE. > > > >>> > > > >>> Missing conversions are LogicalJoin[convention: NONE -> JDBC.DB1] > (2 > > > cases) > > > >>> > > > >>> There are 2 empty subsets: > > > >>> Empty subset 0: rel#34:RelSubset#2.JDBC.DB1, the relevant part of > the > > > >>> original plan is as follows > > > >>> 14:LogicalJoin(condition=[true], joinType=[inner]) > > > >>> 1:JdbcTableScan(subset=[rel#12:RelSubset#0.JDBC.DB1], table=[[DB1, > > > R]]) > > > >>> 3:JdbcTableScan(subset=[rel#13:RelSubset#1.JDBC.DB1], table=[[DB1, > > > S]]) > > > >>> > > > >>> Empty subset 1: rel#36:RelSubset#4.JDBC.DB1, the relevant part of > the > > > >>> original plan is as follows > > > >>> 17:LogicalJoin(condition=[true], joinType=[inner]) > > > >>> 14:LogicalJoin(subset=[rel#15:RelSubset#2.NONE], condition=[true], > > > >>> joinType=[inner]) > > > >>> 1:JdbcTableScan(subset=[rel#12:RelSubset#0.JDBC.DB1], > table=[[DB1, > > > R]]) > > > >>> 3:JdbcTableScan(subset=[rel#13:RelSubset#1.JDBC.DB1], > table=[[DB1, > > > S]]) > > > >>> 7:JdbcTableScan(subset=[rel#16:RelSubset#3.JDBC.DB1], table=[[DB1, > > > T]]) > > > >>> > > > >>> > > > >>> > > > >>> I tried to rewrite the query, and found that as long as T is not > the > > > last > > > >>> relation (e.g. "select * from T, R, S where R.key = T.key and > S.key = > > > >>> T.key"), there is no error. I think it means that the join order in > > the > > > >>> initial logical plan makes the difference, so I tried to add the > > > >>> JoinAssociateRule. However, I found this rule was not applied by > the > > > >>> optimizer because of the convocation not match. Using the above > > > example, > > > >>> for 17:LogicalJoin the convocation of 14:LogicalJoin and > > > 7:JdbcTableScan > > > >>> are not the same ( at here: > > > >>> > > > >>> > > > > > > https://github.com/apache/calcite/blob/e42b85a45bd16dd58db1546736e653deda5463fe/core/src/main/java/org/apache/calcite/plan/volcano/VolcanoRuleCall.java#L358 > > > >>> ). > > > >>> > > > >>> > > > >>> These are the rules in the planner: > > > >>> > > > >>> [FilterIntoJoinRule, JoinAssociateRule, JoinCommuteRule, > > > >>> JdbcToEnumerableConverterRule(in:JDBC.DB1,out:ENUMERABLE), > > > >>> JdbcJoinRule(in:NONE,out:JDBC.DB1), > > > JdbcProjectRule(in:NONE,out:JDBC.DB1), > > > >>> JdbcFilterRule(in:NONE,out:JDBC.DB1), > > > >>> JdbcAggregateRule(in:NONE,out:JDBC.DB1), > > > >>> JdbcSortRule(in:NONE,out:JDBC.DB1), > > > JdbcUnionRule(in:NONE,out:JDBC.DB1), > > > >>> JdbcIntersectRule(in:NONE,out:JDBC.DB1), > > > >>> JdbcMinusRule(in:NONE,out:JDBC.DB1), > > > >>> JdbcTableModificationRule(in:NONE,out:JDBC.DB1), > > > >>> JdbcValuesRule(in:NONE,out:JDBC.DB1), FilterSetOpTransposeRule, > > > >>> ProjectRemoveRule] > > > >>> > > > >>> > > > >>> I'm very new to Calcite. I'm not sure whether I missed some rules > or > > I > > > have > > > >>> to implement something to make it work. Can anyone help me on this? > > > >>> > > > >>> Best, > > > >>> > > > >>> Xiaoying > > > >>> > > > >> > > > >> > > > >> -- > > > >> > > > >> Best, > > > >> Benchao Li > > > >> > > > > > > > > > > > -- > > Best, > Benchao Li >
