hi 丰斌, The exception message has told you the reason:
> Missing conversion is LogicalTableScan[convention: NONE -> ENUMERABLE] This is mostly because your `MyRelOptSchema` returns a `Table` that cannot be transformed to Enumerable Convention. You can refer the code[1] to see why your Table cannot satisfy the requirements. [1] https://github.com/apache/calcite/blob/94dc303ed0a5ccd4e4f972abf7a41f155cbe5546/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableScanRule.java#L38 Julian Hyde <jhyde.apa...@gmail.com> 于2022年6月25日周六 00:40写道: > I had to moderate your message. Can you subscribe to the list so that you > receive updates. > > Julian > > > On Jun 24, 2022, at 09:37, 方丰斌 <8692182...@zju.edu.cn> wrote: > > > > Hey all, > > > > > > > > > > I'm trying to use VolcanoPlanner. I have encountered the following > problems. I hope I can ask for some help. Thank you very much! > > > > Test code: > > > > ````` > > > > VolcanoPlanner planner = new VolcanoPlanner(); > > planner.addRelTraitDef(ConventionTraitDef.INSTANCE); > > > > // Below two lines are important for the planner to use collation > trait and generate merge join > > planner.addRelTraitDef(RelCollationTraitDef.INSTANCE); > > planner.registerAbstractRelationalRules(); > > > > planner.addRule(EnumerableRules.ENUMERABLE_TABLE_SCAN_RULE); > > planner.addRule(EnumerableRules.ENUMERABLE_PROJECT_RULE); > > planner.addRule(CoreRules.PROJECT_TABLE_SCAN); > > > > RelOptCluster cluster = newCluster(planner); > > > > // NOTE:I mock x MyRelOptSchema to ensure that the SQL > verification is successful. > > MyRelOptSchema relOptSchema = new MyRelOptSchema(); > > RelBuilder relBuilder = > RelFactories.LOGICAL_BUILDER.create(cluster, relOptSchema); > > RelNode logicalPlan = relBuilder > > .scan("t1") > > .project(relBuilder.field("attr1")) > > .build(); > > > > RelTraitSet desiredTraits = > > cluster.traitSet().replace(EnumerableConvention.INSTANCE); > > final RelNode newRoot = planner.changeTraits(logicalPlan, > desiredTraits); > > planner.setRoot(newRoot); > > > > RelNode bestExp = planner.findBestExp(); > > System.out.println("Plan is: " + RelOptUtil.toString(bestExp)); > > > > ``` > > > > The exception is: > > > > ``` > > > > org.apache.calcite.plan.RelOptPlanner$CannotPlanException: There are not > enough rules to produce a node with desired properties: > convention=ENUMERABLE, sort=[]. > > Missing conversion is LogicalTableScan[convention: NONE -> ENUMERABLE] > > There is 1 empty subset: rel#7:RelSubset#0.ENUMERABLE.[], the relevant > part of the original plan is as follows > > 0:LogicalTableScan(table=[[t1]]) > > > > Root: rel#5:RelSubset#1.ENUMERABLE.[] > > Original rel: > > LogicalProject(subset=[rel#5:RelSubset#1.ENUMERABLE.[]], attr1=[$0]): > rowcount = 1.0, cumulative cost = {1.0 rows, 1.0 cpu, 0.0 io}, id = 3 > > LogicalTableScan(subset=[rel#2:RelSubset#0.NONE.[]], table=[[t1]]): > rowcount = 1.0, cumulative cost = {0.0 rows, 1.0 cpu, 0.0 io}, id = 0 > > > > Sets: > > Set#0, type: > com.dipeak.disql.query.SimpleSqlTest$MyRelOptSchema$1@67f77f6e > > rel#2:RelSubset#0.NONE.[], best=null > > rel#0:LogicalTableScan.NONE.[](table=[t1]), rowcount=1.0, cumulative > cost={inf} > > rel#7:RelSubset#0.ENUMERABLE.[], best=null > > Set#1, type: RecordType(INTEGER attr1) > > rel#4:RelSubset#1.NONE.[], best=null > > rel#3:LogicalProject.NONE.[](input=RelSubset#2,inputs=0), rowcount=1.0, > cumulative cost={inf} > > rel#5:RelSubset#1.ENUMERABLE.[], best=null > > > rel#6:AbstractConverter.ENUMERABLE.[](input=RelSubset#4,convention=ENUMERABLE,sort=[]), > rowcount=1.0, cumulative cost={inf} > > rel#8:EnumerableProject.ENUMERABLE.[](input=RelSubset#7,inputs=0), > rowcount=1.0, cumulative cost={inf} > > > > Graphviz: > > digraph G { > > root [style=filled,label="Root"]; > > subgraph cluster0{ > > label="Set 0 > com.dipeak.disql.query.SimpleSqlTest$MyRelOptSchema$1@67f77f6e"; > > rel0 [label="rel#0:LogicalTableScan\ntable=[t1]\nrows=1.0, > cost={inf}",shape=box] > > subset2 [label="rel#2:RelSubset#0.NONE.[]"] > > subset7 [label="rel#7:RelSubset#0.ENUMERABLE.[]",color=red] > > } > > subgraph cluster1{ > > label="Set 1 RecordType(INTEGER attr1)"; > > rel3 [label="rel#3:LogicalProject\ninput=RelSubset#2,inputs=0\nrows=1.0, > cost={inf}",shape=box] > > rel6 > [label="rel#6:AbstractConverter\ninput=RelSubset#4,convention=ENUMERABLE,sort=[]\nrows=1.0, > cost={inf}",shape=box] > > rel8 > [label="rel#8:EnumerableProject\ninput=RelSubset#7,inputs=0\nrows=1.0, > cost={inf}",shape=box] > > subset4 [label="rel#4:RelSubset#1.NONE.[]"] > > subset5 [label="rel#5:RelSubset#1.ENUMERABLE.[]"] > > } > > root -> subset5; > > subset2 -> rel0; > > subset4 -> rel3; rel3 -> subset2; > > subset5 -> rel6; rel6 -> subset4; > > subset5 -> rel8; rel8 -> subset7; > > } > > > > at > org.apache.calcite.plan.volcano.RelSubset$CheapestPlanReplacer.visit(RelSubset.java:709) > > at > org.apache.calcite.plan.volcano.RelSubset.buildCheapestPlan(RelSubset.java:390) > > at > org.apache.calcite.plan.volcano.VolcanoPlanner.findBestExp(VolcanoPlanner.java:533) > > > > > > ``` > -- Best, Benchao Li