Hi Xiaoying, It would be easier for people to provide feedback if you had a small reproducer available on GitHub where people can actually run your code.
Sooner or later you are gonna bump into queries that cannot be pushed completely into a JDBC endpoint. I don't know your use-case but since you are requesting the result to be in the Enumerable convention maybe you should consider adding the Enumerable rules/operators in your planner to be able to deal with those cases as well. Best, Stamatis On Mon, Mar 28, 2022 at 9:30 PM Xiaoying Wang <[email protected]> wrote: > 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 > > >> > > > > >
