Java Code Examples for org.apache.calcite.util.mapping.Mappings#TargetMapping

The following examples show how to use org.apache.calcite.util.mapping.Mappings#TargetMapping . 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: SubstitutionVisitor.java    From Bats with Apache License 2.0 6 votes vote down vote up
@Override
public UnifyResult apply(UnifyRuleCall call) {
    final MutableAggregate query = (MutableAggregate) call.query;
    final MutableAggregate target = (MutableAggregate) call.target;
    if (!(query.getInput() instanceof MutableProject)) {
        return null;
    }
    final MutableProject project = (MutableProject) query.getInput();
    if (project.getInput() != target.getInput()) {
        return null;
    }
    final Mappings.TargetMapping mapping = project.getMapping();
    if (mapping == null) {
        return null;
    }
    final MutableAggregate aggregate2 = permute(query, project.getInput(), mapping.inverse());
    final MutableRel result = unifyAggregates(aggregate2, target);
    return result == null ? null : call.result(result);
}
 
Example 2
Source File: EnumerableMergeJoin.java    From calcite with Apache License 2.0 5 votes vote down vote up
private Mappings.TargetMapping buildMapping(boolean left2Right) {
  ImmutableIntList sourceKeys = left2Right ? joinInfo.leftKeys : joinInfo.rightKeys;
  ImmutableIntList targetKeys = left2Right ? joinInfo.rightKeys : joinInfo.leftKeys;
  Map<Integer, Integer> keyMap = new HashMap<>();
  for (int i = 0; i < joinInfo.leftKeys.size(); i++) {
    keyMap.put(sourceKeys.get(i), targetKeys.get(i));
  }

  Mappings.TargetMapping mapping = Mappings.target(keyMap,
      (left2Right ? left : right).getRowType().getFieldCount(),
      (left2Right ? right : left).getRowType().getFieldCount());
  return mapping;
}
 
Example 3
Source File: RexProgram.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Returns a partial mapping of a set of project expressions.
 *
 * <p>The mapping is an inverse function.
 * Every target has a source field, but
 * a source might have 0, 1 or more targets.
 * Project expressions that do not consist of
 * a mapping are ignored.
 *
 * @param inputFieldCount Number of input fields
 * @return Mapping of a set of project expressions, never null
 */
public Mappings.TargetMapping getPartialMapping(int inputFieldCount) {
  Mappings.TargetMapping mapping =
      Mappings.create(MappingType.INVERSE_FUNCTION,
          inputFieldCount, projects.size());
  for (Ord<RexLocalRef> exp : Ord.zip(projects)) {
    RexNode rexNode = expandLocalRef(exp.e);
    if (rexNode instanceof RexInputRef) {
      mapping.set(((RexInputRef) rexNode).getIndex(), exp.i);
    }
  }
  return mapping;
}
 
Example 4
Source File: SortProjectTransposeRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Sort sort = call.rel(0);
  final Project project = call.rel(1);
  final RelOptCluster cluster = project.getCluster();

  if (sort.getConvention() != project.getConvention()) {
    return;
  }

  // Determine mapping between project input and output fields. If sort
  // relies on non-trivial expressions, we can't push.
  final Mappings.TargetMapping map =
      RelOptUtil.permutationIgnoreCast(
          project.getProjects(), project.getInput().getRowType());
  for (RelFieldCollation fc : sort.getCollation().getFieldCollations()) {
    if (map.getTargetOpt(fc.getFieldIndex()) < 0) {
      return;
    }
    final RexNode node = project.getProjects().get(fc.getFieldIndex());
    if (node.isA(SqlKind.CAST)) {
      // Check whether it is a monotonic preserving cast, otherwise we cannot push
      final RexCall cast = (RexCall) node;
      RelFieldCollation newFc = Objects.requireNonNull(RexUtil.apply(map, fc));
      final RexCallBinding binding =
          RexCallBinding.create(cluster.getTypeFactory(), cast,
              ImmutableList.of(RelCollations.of(newFc)));
      if (cast.getOperator().getMonotonicity(binding) == SqlMonotonicity.NOT_MONOTONIC) {
        return;
      }
    }
  }
  final RelCollation newCollation =
      cluster.traitSet().canonize(
          RexUtil.apply(map, sort.getCollation()));
  final Sort newSort =
      sort.copy(
          sort.getTraitSet().replace(newCollation),
          project.getInput(),
          newCollation,
          sort.offset,
          sort.fetch);
  RelNode newProject =
      project.copy(
          sort.getTraitSet(),
          ImmutableList.of(newSort));
  // Not only is newProject equivalent to sort;
  // newSort is equivalent to project's input
  // (but only if the sort is not also applying an offset/limit).
  Map<RelNode, RelNode> equiv;
  if (sort.offset == null
      && sort.fetch == null
      && cluster.getPlanner().getRelTraitDefs()
          .contains(RelCollationTraitDef.INSTANCE)) {
    equiv = ImmutableMap.of((RelNode) newSort, project.getInput());
  } else {
    equiv = ImmutableMap.of();
  }
  call.transformTo(newProject, equiv);
}
 
Example 5
Source File: RexPermuteInputsShuttle.java    From calcite with Apache License 2.0 4 votes vote down vote up
/** Creates a shuttle with an empty field list. It cannot handle GET calls but
 * otherwise works OK. */
public static RexPermuteInputsShuttle of(Mappings.TargetMapping mapping) {
  return new RexPermuteInputsShuttle(mapping,
      ImmutableList.of());
}
 
Example 6
Source File: SqlSplittableAggFunction.java    From Bats with Apache License 2.0 4 votes vote down vote up
public AggregateCall split(AggregateCall aggregateCall,
    Mappings.TargetMapping mapping) {
  return aggregateCall.transform(mapping);
}
 
Example 7
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 8
Source File: SqlSplittableAggFunction.java    From Bats with Apache License 2.0 4 votes vote down vote up
AggregateCall split(AggregateCall aggregateCall,
Mappings.TargetMapping mapping);
 
Example 9
Source File: UnionPullUpConstantsRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
@Override public void onMatch(RelOptRuleCall call) {
  final Union union = call.rel(0);

  final RexBuilder rexBuilder = union.getCluster().getRexBuilder();
  final RelMetadataQuery mq = call.getMetadataQuery();
  final RelOptPredicateList predicates = mq.getPulledUpPredicates(union);
  if (predicates == null) {
    return;
  }

  final Map<Integer, RexNode> constants = new HashMap<>();
  for (Map.Entry<RexNode, RexNode> e : predicates.constantMap.entrySet()) {
    if (e.getKey() instanceof RexInputRef) {
      constants.put(((RexInputRef) e.getKey()).getIndex(), e.getValue());
    }
  }

  // None of the expressions are constant. Nothing to do.
  if (constants.isEmpty()) {
    return;
  }

  // Create expressions for Project operators before and after the Union
  List<RelDataTypeField> fields = union.getRowType().getFieldList();
  List<RexNode> topChildExprs = new ArrayList<>();
  List<String> topChildExprsFields = new ArrayList<>();
  List<RexNode> refs = new ArrayList<>();
  ImmutableBitSet.Builder refsIndexBuilder = ImmutableBitSet.builder();
  for (RelDataTypeField field : fields) {
    final RexNode constant = constants.get(field.getIndex());
    if (constant != null) {
      topChildExprs.add(constant);
      topChildExprsFields.add(field.getName());
    } else {
      final RexNode expr = rexBuilder.makeInputRef(union, field.getIndex());
      topChildExprs.add(expr);
      topChildExprsFields.add(field.getName());
      refs.add(expr);
      refsIndexBuilder.set(field.getIndex());
    }
  }
  ImmutableBitSet refsIndex = refsIndexBuilder.build();

  // Update top Project positions
  final Mappings.TargetMapping mapping =
      RelOptUtil.permutation(refs, union.getInput(0).getRowType()).inverse();
  topChildExprs = RexUtil.apply(mapping, topChildExprs);

  // Create new Project-Union-Project sequences
  final RelBuilder relBuilder = call.builder();
  for (RelNode input : union.getInputs()) {
    List<Pair<RexNode, String>> newChildExprs = new ArrayList<>();
    for (int j : refsIndex) {
      newChildExprs.add(
          Pair.of(rexBuilder.makeInputRef(input, j),
              input.getRowType().getFieldList().get(j).getName()));
    }
    if (newChildExprs.isEmpty()) {
      // At least a single item in project is required.
      newChildExprs.add(
          Pair.of(topChildExprs.get(0), topChildExprsFields.get(0)));
    }
    // Add the input with project on top
    relBuilder.push(input);
    relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs));
  }
  relBuilder.union(union.all, union.getInputs().size());
  // Create top Project fixing nullability of fields
  relBuilder.project(topChildExprs, topChildExprsFields);
  relBuilder.convert(union.getRowType(), false);

  call.transformTo(relBuilder.build());
}
 
Example 10
Source File: AggregateCall.java    From Bats with Apache License 2.0 4 votes vote down vote up
/** Creates a copy of this aggregate call, applying a mapping to its
 * arguments. */
public AggregateCall transform(Mappings.TargetMapping mapping) {
  return copy(Mappings.apply2((Mapping) mapping, argList),
      hasFilter() ? Mappings.apply(mapping, filterArg) : -1,
      RelCollations.permute(collation, mapping));
}
 
Example 11
Source File: RelBuilder.java    From calcite with Apache License 2.0 4 votes vote down vote up
/** Returns references to fields identified by a mapping. */
public ImmutableList<RexNode> fields(Mappings.TargetMapping mapping) {
  return fields(Mappings.asList(mapping));
}
 
Example 12
Source File: SqlSplittableAggFunction.java    From calcite with Apache License 2.0 4 votes vote down vote up
public AggregateCall split(AggregateCall aggregateCall,
    Mappings.TargetMapping mapping) {
  return aggregateCall.transform(mapping);
}
 
Example 13
Source File: RelOptUtil.java    From Bats with Apache License 2.0 4 votes vote down vote up
public static RelNode createProject(RelNode child, Mappings.TargetMapping mapping,
        RelFactories.ProjectFactory projectFactory) {
    return createProject(projectFactory, child, Mappings.asList(mapping.inverse()));
}
 
Example 14
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 15
Source File: SqlSplittableAggFunction.java    From calcite with Apache License 2.0 4 votes vote down vote up
public AggregateCall split(AggregateCall aggregateCall,
    Mappings.TargetMapping mapping) {
  return aggregateCall.transform(mapping);
}
 
Example 16
Source File: MutableProject.java    From Bats with Apache License 2.0 4 votes vote down vote up
public Mappings.TargetMapping getMapping() {
  return Project.getMapping(input.rowType.getFieldCount(), projects);
}
 
Example 17
Source File: RelOptMaterialization.java    From calcite with Apache License 2.0 4 votes vote down vote up
private ProjectFilterTable(RexNode condition,
    Mappings.TargetMapping mapping, TableScan scan) {
  this.condition = condition;
  this.mapping = mapping;
  this.scan = Objects.requireNonNull(scan);
}
 
Example 18
Source File: RelTrait.java    From calcite with Apache License 2.0 2 votes vote down vote up
/**
 * Applies a mapping to this trait.
 *
 * <p>Some traits may be changed if the columns order is changed by a mapping
 * of the {@link Project} operator. </p>
 *
 * <p>For example, if relation {@code SELECT a, b ORDER BY a, b} is sorted by
 * columns [0, 1], then the project {@code SELECT b, a} over this relation
 * will be sorted by columns [1, 0]. In the same time project {@code SELECT b}
 * will not be sorted at all because it doesn't contain the collation
 * prefix and this method will return an empty collation. </p>
 *
 * <p>Other traits are independent from the columns remapping. For example
 * {@link Convention} or {@link RelDistributions#SINGLETON}.</p>
 *
 * @param mapping   Mapping
 * @return trait with mapping applied
 */
default <T extends RelTrait> T apply(Mappings.TargetMapping mapping) {
  return (T) this;
}
 
Example 19
Source File: RexUtil.java    From Bats with Apache License 2.0 2 votes vote down vote up
/**
 * Applies a mapping to a collation.
 *
 * @param mapping   Mapping
 * @param collation Collation
 * @return collation with mapping applied
 */
public static RelCollation apply(Mappings.TargetMapping mapping, RelCollation collation) {
    List<RelFieldCollation> fieldCollations = applyFields(mapping, collation.getFieldCollations());
    return fieldCollations.equals(collation.getFieldCollations()) ? collation : RelCollations.of(fieldCollations);
}
 
Example 20
Source File: Project.java    From calcite with Apache License 2.0 2 votes vote down vote up
/**
 * Returns a mapping, or null if this projection is not a mapping.
 *
 * @return Mapping, or null if this projection is not a mapping
 */
public Mappings.TargetMapping getMapping() {
  return getMapping(getInput().getRowType().getFieldCount(), exps);
}