添加 FilterRule 以在适配器中下推过滤器时出现问题:RelSubset 无法转换为 HepRelVertex

Problem while adding FilterRule to push down filter in adapter: RelSubset cannot be cast to HepRelVertex

我写了一个适配器并添加了一些规则来下推谓词。

但是,当我添加FilterRule下推过滤器时,在测试中出现了问题:

Caused by: java.lang.ClassCastException: org.apache.calcite.plan.volcano.RelSubset cannot be cast to org.apache.calcite.plan.hep.HepRelVertex
    at org.apache.calcite.plan.hep.HepPlanner.addRelToGraph(HepPlanner.java:840)
    at org.apache.calcite.plan.hep.HepPlanner.addRelToGraph(HepPlanner.java:810)
    at org.apache.calcite.plan.hep.HepPlanner.setRoot(HepPlanner.java:153)
    at org.apache.calcite.tools.Programs.lambda$of[=10=](Programs.java:189)
    at org.apache.calcite.tools.Programs$SequenceProgram.run(Programs.java:347)
    at org.apache.calcite.prepare.Prepare.optimize(Prepare.java:189)
    at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:320)
    at org.apache.calcite.prepare.Prepare.prepareSql(Prepare.java:231)

我尝试调试这个问题,发现错误的节点是: enter image description here

RelSubset中的集合为: enter image description here

错误发生在 HepPlanner.setRoot() 函数中。

我不知道是什么导致了这个错误。其他规则如 ProjectRule 和 LimitRule 运行 很好。如果您需要更多详细信息,请发表评论,我会添加。

我的过滤规则和其他适配器一样:

  private static class IoTDBFilterRule extends ConverterRule {
    private static final IoTDBFilterRule INSTANCE = new IoTDBFilterRule();

    private IoTDBFilterRule() {
      super(LogicalFilter.class, Convention.NONE, IoTDBRel.CONVENTION, "IoTDBFilterRule");
    }

    public RelNode convert(RelNode rel) {
      final LogicalFilter filter = (LogicalFilter) rel;
      final RelTraitSet traitSet = filter.getTraitSet().replace(IoTDBRel.CONVENTION);
      try {
        return new IoTDBFilter(filter.getCluster(), traitSet,
                convert(filter.getInput(), IoTDBRel.CONVENTION), filter.getCondition());
      } catch (LogicalOptimizeException e) {
        throw new AssertionError(e.getMessage());
      }
    }
  }

抱歉,我发现了错误。这是过滤器的 copy 功能。

在VolcanoPlanner中,它选择最便宜的节点作为输入,需要复制一个新节点, copy 函数应该是这样的

public Filter copy(RelTraitSet traitSet, RelNode input, RexNode condition){
    return new Filter(getCluster(), traitSet, input, condition);
}

但是忘记改参数名了,结果是这样的:

public Filter copy(RelTraitSet traitSet, RelNode relNode, RexNode rexNode)

并且在执行复制函数时,它访问过滤器的原点输入作为输入参数,而不是函数定义中的 RelNode。

费了我很多时间才找到这个,请不要像我一样。