Hey Benchao,
Thank you for your guidance and advice. I am very happy to be able to
develop based on calcite. Thank you very much!
-----原始邮件-----
发件人:"Benchao Li" <[email protected]>
发送时间:2022-06-26 18:20:53 (星期日)
收件人: "方丰斌" <[email protected]>, [email protected]
抄送:
主题: Re: Re: Re: Looking for help: There are not enough rules to produce a node
with desired properties
Hi 丰斌,
Below four kinds of Table can all fit your case.
- ScannableTable
- FilterableTable
- ProjectableFilterableTable
- QueryableTable
Translatable is another different case, it provides a way for you to translate
your table
to your customized TableScan.
If you just want to add your CK table into Calcite, and make it queryable by
Calcite,
you can implement ScannableTable or QueryableTable.
If you want to do more, e.g. filter pushdown or projection pushdown, you can use
FilterableTable or ProjectableFilterableTable.
And if you want to do more complicated works, you need to invent your own
RelNodes
and Rules and translate them to CK queries just like Mongo/Druid Adaptor do. By
doing
this, you can leave other works to Calcite Enumerable convention, which is very
flexible.
BTW, please reply all to the [email protected],
then all the people who subscribed to the ML could see it.
方丰斌 <[email protected]> 于2022年6月26日周日 10:39写道:
Hey Benchao,
I am trying to use the calcite adapter to connect the Clickhouse. So I need
to create CKTable, just like DruidTable(class DruidTable extends AbstractTable
implements TranslatableTable)or InnodbTable(class InnodbTable extends
AbstractQueryableTable implements TranslatableTable), but the classes inherited
by these two tables are different. I'm not sure which is more appropriate. By
looking at the source code comments, I can't get enough information.
-----原始邮件-----
发件人:"Benchao Li" <[email protected]>
发送时间:2022-06-26 09:45:36 (星期日)
收件人: "方丰斌" <[email protected]>
抄送:[email protected]
主题: Re: Re: Looking for help: There are not enough rules to produce a node with
desired properties
I tried to add DDL statements and create a custom table (which inherits
AbstractTable). However, it is obvious that some rules cannot be converted when
CBO is started.
I don't fully understand this question, could you elaborate a little more on
it?
Did you mean that your DDL statement cannot be optimized in Volcano Planner?
Or the query with your customized table created via the DDL cannot be optimized
in Volcano Planner?
方丰斌 <[email protected]> 于2022年6月25日周六 21:48写道:
Thanks for your advice. My mock table inherits AbstractTable, so there is no
convert. I solved the problem according to your suggestion.
BTW:I tried to add DDL statements and create a custom table (which inherits
AbstractTable). However, it is obvious that some rules cannot be converted when
CBO is started. Can you help provide some suggestions? Thank you very much!
-----原始邮件-----
发件人:"Benchao Li" <[email protected]>
发送时间:2022-06-25 20:56:00 (星期六)
收件人:[email protected], [email protected]
抄送:
主题: Re: Looking for help: There are not enough rules to produce a node with
desired properties
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 <[email protected]> 于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, 方丰斌 <[email protected]> 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
--
Best,
Benchao Li
--
Best,
Benchao Li