Проблема при добавлении FilterRule для подавления фильтра в адаптере: RelSubset не может быть приведен к 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$0(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)

Я попытался отладить эту проблему и обнаружил, что неправильный узел: введите здесь описание изображения

Набор в RelSubset был: введите здесь описание изображения

И ошибка произошла в функции 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());
      }
    }
  }

person Xiangwei Wei    schedule 07.01.2020    source источник


Ответы (1)


Извините, я нашел ошибку. Это функция 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 в определении функции.

Мне стоило много времени, чтобы найти это, пожалуйста, не делайте так, как я.

person Xiangwei Wei    schedule 08.01.2020