Java源码示例:org.apache.calcite.rex.RexProgramBuilder

示例1
@Override
public void onMatch(RelOptRuleCall call) {
    LogicalCalc calc = call.rel(0);

    // Expand decimals in every expression in this program. If no
    // expression changes, don't apply the rule.
    final RexProgram program = calc.getProgram();
    if (!RexUtil.requiresDecimalExpansion(program, true)) {
        return;
    }

    final RexBuilder rexBuilder = calc.getCluster().getRexBuilder();
    final RexShuttle shuttle = new DecimalShuttle(rexBuilder);
    RexProgramBuilder programBuilder = RexProgramBuilder.create(rexBuilder, calc.getInput().getRowType(),
            program.getExprList(), program.getProjectList(), program.getCondition(), program.getOutputRowType(),
            shuttle, true);

    final RexProgram newProgram = programBuilder.getProgram();
    LogicalCalc newCalc = LogicalCalc.create(calc.getInput(), newProgram);
    call.transformTo(newCalc);
}
 
示例2
public void onMatch(RelOptRuleCall call) {
  final Filter topFilter = call.rel(0);
  final Filter bottomFilter = call.rel(1);

  // use RexPrograms to merge the two FilterRels into a single program
  // so we can convert the two LogicalFilter conditions to directly
  // reference the bottom LogicalFilter's child
  RexBuilder rexBuilder = topFilter.getCluster().getRexBuilder();
  RexProgram bottomProgram = createProgram(bottomFilter);
  RexProgram topProgram = createProgram(topFilter);

  RexProgram mergedProgram = RexProgramBuilder.mergePrograms(topProgram, bottomProgram, rexBuilder);

  RexNode newCondition = mergedProgram.expandLocalRef(mergedProgram.getCondition());

  final RelBuilder relBuilder = call.builder();
  relBuilder.push(bottomFilter.getInput()).filter(newCondition);

  call.transformTo(relBuilder.build());
}
 
示例3
public void onMatch(RelOptRuleCall call) {
  final EnumerableFilter filter = call.rel(0);
  final RelNode input = filter.getInput();

  // Create a program containing a filter.
  final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
  final RelDataType inputRowType = input.getRowType();
  final RexProgramBuilder programBuilder =
      new RexProgramBuilder(inputRowType, rexBuilder);
  programBuilder.addIdentity();
  programBuilder.addCondition(filter.getCondition());
  final RexProgram program = programBuilder.getProgram();

  final EnumerableCalc calc = EnumerableCalc.create(input, program);
  call.transformTo(calc);
}
 
示例4
public void onMatch(RelOptRuleCall call) {
  final Filter topFilter = call.rel(0);
  final Filter bottomFilter = call.rel(1);

  // use RexPrograms to merge the two FilterRels into a single program
  // so we can convert the two LogicalFilter conditions to directly
  // reference the bottom LogicalFilter's child
  RexBuilder rexBuilder = topFilter.getCluster().getRexBuilder();
  RexProgram bottomProgram = createProgram(bottomFilter);
  RexProgram topProgram = createProgram(topFilter);

  RexProgram mergedProgram =
      RexProgramBuilder.mergePrograms(
          topProgram,
          bottomProgram,
          rexBuilder);

  RexNode newCondition =
      mergedProgram.expandLocalRef(
          mergedProgram.getCondition());

  final RelBuilder relBuilder = call.builder();
  relBuilder.push(bottomFilter.getInput())
      .filter(newCondition);

  call.transformTo(relBuilder.build());
}
 
示例5
/**
 * Creates a RexProgram corresponding to a LogicalFilter
 *
 * @param filterRel the LogicalFilter
 * @return created RexProgram
 */
private RexProgram createProgram(Filter filterRel) {
  RexProgramBuilder programBuilder =
      new RexProgramBuilder(
          filterRel.getRowType(),
          filterRel.getCluster().getRexBuilder());
  programBuilder.addIdentity();
  programBuilder.addCondition(filterRel.getCondition());
  return programBuilder.getProgram();
}
 
示例6
public void onMatch(RelOptRuleCall call) {
  final LogicalFilter filter = call.rel(0);
  final LogicalCalc calc = call.rel(1);

  // Don't merge a filter onto a calc which contains windowed aggregates.
  // That would effectively be pushing a multiset down through a filter.
  // We'll have chance to merge later, when the over is expanded.
  if (calc.getProgram().containsAggs()) {
    return;
  }

  // Create a program containing the filter.
  final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
  final RexProgramBuilder progBuilder =
      new RexProgramBuilder(
          calc.getRowType(),
          rexBuilder);
  progBuilder.addIdentity();
  progBuilder.addCondition(filter.getCondition());
  RexProgram topProgram = progBuilder.getProgram();
  RexProgram bottomProgram = calc.getProgram();

  // Merge the programs together.
  RexProgram mergedProgram =
      RexProgramBuilder.mergePrograms(
          topProgram,
          bottomProgram,
          rexBuilder);
  final LogicalCalc newCalc =
      LogicalCalc.create(calc.getInput(), mergedProgram);
  call.transformTo(newCalc);
}
 
示例7
public void rewriteRel(LogicalCalc rel) {
    // Translate the child.
    final RelNode newInput = getNewForOldRel(rel.getInput());

    final RelOptCluster cluster = rel.getCluster();
    RexProgramBuilder programBuilder = new RexProgramBuilder(newInput.getRowType(), cluster.getRexBuilder());

    // Convert the common expressions.
    final RexProgram program = rel.getProgram();
    final RewriteRexShuttle shuttle = new RewriteRexShuttle();
    for (RexNode expr : program.getExprList()) {
        programBuilder.registerInput(expr.accept(shuttle));
    }

    // Convert the projections.
    final List<Pair<RexNode, String>> flattenedExpList = new ArrayList<>();
    List<String> fieldNames = rel.getRowType().getFieldNames();
    flattenProjections(new RewriteRexShuttle(), program.getProjectList(), fieldNames, "", flattenedExpList);

    // Register each of the new projections.
    for (Pair<RexNode, String> flattenedExp : flattenedExpList) {
        programBuilder.addProject(flattenedExp.left, flattenedExp.right);
    }

    // Translate the condition.
    final RexLocalRef conditionRef = program.getCondition();
    if (conditionRef != null) {
        final Ord<RelDataType> newField = getNewFieldForOldInput(conditionRef.getIndex());
        programBuilder.addCondition(RexBuilder.getRexFactory().makeInputRef(newField.i, newField.e));
    }

    RexProgram newProgram = programBuilder.getProgram();

    // Create a new calc relational expression.
    LogicalCalc newRel = LogicalCalc.create(newInput, newProgram);
    setNewForOldRel(rel, newRel);
}
 
示例8
public void onMatch(RelOptRuleCall call) {
    Filter topFilter = call.rel(0);
    Filter bottomFilter = call.rel(1);

    // use RexPrograms to merge the two FilterRels into a single program
    // so we can convert the two FilterRel conditions to directly
    // reference the bottom FilterRel's child
    RexBuilder rexBuilder = topFilter.getCluster().getRexBuilder();
    RexProgram bottomProgram = createProgram(bottomFilter);
    RexProgram topProgram = createProgram(topFilter);

    RexProgram mergedProgram =
        RexProgramBuilder.mergePrograms(
            topProgram,
            bottomProgram,
            rexBuilder);

    RexNode newCondition =
        mergedProgram.expandLocalRef(
            mergedProgram.getCondition());

//    if(!RexUtil.isFlat(newCondition)){
//      RexCall newCall = (RexCall) newCondition;
//      newCondition = rexBuilder.makeFlatCall( newCall.getOperator(), newCall.getOperands());
//    }

    Filter newFilterRel =
        (Filter) filterFactory.createFilter(
            bottomFilter.getInput(),
            RexUtil.flatten(rexBuilder, newCondition));

    call.transformTo(newFilterRel);
  }
 
示例9
/**
 * Creates a RexProgram corresponding to a LogicalFilter
 *
 * @param filterRel the LogicalFilter
 * @return created RexProgram
 */
private RexProgram createProgram(Filter filterRel) {
  RexProgramBuilder programBuilder =
      new RexProgramBuilder(
          filterRel.getRowType(),
          filterRel.getCluster().getRexBuilder());
  programBuilder.addIdentity();
  programBuilder.addCondition(filterRel.getCondition());
  return programBuilder.getProgram();
}
 
示例10
private String compile(RexBuilder rexBuilder, List<RexNode> constExps,
    RexToLixTranslator.InputGetter getter, RelDataType rowType) {
  final RexProgramBuilder programBuilder =
      new RexProgramBuilder(rowType, rexBuilder);
  for (RexNode node : constExps) {
    programBuilder.addProject(
        node, "c" + programBuilder.getProjectList().size());
  }
  final JavaTypeFactoryImpl javaTypeFactory =
      new JavaTypeFactoryImpl(rexBuilder.getTypeFactory().getTypeSystem());
  final BlockBuilder blockBuilder = new BlockBuilder();
  final ParameterExpression root0_ =
      Expressions.parameter(Object.class, "root0");
  final ParameterExpression root_ = DataContext.ROOT;
  blockBuilder.add(
      Expressions.declare(
          Modifier.FINAL, root_,
          Expressions.convert_(root0_, DataContext.class)));
  final SqlConformance conformance = SqlConformanceEnum.HIVE;
  final RexProgram program = programBuilder.getProgram();
  final List<Expression> expressions =
      RexToLixTranslator.translateProjects(program, javaTypeFactory,
          conformance, blockBuilder, null, root_, getter, null);
  blockBuilder.add(
      Expressions.return_(null,
          Expressions.newArrayInit(Object[].class, expressions)));
  final MethodDeclaration methodDecl =
      Expressions.methodDecl(Modifier.PUBLIC, Object[].class,
          BuiltInMethod.FUNCTION1_APPLY.method.getName(),
          ImmutableList.of(root0_), blockBuilder.toBlock());
  String code = Expressions.toString(methodDecl);
  if (CalcitePrepareImpl.DEBUG) {
    Util.debugCode(System.out, code);
  }
  return code;
}
 
示例11
@Override
public EnumerableRel implementEnumerable(List<EnumerableRel> inputs) {
    // keep it for having clause
    RexBuilder rexBuilder = getCluster().getRexBuilder();
    RelDataType inputRowType = getInput().getRowType();
    RexProgramBuilder programBuilder = new RexProgramBuilder(inputRowType, rexBuilder);
    programBuilder.addIdentity();
    programBuilder.addCondition(this.condition);
    RexProgram program = programBuilder.getProgram();

    return new EnumerableCalc(getCluster(), getCluster().traitSetOf(EnumerableConvention.INSTANCE), //
            sole(inputs), program);
}
 
示例12
/**
 * Creates a RexProgram corresponding to a LogicalFilter
 *
 * @param filterRel
 *          the LogicalFilter
 * @return created RexProgram
 */
private RexProgram createProgram(Filter filterRel) {
  RexProgramBuilder programBuilder = new RexProgramBuilder(filterRel.getRowType(),
      filterRel.getCluster().getRexBuilder());
  programBuilder.addIdentity();
  programBuilder.addCondition(filterRel.getCondition());
  return programBuilder.getProgram();
}
 
示例13
/**
 * Create quasi-Java expression from given {@link RexNode}
 *
 * @param node Expression in the form of {@link RexNode}
 * @param inputRowType Input Data type to expression in the form of {@link RelDataType}
 * @param outputRowType Output data type of expression in the form of {@link RelDataType}
 *
 * @return Returns quasi-Java expression
 */
public String getExpression(RexNode node, RelDataType inputRowType, RelDataType outputRowType)
{
  final RexProgramBuilder programBuilder = new RexProgramBuilder(inputRowType, rexBuilder);
  programBuilder.addProject(node, null);
  final RexProgram program = programBuilder.getProgram();

  final BlockBuilder builder = new BlockBuilder();
  final JavaTypeFactory javaTypeFactory = (JavaTypeFactory)rexBuilder.getTypeFactory();

  final RexToLixTranslator.InputGetter inputGetter = new RexToLixTranslator.InputGetterImpl(ImmutableList
      .of(Pair.<Expression, PhysType>of(Expressions.variable(Object[].class, "inputValues"),
      PhysTypeImpl.of(javaTypeFactory, inputRowType, JavaRowFormat.ARRAY, false))));
  final Function1<String, RexToLixTranslator.InputGetter> correlates =
      new Function1<String, RexToLixTranslator.InputGetter>()
    {
      public RexToLixTranslator.InputGetter apply(String a0)
      {
        throw new UnsupportedOperationException();
      }
    };

  final List<Expression> list = RexToLixTranslator.translateProjects(program, javaTypeFactory, builder,
      PhysTypeImpl.of(javaTypeFactory, outputRowType, JavaRowFormat.ARRAY, false), null, inputGetter, correlates);

  for (int i = 0; i < list.size(); i++) {
    Statement statement = Expressions.statement(list.get(i));
    builder.add(statement);
  }

  return finalizeExpression(builder.toBlock(), inputRowType);
}
 
示例14
public BlockStatement compileToBlock(List<RexNode> nodes, RelDataType inputRowType) {
  final RexProgramBuilder programBuilder =
      new RexProgramBuilder(inputRowType, rexBuilder);
  for (RexNode node : nodes) {
    programBuilder.addProject(node, null);
  }

  return compileToBlock(programBuilder.getProgram());
}
 
示例15
public String compile(List<RexNode> nodes, RelDataType inputRowType, String className) {
  final RexProgramBuilder programBuilder =
          new RexProgramBuilder(inputRowType, rexBuilder);
  for (RexNode node : nodes) {
    programBuilder.addProject(node, null);
  }

  return compile(programBuilder.getProgram(), className);
}
 
示例16
@Override
public EnumerableRel implementEnumerable(List<EnumerableRel> inputs) {
    // keep it for having clause
    RexBuilder rexBuilder = getCluster().getRexBuilder();
    RelDataType inputRowType = getInput().getRowType();
    RexProgramBuilder programBuilder = new RexProgramBuilder(inputRowType, rexBuilder);
    programBuilder.addIdentity();
    programBuilder.addCondition(this.condition);
    RexProgram program = programBuilder.getProgram();

    return new EnumerableCalc(getCluster(), getCluster().traitSetOf(EnumerableConvention.INSTANCE), //
            sole(inputs), program);
}
 
示例17
private FlinkLogicalCalc createTopCalc(
	int primitiveLeftFieldCount,
	RexBuilder rexBuilder,
	ArrayBuffer<RexNode> extractedRexNodes,
	RelDataType calcRowType,
	FlinkLogicalCorrelate newCorrelate) {
	RexProgram rexProgram = new RexProgramBuilder(newCorrelate.getRowType(), rexBuilder).getProgram();
	int offset = extractedRexNodes.size() + primitiveLeftFieldCount;

	// extract correlate output RexNode.
	List<RexNode> newTopCalcProjects = rexProgram
		.getExprList()
		.stream()
		.filter(x -> x instanceof RexInputRef)
		.filter(x -> {
			int index = ((RexInputRef) x).getIndex();
			return index < primitiveLeftFieldCount || index >= offset;
		})
		.collect(Collectors.toList());

	return new FlinkLogicalCalc(
		newCorrelate.getCluster(),
		newCorrelate.getTraitSet(),
		newCorrelate,
		RexProgram.create(
			newCorrelate.getRowType(),
			newTopCalcProjects,
			null,
			calcRowType,
			rexBuilder));
}
 
示例18
private FlinkLogicalCalc createTopCalc(
	int primitiveLeftFieldCount,
	RexBuilder rexBuilder,
	ArrayBuffer<RexNode> extractedRexNodes,
	RelDataType calcRowType,
	FlinkLogicalCorrelate newCorrelate) {
	RexProgram rexProgram = new RexProgramBuilder(newCorrelate.getRowType(), rexBuilder).getProgram();
	int offset = extractedRexNodes.size() + primitiveLeftFieldCount;

	// extract correlate output RexNode.
	List<RexNode> newTopCalcProjects = rexProgram
		.getExprList()
		.stream()
		.filter(x -> x instanceof RexInputRef)
		.filter(x -> {
			int index = ((RexInputRef) x).getIndex();
			return index < primitiveLeftFieldCount || index >= offset;
		})
		.collect(Collectors.toList());

	return new FlinkLogicalCalc(
		newCorrelate.getCluster(),
		newCorrelate.getTraitSet(),
		newCorrelate,
		RexProgram.create(
			newCorrelate.getRowType(),
			newTopCalcProjects,
			null,
			calcRowType,
			rexBuilder));
}
 
示例19
public void onMatch(RelOptRuleCall call) {
  final LogicalFilter filter = call.rel(0);
  final LogicalCalc calc = call.rel(1);

  // Don't merge a filter onto a calc which contains windowed aggregates.
  // That would effectively be pushing a multiset down through a filter.
  // We'll have chance to merge later, when the over is expanded.
  if (calc.getProgram().containsAggs()) {
    return;
  }

  // Create a program containing the filter.
  final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
  final RexProgramBuilder progBuilder =
      new RexProgramBuilder(
          calc.getRowType(),
          rexBuilder);
  progBuilder.addIdentity();
  progBuilder.addCondition(filter.getCondition());
  RexProgram topProgram = progBuilder.getProgram();
  RexProgram bottomProgram = calc.getProgram();

  // Merge the programs together.
  RexProgram mergedProgram =
      RexProgramBuilder.mergePrograms(
          topProgram,
          bottomProgram,
          rexBuilder);
  final LogicalCalc newCalc =
      LogicalCalc.create(calc.getInput(), mergedProgram);
  call.transformTo(newCalc);
}
 
示例20
public void onMatch(RelOptRuleCall call) {
  LogicalCalc calc = call.rel(0);

  // Expand decimals in every expression in this program. If no
  // expression changes, don't apply the rule.
  final RexProgram program = calc.getProgram();
  if (!RexUtil.requiresDecimalExpansion(program, true)) {
    return;
  }

  final RexBuilder rexBuilder = calc.getCluster().getRexBuilder();
  final RexShuttle shuttle = new DecimalShuttle(rexBuilder);
  RexProgramBuilder programBuilder =
      RexProgramBuilder.create(
          rexBuilder,
          calc.getInput().getRowType(),
          program.getExprList(),
          program.getProjectList(),
          program.getCondition(),
          program.getOutputRowType(),
          shuttle,
          true);

  final RexProgram newProgram = programBuilder.getProgram();
  LogicalCalc newCalc = LogicalCalc.create(calc.getInput(), newProgram);
  call.transformTo(newCalc);
}
 
示例21
/** Returns a predicate expression based on a join condition. **/
static Expression generatePredicate(
    EnumerableRelImplementor implementor,
    RexBuilder rexBuilder,
    RelNode left,
    RelNode right,
    PhysType leftPhysType,
    PhysType rightPhysType,
    RexNode condition) {
  final BlockBuilder builder = new BlockBuilder();
  final ParameterExpression left_ =
      Expressions.parameter(leftPhysType.getJavaRowType(), "left");
  final ParameterExpression right_ =
      Expressions.parameter(rightPhysType.getJavaRowType(), "right");
  final RexProgramBuilder program =
      new RexProgramBuilder(
          implementor.getTypeFactory().builder()
              .addAll(left.getRowType().getFieldList())
              .addAll(right.getRowType().getFieldList())
              .build(),
          rexBuilder);
  program.addCondition(condition);
  builder.add(
      Expressions.return_(null,
          RexToLixTranslator.translateCondition(program.getProgram(),
              implementor.getTypeFactory(),
              builder,
              new RexToLixTranslator.InputGetterImpl(
                  ImmutableList.of(Pair.of(left_, leftPhysType),
                      Pair.of(right_, rightPhysType))),
              implementor.allCorrelateVariables,
              implementor.getConformance())));
  return Expressions.lambda(Predicate2.class, builder.toBlock(), left_, right_);
}
 
示例22
@Test void testCalc() {
  final FrameworkConfig config = RelBuilderTest.config().build();
  final RelBuilder builder = RelBuilder.create(config);
  final RexBuilder rexBuilder = builder.getRexBuilder();
  final LogicalTableScan scan = (LogicalTableScan) builder.scan("EMP").build();
  final RexProgramBuilder programBuilder =
      new RexProgramBuilder(scan.getRowType(), rexBuilder);
  final RelDataTypeField field = scan.getRowType().getField("SAL", false, false);
  programBuilder.addIdentity();
  programBuilder.addCondition(
      rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN,
          new RexInputRef(field.getIndex(), field.getType()),
          builder.literal(10)));
  final LogicalCalc calc = LogicalCalc.create(scan, programBuilder.getProgram());
  String relJson = RelOptUtil.dumpPlan("", calc,
      SqlExplainFormat.JSON, SqlExplainLevel.EXPPLAN_ATTRIBUTES);
  String s =
      Frameworks.withPlanner((cluster, relOptSchema, rootSchema) -> {
        final RelJsonReader reader = new RelJsonReader(
            cluster, getSchema(calc), rootSchema);
        RelNode node;
        try {
          node = reader.read(relJson);
        } catch (IOException e) {
          throw TestUtil.rethrow(e);
        }
        return RelOptUtil.dumpPlan("", node, SqlExplainFormat.TEXT,
            SqlExplainLevel.EXPPLAN_ATTRIBUTES);
      });
  final String expected =
      "LogicalCalc(expr#0..7=[{inputs}], expr#8=[10], expr#9=[>($t5, $t8)],"
          + " proj#0..7=[{exprs}], $condition=[$t9])\n"
          + "  LogicalTableScan(table=[[scott, EMP]])\n";
  assertThat(s, isLinux(expected));
}
 
示例23
public void onMatch(RelOptRuleCall call) {
  final LogicalProject project = call.rel(0);
  final LogicalCalc calc = call.rel(1);

  // Don't merge a project which contains windowed aggregates onto a
  // calc. That would effectively be pushing a windowed aggregate down
  // through a filter. Transform the project into an identical calc,
  // which we'll have chance to merge later, after the over is
  // expanded.
  final RelOptCluster cluster = project.getCluster();
  RexProgram program =
      RexProgram.create(
          calc.getRowType(),
          project.getProjects(),
          null,
          project.getRowType(),
          cluster.getRexBuilder());
  if (RexOver.containsOver(program)) {
    LogicalCalc projectAsCalc = LogicalCalc.create(calc, program);
    call.transformTo(projectAsCalc);
    return;
  }

  // Create a program containing the project node's expressions.
  final RexBuilder rexBuilder = cluster.getRexBuilder();
  final RexProgramBuilder progBuilder =
      new RexProgramBuilder(
          calc.getRowType(),
          rexBuilder);
  for (Pair<RexNode, String> field : project.getNamedProjects()) {
    progBuilder.addProject(field.left, field.right);
  }
  RexProgram topProgram = progBuilder.getProgram();
  RexProgram bottomProgram = calc.getProgram();

  // Merge the programs together.
  RexProgram mergedProgram =
      RexProgramBuilder.mergePrograms(
          topProgram,
          bottomProgram,
          rexBuilder);
  final LogicalCalc newCalc =
      LogicalCalc.create(calc.getInput(), mergedProgram);
  call.transformTo(newCalc);
}
 
示例24
/**
 * Pulls the project above the semijoin and returns the resulting semijoin
 * condition. As a result, the semijoin condition should be modified such
 * that references to the LHS of a semijoin should now reference the
 * children of the project that's on the LHS.
 *
 * @param project  LogicalProject on the LHS of the semijoin
 * @param semiJoin the semijoin
 * @return the modified semijoin condition
 */
private RexNode adjustCondition(LogicalProject project, SemiJoin semiJoin) {
  // create two RexPrograms -- the bottom one representing a
  // concatenation of the project and the RHS of the semijoin and the
  // top one representing the semijoin condition

  RexBuilder rexBuilder = project.getCluster().getRexBuilder();
  RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
  RelNode rightChild = semiJoin.getRight();

  // for the bottom RexProgram, the input is a concatenation of the
  // child of the project and the RHS of the semijoin
  RelDataType bottomInputRowType =
      SqlValidatorUtil.deriveJoinRowType(
          project.getInput().getRowType(),
          rightChild.getRowType(),
          JoinRelType.INNER,
          typeFactory,
          null,
          semiJoin.getSystemFieldList());
  RexProgramBuilder bottomProgramBuilder =
      new RexProgramBuilder(bottomInputRowType, rexBuilder);

  // add the project expressions, then add input references for the RHS
  // of the semijoin
  for (Pair<RexNode, String> pair : project.getNamedProjects()) {
    bottomProgramBuilder.addProject(pair.left, pair.right);
  }
  int nLeftFields = project.getInput().getRowType().getFieldCount();
  List<RelDataTypeField> rightFields =
      rightChild.getRowType().getFieldList();
  int nRightFields = rightFields.size();
  for (int i = 0; i < nRightFields; i++) {
    final RelDataTypeField field = rightFields.get(i);
    RexNode inputRef =
        rexBuilder.makeInputRef(
            field.getType(), i + nLeftFields);
    bottomProgramBuilder.addProject(inputRef, field.getName());
  }
  RexProgram bottomProgram = bottomProgramBuilder.getProgram();

  // input rowtype into the top program is the concatenation of the
  // project and the RHS of the semijoin
  RelDataType topInputRowType =
      SqlValidatorUtil.deriveJoinRowType(
          project.getRowType(),
          rightChild.getRowType(),
          JoinRelType.INNER,
          typeFactory,
          null,
          semiJoin.getSystemFieldList());
  RexProgramBuilder topProgramBuilder =
      new RexProgramBuilder(
          topInputRowType,
          rexBuilder);
  topProgramBuilder.addIdentity();
  topProgramBuilder.addCondition(semiJoin.getCondition());
  RexProgram topProgram = topProgramBuilder.getProgram();

  // merge the programs and expand out the local references to form
  // the new semijoin condition; it now references a concatenation of
  // the project's child and the RHS of the semijoin
  RexProgram mergedProgram =
      RexProgramBuilder.mergePrograms(
          topProgram,
          bottomProgram,
          rexBuilder);

  return mergedProgram.expandLocalRef(
      mergedProgram.getCondition());
}
 
示例25
/**
 * Pulls the project above the semi/anti join and returns the resulting semi/anti join
 * condition. As a result, the semi/anti join condition should be modified such
 * that references to the LHS of a semi/anti join should now reference the
 * children of the project that's on the LHS.
 *
 * @param project LogicalProject on the LHS of the semi/anti join
 * @param join the semi/anti join
 * @return the modified semi/anti join condition
 */
private RexNode adjustCondition(LogicalProject project, Join join) {
	// create two RexPrograms -- the bottom one representing a
	// concatenation of the project and the RHS of the semi/anti join and the
	// top one representing the semi/anti join condition

	RexBuilder rexBuilder = project.getCluster().getRexBuilder();
	RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
	RelNode rightChild = join.getRight();

	// for the bottom RexProgram, the input is a concatenation of the
	// child of the project and the RHS of the semi/anti join
	RelDataType bottomInputRowType =
			SqlValidatorUtil.deriveJoinRowType(
					project.getInput().getRowType(),
					rightChild.getRowType(),
					JoinRelType.INNER,
					typeFactory,
					null,
					join.getSystemFieldList());
	RexProgramBuilder bottomProgramBuilder =
			new RexProgramBuilder(bottomInputRowType, rexBuilder);

	// add the project expressions, then add input references for the RHS
	// of the semi/anti join
	for (Pair<RexNode, String> pair : project.getNamedProjects()) {
		bottomProgramBuilder.addProject(pair.left, pair.right);
	}
	int nLeftFields = project.getInput().getRowType().getFieldCount();
	List<RelDataTypeField> rightFields =
			rightChild.getRowType().getFieldList();
	int nRightFields = rightFields.size();
	for (int i = 0; i < nRightFields; i++) {
		final RelDataTypeField field = rightFields.get(i);
		RexNode inputRef =
				rexBuilder.makeInputRef(
						field.getType(), i + nLeftFields);
		bottomProgramBuilder.addProject(inputRef, field.getName());
	}
	RexProgram bottomProgram = bottomProgramBuilder.getProgram();

	// input rowtype into the top program is the concatenation of the
	// project and the RHS of the semi/anti join
	RelDataType topInputRowType =
			SqlValidatorUtil.deriveJoinRowType(
					project.getRowType(),
					rightChild.getRowType(),
					JoinRelType.INNER,
					typeFactory,
					null,
					join.getSystemFieldList());
	RexProgramBuilder topProgramBuilder =
			new RexProgramBuilder(
					topInputRowType,
					rexBuilder);
	topProgramBuilder.addIdentity();
	topProgramBuilder.addCondition(join.getCondition());
	RexProgram topProgram = topProgramBuilder.getProgram();

	// merge the programs and expand out the local references to form
	// the new semi/anti join condition; it now references a concatenation of
	// the project's child and the RHS of the semi/anti join
	RexProgram mergedProgram =
			RexProgramBuilder.mergePrograms(
					topProgram,
					bottomProgram,
					rexBuilder);

	return mergedProgram.expandLocalRef(
			mergedProgram.getCondition());
}
 
示例26
public void onMatch(RelOptRuleCall call) {
  final Join joinRel = call.rel(0);
  final RelNode otherNode;
  final Calc calc;

  final RelNode leftJoinChild;
  final RelNode rightJoinChild;

  if (call.rel(1) instanceof Calc) {
    otherNode = call.rel(2);
    calc = call.rel(1);
    rightJoinChild = otherNode;
    leftJoinChild = calc.getInput();
  } else {
    otherNode = call.rel(1);
    calc = call.rel(2);
    rightJoinChild = calc.getInput();
    leftJoinChild = otherNode;
  }
  /**
   * Currently not supporting calc which doesnot
   * project star (all the columns of input)
   * or has aggregates.
   */
  if (!isStar(calc.getProgram())
      || calc.getProgram().containsAggs()) {
    return;
  }

  final List<RelDataTypeField> origFields =
      calc.getRowType().getFieldList();
  final int[] adjustments = new int[calc.getProgram().getExprCount()];
  if (rightJoinChild == calc.getInput()) {
    int offset = leftJoinChild.getRowType().getFieldList().size();
    for (int i = 0; i < origFields.size(); i++) {
      adjustments[i] = offset;
    }
  }
  Join newJoinRel =
      joinRel.copy(joinRel.getTraitSet(), joinRel.getCondition(),
          leftJoinChild, rightJoinChild, joinRel.getJoinType(),
          joinRel.isSemiJoinDone());

  RexProgramBuilder topProgramBuilder =
      new RexProgramBuilder(
          joinRel.getRowType(),
          joinRel.getCluster().getRexBuilder());
  topProgramBuilder.addIdentity();
  final RelOptUtil.RexInputConverter rexInputConverter =
      new RelOptUtil.RexInputConverter(calc.getCluster().getRexBuilder(),
          origFields,
          joinRel.getRowType().getFieldList(),
          adjustments);
  if (calc.getProgram().getCondition() != null) {
    RexNode cond =
        calc.getProgram().expandLocalRef(calc.getProgram().getCondition());
    final RexLocalRef rexLocalRef =
        topProgramBuilder.addExpr(cond.accept(rexInputConverter));
    topProgramBuilder.addCondition(rexLocalRef);
  }
  Calc newCalcRel =
      calc.copy(calc.getTraitSet(), newJoinRel, topProgramBuilder.getProgram());

  call.transformTo(newCalcRel);
}
 
示例27
@Override
public void onMatch(RelOptRuleCall call) {
	FlinkLogicalCorrelate correlate = call.rel(0);
	FlinkLogicalCalc right = call.rel(2);
	RexBuilder rexBuilder = call.builder().getRexBuilder();
	FlinkLogicalCalc mergedCalc = CorrelateUtil.getMergedCalc(right);
	FlinkLogicalTableFunctionScan tableScan = CorrelateUtil.getTableFunctionScan(mergedCalc).get();
	RexProgram mergedCalcProgram = mergedCalc.getProgram();

	InputRefRewriter inputRefRewriter = new InputRefRewriter(
		correlate.getRowType().getFieldCount() - mergedCalc.getRowType().getFieldCount());
	List<RexNode> correlateFilters = RelOptUtil
		.conjunctions(mergedCalcProgram.expandLocalRef(mergedCalcProgram.getCondition()))
		.stream()
		.map(x -> x.accept(inputRefRewriter))
		.collect(Collectors.toList());

	FlinkLogicalCorrelate newCorrelate = new FlinkLogicalCorrelate(
		correlate.getCluster(),
		correlate.getTraitSet(),
		correlate.getLeft(),
		tableScan,
		correlate.getCorrelationId(),
		correlate.getRequiredColumns(),
		correlate.getJoinType());

	RexNode topCalcCondition = RexUtil.composeConjunction(rexBuilder, correlateFilters);
	RexProgram rexProgram = new RexProgramBuilder(
		newCorrelate.getRowType(), rexBuilder).getProgram();
	FlinkLogicalCalc newTopCalc = new FlinkLogicalCalc(
		newCorrelate.getCluster(),
		newCorrelate.getTraitSet(),
		newCorrelate,
		RexProgram.create(
			newCorrelate.getRowType(),
			rexProgram.getExprList(),
			topCalcCondition,
			newCorrelate.getRowType(),
			rexBuilder));

	call.transformTo(newTopCalc);
}
 
示例28
@Override
public void onMatch(RelOptRuleCall call) {
	FlinkLogicalCorrelate correlate = call.rel(0);
	FlinkLogicalCalc right = call.rel(2);
	RexBuilder rexBuilder = call.builder().getRexBuilder();
	FlinkLogicalCalc mergedCalc = StreamExecCorrelateRule.getMergedCalc(right);
	FlinkLogicalTableFunctionScan tableScan = StreamExecCorrelateRule.getTableScan(mergedCalc);
	RexProgram mergedCalcProgram = mergedCalc.getProgram();

	InputRefRewriter inputRefRewriter = new InputRefRewriter(
		correlate.getRowType().getFieldCount() - mergedCalc.getRowType().getFieldCount());
	List<RexNode> correlateFilters = RelOptUtil
		.conjunctions(mergedCalcProgram.expandLocalRef(mergedCalcProgram.getCondition()))
		.stream()
		.map(x -> x.accept(inputRefRewriter))
		.collect(Collectors.toList());

	FlinkLogicalCorrelate newCorrelate = new FlinkLogicalCorrelate(
		correlate.getCluster(),
		correlate.getTraitSet(),
		correlate.getLeft(),
		tableScan,
		correlate.getCorrelationId(),
		correlate.getRequiredColumns(),
		correlate.getJoinType());

	RexNode topCalcCondition = RexUtil.composeConjunction(rexBuilder, correlateFilters);
	RexProgram rexProgram = new RexProgramBuilder(
		newCorrelate.getRowType(), rexBuilder).getProgram();
	FlinkLogicalCalc newTopCalc = new FlinkLogicalCalc(
		newCorrelate.getCluster(),
		newCorrelate.getTraitSet(),
		newCorrelate,
		RexProgram.create(
			newCorrelate.getRowType(),
			rexProgram.getExprList(),
			topCalcCondition,
			newCorrelate.getRowType(),
			rexBuilder));

	call.transformTo(newTopCalc);
}
 
示例29
/**
 * Pulls the project above the semi/anti join and returns the resulting semi/anti join
 * condition. As a result, the semi/anti join condition should be modified such
 * that references to the LHS of a semi/anti join should now reference the
 * children of the project that's on the LHS.
 *
 * @param project LogicalProject on the LHS of the semi/anti join
 * @param join the semi/anti join
 * @return the modified semi/anti join condition
 */
private RexNode adjustCondition(LogicalProject project, Join join) {
	// create two RexPrograms -- the bottom one representing a
	// concatenation of the project and the RHS of the semi/anti join and the
	// top one representing the semi/anti join condition

	RexBuilder rexBuilder = project.getCluster().getRexBuilder();
	RelDataTypeFactory typeFactory = rexBuilder.getTypeFactory();
	RelNode rightChild = join.getRight();

	// for the bottom RexProgram, the input is a concatenation of the
	// child of the project and the RHS of the semi/anti join
	RelDataType bottomInputRowType =
			SqlValidatorUtil.deriveJoinRowType(
					project.getInput().getRowType(),
					rightChild.getRowType(),
					JoinRelType.INNER,
					typeFactory,
					null,
					join.getSystemFieldList());
	RexProgramBuilder bottomProgramBuilder =
			new RexProgramBuilder(bottomInputRowType, rexBuilder);

	// add the project expressions, then add input references for the RHS
	// of the semi/anti join
	for (Pair<RexNode, String> pair : project.getNamedProjects()) {
		bottomProgramBuilder.addProject(pair.left, pair.right);
	}
	int nLeftFields = project.getInput().getRowType().getFieldCount();
	List<RelDataTypeField> rightFields =
			rightChild.getRowType().getFieldList();
	int nRightFields = rightFields.size();
	for (int i = 0; i < nRightFields; i++) {
		final RelDataTypeField field = rightFields.get(i);
		RexNode inputRef =
				rexBuilder.makeInputRef(
						field.getType(), i + nLeftFields);
		bottomProgramBuilder.addProject(inputRef, field.getName());
	}
	RexProgram bottomProgram = bottomProgramBuilder.getProgram();

	// input rowtype into the top program is the concatenation of the
	// project and the RHS of the semi/anti join
	RelDataType topInputRowType =
			SqlValidatorUtil.deriveJoinRowType(
					project.getRowType(),
					rightChild.getRowType(),
					JoinRelType.INNER,
					typeFactory,
					null,
					join.getSystemFieldList());
	RexProgramBuilder topProgramBuilder =
			new RexProgramBuilder(
					topInputRowType,
					rexBuilder);
	topProgramBuilder.addIdentity();
	topProgramBuilder.addCondition(join.getCondition());
	RexProgram topProgram = topProgramBuilder.getProgram();

	// merge the programs and expand out the local references to form
	// the new semi/anti join condition; it now references a concatenation of
	// the project's child and the RHS of the semi/anti join
	RexProgram mergedProgram =
			RexProgramBuilder.mergePrograms(
					topProgram,
					bottomProgram,
					rexBuilder);

	return mergedProgram.expandLocalRef(
			mergedProgram.getCondition());
}
 
示例30
public void onMatch(RelOptRuleCall call) {
  final LogicalProject project = call.rel(0);
  final LogicalCalc calc = call.rel(1);

  // Don't merge a project which contains windowed aggregates onto a
  // calc. That would effectively be pushing a windowed aggregate down
  // through a filter. Transform the project into an identical calc,
  // which we'll have chance to merge later, after the over is
  // expanded.
  final RelOptCluster cluster = project.getCluster();
  RexProgram program =
      RexProgram.create(
          calc.getRowType(),
          project.getProjects(),
          null,
          project.getRowType(),
          cluster.getRexBuilder());
  if (RexOver.containsOver(program)) {
    LogicalCalc projectAsCalc = LogicalCalc.create(calc, program);
    call.transformTo(projectAsCalc);
    return;
  }

  // Create a program containing the project node's expressions.
  final RexBuilder rexBuilder = cluster.getRexBuilder();
  final RexProgramBuilder progBuilder =
      new RexProgramBuilder(
          calc.getRowType(),
          rexBuilder);
  for (Pair<RexNode, String> field : project.getNamedProjects()) {
    progBuilder.addProject(field.left, field.right);
  }
  RexProgram topProgram = progBuilder.getProgram();
  RexProgram bottomProgram = calc.getProgram();

  // Merge the programs together.
  RexProgram mergedProgram =
      RexProgramBuilder.mergePrograms(
          topProgram,
          bottomProgram,
          rexBuilder);
  final LogicalCalc newCalc =
      LogicalCalc.create(calc.getInput(), mergedProgram);
  call.transformTo(newCalc);
}