Java Code Examples for org.apache.calcite.rel.logical.LogicalProject#getNamedProjects()

The following examples show how to use org.apache.calcite.rel.logical.LogicalProject#getNamedProjects() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: RelDecorrelator.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Pulls project above the join from its RHS input. Enforces nullability
 * for join output.
 *
 * @param join          Join
 * @param project       Original project as the right-hand input of the join
 * @param nullIndicatorPos Position of null indicator
 * @return the subtree with the new Project at the root
 */
private RelNode projectJoinOutputWithNullability(LogicalJoin join, LogicalProject project, int nullIndicatorPos) {
    final RelDataTypeFactory typeFactory = join.getCluster().getTypeFactory();
    final RelNode left = join.getLeft();
    final JoinRelType joinType = join.getJoinType();

    RexInputRef nullIndicator = RexBuilder.getRexFactory().makeInputRef(nullIndicatorPos, typeFactory
            .createTypeWithNullability(join.getRowType().getFieldList().get(nullIndicatorPos).getType(), true));

    // now create the new project
    List<Pair<RexNode, String>> newProjExprs = new ArrayList<>();

    // project everything from the LHS and then those from the original
    // projRel
    List<RelDataTypeField> leftInputFields = left.getRowType().getFieldList();

    for (int i = 0; i < leftInputFields.size(); i++) {
        newProjExprs.add(RexInputRef.of2(i, leftInputFields));
    }

    // Marked where the projected expr is coming from so that the types will
    // become nullable for the original projections which are now coming out
    // of the nullable side of the OJ.
    boolean projectPulledAboveLeftCorrelator = joinType.generatesNullsOnRight();

    for (Pair<RexNode, String> pair : project.getNamedProjects()) {
        RexNode newProjExpr = removeCorrelationExpr(pair.left, projectPulledAboveLeftCorrelator, nullIndicator);

        newProjExprs.add(Pair.of(newProjExpr, pair.right));
    }

    return relBuilder.push(join).projectNamed(Pair.left(newProjExprs), Pair.right(newProjExprs), true).build();
}
 
Example 2
Source File: RelDecorrelator.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Pulls a {@link Project} above a {@link Correlate} from its RHS input.
 * Enforces nullability for join output.
 *
 * @param correlate  Correlate
 * @param project the original project as the RHS input of the join
 * @param isCount Positions which are calls to the <code>COUNT</code>
 *                aggregation function
 * @return the subtree with the new Project at the root
 */
private RelNode aggregateCorrelatorOutput(Correlate correlate, LogicalProject project, Set<Integer> isCount) {
    final RelNode left = correlate.getLeft();
    final JoinRelType joinType = correlate.getJoinType().toJoinType();

    // now create the new project
    final List<Pair<RexNode, String>> newProjects = new ArrayList<>();

    // Project everything from the LHS and then those from the original
    // project
    final List<RelDataTypeField> leftInputFields = left.getRowType().getFieldList();

    for (int i = 0; i < leftInputFields.size(); i++) {
        newProjects.add(RexInputRef.of2(i, leftInputFields));
    }

    // Marked where the projected expr is coming from so that the types will
    // become nullable for the original projections which are now coming out
    // of the nullable side of the OJ.
    boolean projectPulledAboveLeftCorrelator = joinType.generatesNullsOnRight();

    for (Pair<RexNode, String> pair : project.getNamedProjects()) {
        RexNode newProjExpr = removeCorrelationExpr(pair.left, projectPulledAboveLeftCorrelator, isCount);
        newProjects.add(Pair.of(newProjExpr, pair.right));
    }

    return relBuilder.push(correlate).projectNamed(Pair.left(newProjects), Pair.right(newProjects), true).build();
}
 
Example 3
Source File: RelDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * Pulls a {@link Project} above a {@link Correlate} from its RHS input.
 * Enforces nullability for join output.
 *
 * @param correlate  Correlate
 * @param project the original project as the RHS input of the join
 * @param isCount Positions which are calls to the <code>COUNT</code>
 *                aggregation function
 * @return the subtree with the new Project at the root
 */
private RelNode aggregateCorrelatorOutput(
    Correlate correlate,
    LogicalProject project,
    Set<Integer> isCount) {
  final RelNode left = correlate.getLeft();
  final JoinRelType joinType = correlate.getJoinType();

  // now create the new project
  final List<Pair<RexNode, String>> newProjects = new ArrayList<>();

  // Project everything from the LHS and then those from the original
  // project
  final List<RelDataTypeField> leftInputFields =
      left.getRowType().getFieldList();

  for (int i = 0; i < leftInputFields.size(); i++) {
    newProjects.add(RexInputRef.of2(i, leftInputFields));
  }

  // Marked where the projected expr is coming from so that the types will
  // become nullable for the original projections which are now coming out
  // of the nullable side of the OJ.
  boolean projectPulledAboveLeftCorrelator =
      joinType.generatesNullsOnRight();

  for (Pair<RexNode, String> pair : project.getNamedProjects()) {
    RexNode newProjExpr =
        removeCorrelationExpr(
            pair.left,
            projectPulledAboveLeftCorrelator,
            isCount);
    newProjects.add(Pair.of(newProjExpr, pair.right));
  }

  return relBuilder.push(correlate)
      .projectNamed(Pair.left(newProjects), Pair.right(newProjects), true)
      .build();
}
 
Example 4
Source File: RelDecorrelator.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * Pulls a {@link Project} above a {@link Correlate} from its RHS input.
 * Enforces nullability for join output.
 *
 * @param correlate  Correlate
 * @param project the original project as the RHS input of the join
 * @param isCount Positions which are calls to the <code>COUNT</code>
 *                aggregation function
 * @return the subtree with the new Project at the root
 */
private RelNode aggregateCorrelatorOutput(
    Correlate correlate,
    LogicalProject project,
    Set<Integer> isCount) {
  final RelNode left = correlate.getLeft();
  final JoinRelType joinType = correlate.getJoinType();

  // now create the new project
  final List<Pair<RexNode, String>> newProjects = new ArrayList<>();

  // Project everything from the LHS and then those from the original
  // project
  final List<RelDataTypeField> leftInputFields =
      left.getRowType().getFieldList();

  for (int i = 0; i < leftInputFields.size(); i++) {
    newProjects.add(RexInputRef.of2(i, leftInputFields));
  }

  // Marked where the projected expr is coming from so that the types will
  // become nullable for the original projections which are now coming out
  // of the nullable side of the OJ.
  boolean projectPulledAboveLeftCorrelator =
      joinType.generatesNullsOnRight();

  for (Pair<RexNode, String> pair : project.getNamedProjects()) {
    RexNode newProjExpr =
        removeCorrelationExpr(
            pair.left,
            projectPulledAboveLeftCorrelator,
            isCount);
    newProjects.add(Pair.of(newProjExpr, pair.right));
  }

  return relBuilder.push(correlate)
      .projectNamed(Pair.left(newProjects), Pair.right(newProjects), true)
      .build();
}
 
Example 5
Source File: ProjectCalcMergeRule.java    From Bats with Apache License 2.0 4 votes vote down vote up
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);
}
 
Example 6
Source File: SemiJoinProjectTransposeRule.java    From Bats with Apache License 2.0 4 votes vote down vote up
/**
 * 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());
}
 
Example 7
Source File: RelDecorrelator.java    From flink with Apache License 2.0 4 votes vote down vote up
/**
 * Pulls project above the join from its RHS input. Enforces nullability
 * for join output.
 *
 * @param join          Join
 * @param project       Original project as the right-hand input of the join
 * @param nullIndicatorPos Position of null indicator
 * @return the subtree with the new Project at the root
 */
private RelNode projectJoinOutputWithNullability(
    LogicalJoin join,
    LogicalProject project,
    int nullIndicatorPos) {
  final RelDataTypeFactory typeFactory = join.getCluster().getTypeFactory();
  final RelNode left = join.getLeft();
  final JoinRelType joinType = join.getJoinType();

  RexInputRef nullIndicator =
      new RexInputRef(
          nullIndicatorPos,
          typeFactory.createTypeWithNullability(
              join.getRowType().getFieldList().get(nullIndicatorPos)
                  .getType(),
              true));

  // now create the new project
  List<Pair<RexNode, String>> newProjExprs = new ArrayList<>();

  // project everything from the LHS and then those from the original
  // projRel
  List<RelDataTypeField> leftInputFields =
      left.getRowType().getFieldList();

  for (int i = 0; i < leftInputFields.size(); i++) {
    newProjExprs.add(RexInputRef.of2(i, leftInputFields));
  }

  // Marked where the projected expr is coming from so that the types will
  // become nullable for the original projections which are now coming out
  // of the nullable side of the OJ.
  boolean projectPulledAboveLeftCorrelator =
      joinType.generatesNullsOnRight();

  for (Pair<RexNode, String> pair : project.getNamedProjects()) {
    RexNode newProjExpr =
        removeCorrelationExpr(
            pair.left,
            projectPulledAboveLeftCorrelator,
            nullIndicator);

    newProjExprs.add(Pair.of(newProjExpr, pair.right));
  }

  return relBuilder.push(join)
      .projectNamed(Pair.left(newProjExprs), Pair.right(newProjExprs), true)
      .build();
}
 
Example 8
Source File: RelDecorrelator.java    From flink with Apache License 2.0 4 votes vote down vote up
/**
 * Pulls project above the join from its RHS input. Enforces nullability
 * for join output.
 *
 * @param join          Join
 * @param project       Original project as the right-hand input of the join
 * @param nullIndicatorPos Position of null indicator
 * @return the subtree with the new Project at the root
 */
private RelNode projectJoinOutputWithNullability(
    LogicalJoin join,
    LogicalProject project,
    int nullIndicatorPos) {
  final RelDataTypeFactory typeFactory = join.getCluster().getTypeFactory();
  final RelNode left = join.getLeft();
  final JoinRelType joinType = join.getJoinType();

  RexInputRef nullIndicator =
      new RexInputRef(
          nullIndicatorPos,
          typeFactory.createTypeWithNullability(
              join.getRowType().getFieldList().get(nullIndicatorPos)
                  .getType(),
              true));

  // now create the new project
  List<Pair<RexNode, String>> newProjExprs = new ArrayList<>();

  // project everything from the LHS and then those from the original
  // projRel
  List<RelDataTypeField> leftInputFields =
      left.getRowType().getFieldList();

  for (int i = 0; i < leftInputFields.size(); i++) {
    newProjExprs.add(RexInputRef.of2(i, leftInputFields));
  }

  // Marked where the projected expr is coming from so that the types will
  // become nullable for the original projections which are now coming out
  // of the nullable side of the OJ.
  boolean projectPulledAboveLeftCorrelator =
      joinType.generatesNullsOnRight();

  for (Pair<RexNode, String> pair : project.getNamedProjects()) {
    RexNode newProjExpr =
        removeCorrelationExpr(
            pair.left,
            projectPulledAboveLeftCorrelator,
            nullIndicator);

    newProjExprs.add(Pair.of(newProjExpr, pair.right));
  }

  return relBuilder.push(join)
      .projectNamed(Pair.left(newProjExprs), Pair.right(newProjExprs), true)
      .build();
}
 
Example 9
Source File: FlinkSemiAntiJoinProjectTransposeRule.java    From flink with Apache License 2.0 4 votes vote down vote up
/**
 * 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());
}
 
Example 10
Source File: JournalledInsertRule.java    From calcite-sql-rewriter with Apache License 2.0 4 votes vote down vote up
@Override
public RelNode doApply(LogicalTableModify tableModify, JournalledJdbcTable journalTable,
		JdbcRelBuilderFactory relBuilderFactory) {

	JdbcRelBuilder relBuilder = relBuilderFactory.create(
			tableModify.getCluster(),
			tableModify.getTable().getRelOptSchema()
	);

	RelNode input = tableModify.getInput();
	if (input instanceof LogicalValues) {

		// TODO: do we need to do anything here?
		relBuilder.push(input);

	}
	else if (input instanceof LogicalProject) {

		LogicalProject project = (LogicalProject) input;
		List<RexNode> desiredFields = new ArrayList<>();
		List<String> desiredNames = new ArrayList<>();
		for (Pair<RexNode, String> field : project.getNamedProjects()) {
			if (field.getKey() instanceof RexInputRef) {
				desiredFields.add(field.getKey());
				desiredNames.add(field.getValue());
			}
		}

		relBuilder.push(project.getInput());
		relBuilder.project(desiredFields, desiredNames);

	}
	else {
		throw new IllegalStateException("Unknown Calcite INSERT structure");
	}

	relBuilder.insertCopying(
			tableModify,
			journalTable.getJournalTable()
	);

	return relBuilder.build();

}
 
Example 11
Source File: JournalledUpdateRule.java    From calcite-sql-rewriter with Apache License 2.0 4 votes vote down vote up
@Override
public RelNode doApply(LogicalTableModify tableModify, JournalledJdbcTable journalTable,
		JdbcRelBuilderFactory relBuilderFactory) {

	if (!(tableModify.getInput() instanceof LogicalProject)) {
		throw new IllegalStateException("Unknown Calcite UPDATE structure");
	}

	String versionField = journalTable.getVersionField();

	// Merge the Update's update column expression into the target INSERT
	LogicalProject project = (LogicalProject) tableModify.getInput();
	List<RexNode> desiredFields = new ArrayList<>();
	List<String> desiredNames = new ArrayList<>();

	for (Pair<RexNode, String> field : project.getNamedProjects()) {
		if (field.getKey() instanceof RexInputRef) {
			int index = tableModify.getUpdateColumnList().indexOf(field.getValue());
			if (index != -1) {
				desiredFields.add(tableModify.getSourceExpressionList().get(index));
			}
			else {
				desiredFields.add(field.getKey());
			}
			desiredNames.add(field.getValue());
		}
	}

	JdbcRelBuilder relBuilder = relBuilderFactory.create(
			tableModify.getCluster(),
			tableModify.getTable().getRelOptSchema()
	);

	relBuilder.push(project.getInput());

	JournalVersionType versionType = journalTable.getVersionType();
	if (!versionType.isValidSqlType(relBuilder.field(versionField).getType().getSqlTypeName())) {
		throw new IllegalStateException("Incorrect journalVersionType! Column 'version_number' is of type: "
				+ relBuilder.field(versionField).getType().getSqlTypeName()
				+ " but the journalVersionType is " + versionType);
	}
	if (versionType.updateRequiresExplicitVersion()) {
		RexNode newVersion = versionType.incrementVersion(relBuilder, relBuilder.field(versionField));
		desiredFields.add(newVersion);
		desiredNames.add(versionField);
	}

	relBuilder.project(desiredFields, desiredNames);

	// Convert the UPDATE into INSERT TableModify operations
	relBuilder.insertCopying(
			tableModify,
			journalTable.getJournalTable()
	);

	return relBuilder.build();
}
 
Example 12
Source File: FlinkSemiAntiJoinProjectTransposeRule.java    From flink with Apache License 2.0 4 votes vote down vote up
/**
 * 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());
}
 
Example 13
Source File: ProjectCalcMergeRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
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);
}
 
Example 14
Source File: SemiJoinProjectTransposeRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * 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, LogicalJoin 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());
}