Java Code Examples for org.apache.calcite.util.mapping.Mappings#createShiftMapping()

The following examples show how to use org.apache.calcite.util.mapping.Mappings#createShiftMapping() . 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: JoinPushThroughJoinRule.java    From Bats with Apache License 2.0 4 votes vote down vote up
/**
 * Similar to {@link #onMatch}, but swaps the upper sibling with the left
 * of the two lower siblings, rather than the right.
 */
private void onMatchLeft(RelOptRuleCall call) {
  final Join topJoin = call.rel(0);
  final Join bottomJoin = call.rel(1);
  final RelNode relC = call.rel(2);
  final RelNode relA = bottomJoin.getLeft();
  final RelNode relB = bottomJoin.getRight();
  final RelOptCluster cluster = topJoin.getCluster();

  //        topJoin
  //        /     \
  //   bottomJoin  C
  //    /    \
  //   A      B

  final int aCount = relA.getRowType().getFieldCount();
  final int bCount = relB.getRowType().getFieldCount();
  final int cCount = relC.getRowType().getFieldCount();
  final ImmutableBitSet aBitSet = ImmutableBitSet.range(aCount);

  // becomes
  //
  //        newTopJoin
  //        /        \
  //   newBottomJoin  A
  //    /    \
  //   C      B

  // If either join is not inner, we cannot proceed.
  // (Is this too strict?)
  if (topJoin.getJoinType() != JoinRelType.INNER
      || bottomJoin.getJoinType() != JoinRelType.INNER) {
    return;
  }

  // Split the condition of topJoin into a conjunction. Each of the
  // parts that does not use columns from A can be pushed down.
  final List<RexNode> intersecting = new ArrayList<>();
  final List<RexNode> nonIntersecting = new ArrayList<>();
  split(topJoin.getCondition(), aBitSet, intersecting, nonIntersecting);

  // If there's nothing to push down, it's not worth proceeding.
  if (nonIntersecting.isEmpty()) {
    return;
  }

  // Split the condition of bottomJoin into a conjunction. Each of the
  // parts that use columns from A will need to be pulled up.
  final List<RexNode> bottomIntersecting = new ArrayList<>();
  final List<RexNode> bottomNonIntersecting = new ArrayList<>();
  split(
      bottomJoin.getCondition(), aBitSet, bottomIntersecting,
      bottomNonIntersecting);

  // target: | C      | B |
  // source: | A       | B | C      |
  final Mappings.TargetMapping bottomMapping =
      Mappings.createShiftMapping(
          aCount + bCount + cCount,
          cCount, aCount, bCount,
          0, aCount + bCount, cCount);
  final List<RexNode> newBottomList = new ArrayList<>();
  new RexPermuteInputsShuttle(bottomMapping, relC, relB)
      .visitList(nonIntersecting, newBottomList);
  new RexPermuteInputsShuttle(bottomMapping, relC, relB)
      .visitList(bottomNonIntersecting, newBottomList);
  final RexBuilder rexBuilder = cluster.getRexBuilder();
  RexNode newBottomCondition =
      RexUtil.composeConjunction(rexBuilder, newBottomList);
  final Join newBottomJoin =
      bottomJoin.copy(bottomJoin.getTraitSet(), newBottomCondition, relC,
          relB, bottomJoin.getJoinType(), bottomJoin.isSemiJoinDone());

  // target: | C      | B | A       |
  // source: | A       | B | C      |
  final Mappings.TargetMapping topMapping =
      Mappings.createShiftMapping(
          aCount + bCount + cCount,
          cCount + bCount, 0, aCount,
          cCount, aCount, bCount,
          0, aCount + bCount, cCount);
  final List<RexNode> newTopList = new ArrayList<>();
  new RexPermuteInputsShuttle(topMapping, newBottomJoin, relA)
      .visitList(intersecting, newTopList);
  new RexPermuteInputsShuttle(topMapping, newBottomJoin, relA)
      .visitList(bottomIntersecting, newTopList);
  RexNode newTopCondition =
      RexUtil.composeConjunction(rexBuilder, newTopList);
  @SuppressWarnings("SuspiciousNameCombination")
  final Join newTopJoin =
      topJoin.copy(topJoin.getTraitSet(), newTopCondition, newBottomJoin,
          relA, topJoin.getJoinType(), topJoin.isSemiJoinDone());

  final RelBuilder relBuilder = call.builder();
  relBuilder.push(newTopJoin);
  relBuilder.project(relBuilder.fields(topMapping));
  call.transformTo(relBuilder.build());
}
 
Example 2
Source File: JoinAssociateRule.java    From Bats with Apache License 2.0 4 votes vote down vote up
public void onMatch(final RelOptRuleCall call) {
  final Join topJoin = call.rel(0);
  final Join bottomJoin = call.rel(1);
  final RelNode relA = bottomJoin.getLeft();
  final RelNode relB = bottomJoin.getRight();
  final RelSubset relC = call.rel(2);
  final RelOptCluster cluster = topJoin.getCluster();
  final RexBuilder rexBuilder = cluster.getRexBuilder();

  if (relC.getConvention() != relA.getConvention()) {
    // relC could have any trait-set. But if we're matching say
    // EnumerableConvention, we're only interested in enumerable subsets.
    return;
  }

  //        topJoin
  //        /     \
  //   bottomJoin  C
  //    /    \
  //   A      B

  final int aCount = relA.getRowType().getFieldCount();
  final int bCount = relB.getRowType().getFieldCount();
  final int cCount = relC.getRowType().getFieldCount();
  final ImmutableBitSet aBitSet = ImmutableBitSet.range(0, aCount);
  final ImmutableBitSet bBitSet =
      ImmutableBitSet.range(aCount, aCount + bCount);

  if (!topJoin.getSystemFieldList().isEmpty()) {
    // FIXME Enable this rule for joins with system fields
    return;
  }

  // If either join is not inner, we cannot proceed.
  // (Is this too strict?)
  if (topJoin.getJoinType() != JoinRelType.INNER
      || bottomJoin.getJoinType() != JoinRelType.INNER) {
    return;
  }

  // Goal is to transform to
  //
  //       newTopJoin
  //        /     \
  //       A   newBottomJoin
  //               /    \
  //              B      C

  // Split the condition of topJoin and bottomJoin into a conjunctions. A
  // condition can be pushed down if it does not use columns from A.
  final List<RexNode> top = new ArrayList<>();
  final List<RexNode> bottom = new ArrayList<>();
  JoinPushThroughJoinRule.split(topJoin.getCondition(), aBitSet, top, bottom);
  JoinPushThroughJoinRule.split(bottomJoin.getCondition(), aBitSet, top,
      bottom);

  // Mapping for moving conditions from topJoin or bottomJoin to
  // newBottomJoin.
  // target: | B | C      |
  // source: | A       | B | C      |
  final Mappings.TargetMapping bottomMapping =
      Mappings.createShiftMapping(
          aCount + bCount + cCount,
          0, aCount, bCount,
          bCount, aCount + bCount, cCount);
  final List<RexNode> newBottomList = new ArrayList<>();
  new RexPermuteInputsShuttle(bottomMapping, relB, relC)
      .visitList(bottom, newBottomList);
  RexNode newBottomCondition =
      RexUtil.composeConjunction(rexBuilder, newBottomList);

  final Join newBottomJoin =
      bottomJoin.copy(bottomJoin.getTraitSet(), newBottomCondition, relB,
          relC, JoinRelType.INNER, false);

  // Condition for newTopJoin consists of pieces from bottomJoin and topJoin.
  // Field ordinals do not need to be changed.
  RexNode newTopCondition = RexUtil.composeConjunction(rexBuilder, top);
  @SuppressWarnings("SuspiciousNameCombination")
  final Join newTopJoin =
      topJoin.copy(topJoin.getTraitSet(), newTopCondition, relA,
          newBottomJoin, JoinRelType.INNER, false);

  call.transformTo(newTopJoin);
}
 
Example 3
Source File: JoinPushThroughJoinRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * Similar to {@link #onMatch}, but swaps the upper sibling with the left
 * of the two lower siblings, rather than the right.
 */
private void onMatchLeft(RelOptRuleCall call) {
  final Join topJoin = call.rel(0);
  final Join bottomJoin = call.rel(1);
  final RelNode relC = call.rel(2);
  final RelNode relA = bottomJoin.getLeft();
  final RelNode relB = bottomJoin.getRight();
  final RelOptCluster cluster = topJoin.getCluster();

  //        topJoin
  //        /     \
  //   bottomJoin  C
  //    /    \
  //   A      B

  final int aCount = relA.getRowType().getFieldCount();
  final int bCount = relB.getRowType().getFieldCount();
  final int cCount = relC.getRowType().getFieldCount();
  final ImmutableBitSet aBitSet = ImmutableBitSet.range(aCount);

  // becomes
  //
  //        newTopJoin
  //        /        \
  //   newBottomJoin  A
  //    /    \
  //   C      B

  // If either join is not inner, we cannot proceed.
  // (Is this too strict?)
  if (topJoin.getJoinType() != JoinRelType.INNER
      || bottomJoin.getJoinType() != JoinRelType.INNER) {
    return;
  }

  // Split the condition of topJoin into a conjunction. Each of the
  // parts that does not use columns from A can be pushed down.
  final List<RexNode> intersecting = new ArrayList<>();
  final List<RexNode> nonIntersecting = new ArrayList<>();
  split(topJoin.getCondition(), aBitSet, intersecting, nonIntersecting);

  // If there's nothing to push down, it's not worth proceeding.
  if (nonIntersecting.isEmpty()) {
    return;
  }

  // Split the condition of bottomJoin into a conjunction. Each of the
  // parts that use columns from A will need to be pulled up.
  final List<RexNode> bottomIntersecting = new ArrayList<>();
  final List<RexNode> bottomNonIntersecting = new ArrayList<>();
  split(
      bottomJoin.getCondition(), aBitSet, bottomIntersecting,
      bottomNonIntersecting);

  // target: | C      | B |
  // source: | A       | B | C      |
  final Mappings.TargetMapping bottomMapping =
      Mappings.createShiftMapping(
          aCount + bCount + cCount,
          cCount, aCount, bCount,
          0, aCount + bCount, cCount);
  final List<RexNode> newBottomList = new ArrayList<>();
  new RexPermuteInputsShuttle(bottomMapping, relC, relB)
      .visitList(nonIntersecting, newBottomList);
  new RexPermuteInputsShuttle(bottomMapping, relC, relB)
      .visitList(bottomNonIntersecting, newBottomList);
  final RexBuilder rexBuilder = cluster.getRexBuilder();
  RexNode newBottomCondition =
      RexUtil.composeConjunction(rexBuilder, newBottomList);
  final Join newBottomJoin =
      bottomJoin.copy(bottomJoin.getTraitSet(), newBottomCondition, relC,
          relB, bottomJoin.getJoinType(), bottomJoin.isSemiJoinDone());

  // target: | C      | B | A       |
  // source: | A       | B | C      |
  final Mappings.TargetMapping topMapping =
      Mappings.createShiftMapping(
          aCount + bCount + cCount,
          cCount + bCount, 0, aCount,
          cCount, aCount, bCount,
          0, aCount + bCount, cCount);
  final List<RexNode> newTopList = new ArrayList<>();
  new RexPermuteInputsShuttle(topMapping, newBottomJoin, relA)
      .visitList(intersecting, newTopList);
  new RexPermuteInputsShuttle(topMapping, newBottomJoin, relA)
      .visitList(bottomIntersecting, newTopList);
  RexNode newTopCondition =
      RexUtil.composeConjunction(rexBuilder, newTopList);
  @SuppressWarnings("SuspiciousNameCombination")
  final Join newTopJoin =
      topJoin.copy(topJoin.getTraitSet(), newTopCondition, newBottomJoin,
          relA, topJoin.getJoinType(), topJoin.isSemiJoinDone());

  final RelBuilder relBuilder = call.builder();
  relBuilder.push(newTopJoin);
  relBuilder.project(relBuilder.fields(topMapping));
  call.transformTo(relBuilder.build());
}
 
Example 4
Source File: JoinAssociateRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
public void onMatch(final RelOptRuleCall call) {
  final Join topJoin = call.rel(0);
  final Join bottomJoin = call.rel(1);
  final RelNode relA = bottomJoin.getLeft();
  final RelNode relB = bottomJoin.getRight();
  final RelSubset relC = call.rel(2);
  final RelOptCluster cluster = topJoin.getCluster();
  final RexBuilder rexBuilder = cluster.getRexBuilder();

  if (relC.getConvention() != relA.getConvention()) {
    // relC could have any trait-set. But if we're matching say
    // EnumerableConvention, we're only interested in enumerable subsets.
    return;
  }

  //        topJoin
  //        /     \
  //   bottomJoin  C
  //    /    \
  //   A      B

  final int aCount = relA.getRowType().getFieldCount();
  final int bCount = relB.getRowType().getFieldCount();
  final int cCount = relC.getRowType().getFieldCount();
  final ImmutableBitSet aBitSet = ImmutableBitSet.range(0, aCount);
  final ImmutableBitSet bBitSet =
      ImmutableBitSet.range(aCount, aCount + bCount);

  if (!topJoin.getSystemFieldList().isEmpty()) {
    // FIXME Enable this rule for joins with system fields
    return;
  }

  // If either join is not inner, we cannot proceed.
  // (Is this too strict?)
  if (topJoin.getJoinType() != JoinRelType.INNER
      || bottomJoin.getJoinType() != JoinRelType.INNER) {
    return;
  }

  // Goal is to transform to
  //
  //       newTopJoin
  //        /     \
  //       A   newBottomJoin
  //               /    \
  //              B      C

  // Split the condition of topJoin and bottomJoin into a conjunctions. A
  // condition can be pushed down if it does not use columns from A.
  final List<RexNode> top = new ArrayList<>();
  final List<RexNode> bottom = new ArrayList<>();
  JoinPushThroughJoinRule.split(topJoin.getCondition(), aBitSet, top, bottom);
  JoinPushThroughJoinRule.split(bottomJoin.getCondition(), aBitSet, top,
      bottom);

  // Mapping for moving conditions from topJoin or bottomJoin to
  // newBottomJoin.
  // target: | B | C      |
  // source: | A       | B | C      |
  final Mappings.TargetMapping bottomMapping =
      Mappings.createShiftMapping(
          aCount + bCount + cCount,
          0, aCount, bCount,
          bCount, aCount + bCount, cCount);
  final List<RexNode> newBottomList =
      new RexPermuteInputsShuttle(bottomMapping, relB, relC)
          .visitList(bottom);
  RexNode newBottomCondition =
      RexUtil.composeConjunction(rexBuilder, newBottomList);

  final Join newBottomJoin =
      bottomJoin.copy(bottomJoin.getTraitSet(), newBottomCondition, relB,
          relC, JoinRelType.INNER, false);

  // Condition for newTopJoin consists of pieces from bottomJoin and topJoin.
  // Field ordinals do not need to be changed.
  RexNode newTopCondition = RexUtil.composeConjunction(rexBuilder, top);
  @SuppressWarnings("SuspiciousNameCombination")
  final Join newTopJoin =
      topJoin.copy(topJoin.getTraitSet(), newTopCondition, relA,
          newBottomJoin, JoinRelType.INNER, false);

  call.transformTo(newTopJoin);
}