osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Calcite - add new field to Project via RelOptRule


Hello,

There is a overall task to pushdown an expression from outer select to
nested project (if it has all required dependent fields).

For replace purpose were selected RelOptRule, but when I try to replace
project with a newProject that has on 1 expression more - validation fails:

java.lang.AssertionError: Cannot add expression of different type to set:
set type is RecordType(DOUBLE field1) NOT NULL
expression type is RecordType(DOUBLE field1, DOUBLE newField) NOT NULL
set is
rel#135:LogicalProject.NONE.[](input=HepRelVertex#134,field1=$4,newField=$7)
expression is LogicalProject#187
    at
org.apache.calcite.plan.RelOptUtil.verifyTypeEquivalence(RelOptUtil.java:411)
    at
org.apache.calcite.plan.hep.HepRuleCall.transformTo(HepRuleCall.java:57)
    at
org.apache.calcite.plan.RelOptRuleCall.transformTo(RelOptRuleCall.java:234)

Rule:
    override def onMatch(call: RelOptRuleCall): Unit = {
      val project = _getProject(call)
      logger.info(s"onMatch() DO UPDATE, call=$call, project=$project")

      val rexCall = _formulaContext.formula.rexCall
      val builder = call.builder()

      val newRexNodes = new java.util.ArrayList[RexNode]()
      newRexNodes.addAll(project.getChildExps)
      newRexNodes.add(rexCall)
      val newRexNodeNames =
Seq[String](project.getRowType.getFieldNames.asScala :+
_formulaContext.formula.field: _*)

      val typeBuilder = call.builder().getTypeFactory.builder()
      typeBuilder.addAll(project.getRowType.getFieldList.asScala.map(f =>
new util.AbstractMap.SimpleEntry(f.getName, f.getType)).asJava)
      typeBuilder.add(_formulaContext.formula.field,
_formulaContext.formula.rexCall.`type`)

      val newProject = project.copy(project.getTraitSet, project.getInput,
newRexNodes, typeBuilder.build())

      call.transformTo(newProject)
    }


What is the correct way to update project by adding new expression to it ?

Thanks.