public void onMatch(RelOptRuleCall call) { CalcRel calc = (CalcRel) call.getRels()[0]; RexProgram program = calc.getProgram(); final List<RexNode> exprList = program.getExprList(); // Form a list of expressions with sub-expressions fully // expanded. final List<RexNode> expandedExprList = new ArrayList<RexNode>(exprList.size()); final RexShuttle shuttle = new RexShuttle() { public RexNode visitLocalRef(RexLocalRef localRef) { return expandedExprList.get(localRef.getIndex()); } }; for (RexNode expr : exprList) { expandedExprList.add(expr.accept(shuttle)); } if (reduceExpressions(calc, expandedExprList)) { final RexProgramBuilder builder = new RexProgramBuilder( calc.getChild().getRowType(), calc.getCluster().getRexBuilder()); List<RexLocalRef> list = new ArrayList<RexLocalRef>(); for (RexNode expr : expandedExprList) { list.add(builder.registerInput(expr)); } if (program.getCondition() != null) { final int conditionIndex = program.getCondition().getIndex(); final RexNode newConditionExp = expandedExprList.get(conditionIndex); if (newConditionExp.isAlwaysTrue()) { // condition is always TRUE - drop it } else if ((newConditionExp instanceof RexLiteral) || RexUtil.isNullLiteral(newConditionExp, true)) { // condition is always NULL or FALSE - replace calc // with empty call.transformTo(new EmptyRel(calc.getCluster(), calc.getRowType())); return; } else { builder.addCondition(list.get(conditionIndex)); } } int k = 0; for (RexLocalRef projectExpr : program.getProjectList()) { final int index = projectExpr.getIndex(); builder.addProject( list.get(index).getIndex(), program.getOutputRowType().getFieldList().get(k++).getName()); } call.transformTo( new CalcRel( calc.getCluster(), calc.getTraits(), calc.getChild(), calc.getRowType(), builder.getProgram(), calc.getCollationList())); // New plan is absolutely better than old plan. call.getPlanner().setImportance(calc, 0.0); } }
/** Returns whether a {@link RexProgram} contains expressions which require decimal expansion. */ public static boolean requiresDecimalExpansion(RexProgram program, boolean recurse) { final List<RexNode> exprList = program.getExprList(); for (RexNode expr : exprList) { if (requiresDecimalExpansion(expr, recurse)) { return true; } } return false; }
/** * Burrows into a synthetic record and returns the underlying relation which provides the field * called <code>fieldName</code>. */ public JavaRel implementFieldAccess(JavaRelImplementor implementor, String fieldName) { if (!isBoxed()) { return implementor.implementFieldAccess((JavaRel) getChild(), fieldName); } RelDataType type = getRowType(); int field = type.getFieldOrdinal(fieldName); RexLocalRef ref = program.getProjectList().get(field); final int index = ref.getIndex(); return implementor.findRel((JavaRel) this, program.getExprList().get(index)); }
/** * Determines whether it is possible to implement a set of expressions in Java. * * @param program Program to translate * @return whether all expressions in the program can be implemented */ public boolean canTranslate(RelNode rel, RexProgram program) { RexToOJTranslator translator = newTranslator(rel); TranslationTester tester = new TranslationTester(translator, true); final List<RexNode> exprList = program.getExprList(); for (RexNode expr : exprList) { if (!tester.canTranslate(expr)) { return false; } } return true; }