Java Code Examples for org.apache.calcite.rel.core.Project#copy()

The following examples show how to use org.apache.calcite.rel.core.Project#copy() . 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: ProjectSortTransposeRule.java    From Bats with Apache License 2.0 6 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Project project = call.rel(0);
  final Sort sort = call.rel(1);
  if (sort.getClass() != Sort.class) {
    return;
  }
  RelNode newProject =
      project.copy(
          project.getTraitSet(), ImmutableList.of(sort.getInput()));
  final Sort newSort =
      sort.copy(
          sort.getTraitSet(),
          newProject,
          sort.getCollation(),
          sort.offset,
          sort.fetch);
  call.transformTo(newSort);
}
 
Example 2
Source File: RelBuilder.java    From Bats with Apache License 2.0 6 votes vote down vote up
/** Creates a {@link Project} of the given
 * expressions and field names, and optionally optimizing.
 *
 * <p>If {@code fieldNames} is null, or if a particular entry in
 * {@code fieldNames} is null, derives field names from the input
 * expressions.
 *
 * <p>If {@code force} is false,
 * and the input is a {@code Project},
 * and the expressions  make the trivial projection ($0, $1, ...),
 * modifies the input.
 *
 * @param nodes       Expressions
 * @param fieldNames  Suggested field names, or null to generate
 * @param force       Whether to create a renaming Project if the
 *                    projections are trivial
 */
public RelBuilder projectNamed(Iterable<? extends RexNode> nodes, Iterable<String> fieldNames, boolean force) {
    @SuppressWarnings({ "unchecked", "rawtypes" })
    final List<? extends RexNode> nodeList = nodes instanceof List ? (List) nodes : ImmutableList.copyOf(nodes);
    final List<String> fieldNameList = fieldNames == null ? null
            : fieldNames instanceof List ? (List<String>) fieldNames : ImmutableNullableList.copyOf(fieldNames);
    final RelNode input = peek();
    final RelDataType rowType = RexUtil.createStructType(cluster.getTypeFactory(), nodeList, fieldNameList,
            SqlValidatorUtil.F_SUGGESTER);
    if (!force && RexUtil.isIdentity(nodeList, input.getRowType())) {
        if (input instanceof Project && fieldNames != null) {
            // Rename columns of child projection if desired field names are given.
            final Frame frame = stack.pop();
            final Project childProject = (Project) frame.rel;
            final Project newInput = childProject.copy(childProject.getTraitSet(), childProject.getInput(),
                    childProject.getProjects(), rowType);
            stack.push(new Frame(newInput, frame.fields));
        }
    } else {
        project(nodeList, rowType.getFieldNames(), force);
    }
    return this;
}
 
Example 3
Source File: ProjectSortTransposeRule.java    From calcite with Apache License 2.0 6 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Project project = call.rel(0);
  final Sort sort = call.rel(1);
  if (sort.getClass() != Sort.class) {
    return;
  }
  RelNode newProject =
      project.copy(
          project.getTraitSet(), ImmutableList.of(sort.getInput()));
  final Sort newSort =
      sort.copy(
          sort.getTraitSet(),
          newProject,
          sort.getCollation(),
          sort.offset,
          sort.fetch);
  call.transformTo(newSort);
}
 
Example 4
Source File: FilterProjectTransposeRule.java    From Bats with Apache License 2.0 5 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Filter filter = call.rel(0);
  final Project project = call.rel(1);

  if (RexOver.containsOver(project.getProjects(), null)) {
    // In general a filter cannot be pushed below a windowing calculation.
    // Applying the filter before the aggregation function changes
    // the results of the windowing invocation.
    //
    // When the filter is on the PARTITION BY expression of the OVER clause
    // it can be pushed down. For now we don't support this.
    return;
  }
  // convert the filter to one that references the child of the project
  RexNode newCondition =
      RelOptUtil.pushPastProject(filter.getCondition(), project);

  final RelBuilder relBuilder = call.builder();
  RelNode newFilterRel;
  if (copyFilter) {
    newFilterRel = filter.copy(filter.getTraitSet(), project.getInput(),
        simplifyFilterCondition(newCondition, call));
  } else {
    newFilterRel =
        relBuilder.push(project.getInput()).filter(newCondition).build();
  }

  RelNode newProjRel =
      copyProject
          ? project.copy(project.getTraitSet(), newFilterRel,
              project.getProjects(), project.getRowType())
          : relBuilder.push(newFilterRel)
              .project(project.getProjects(), project.getRowType().getFieldNames())
              .build();

  call.transformTo(newProjRel);
}
 
Example 5
Source File: DruidRules.java    From calcite with Apache License 2.0 5 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Aggregate aggregate = call.rel(0);
  final Project project = call.rel(1);
  final DruidQuery query = call.rel(2);
  if (!DruidQuery.isValidSignature(query.signature() + 'p' + 'a')) {
    return;
  }
  if (aggregate.getGroupSets().size() != 1) {
    return;
  }
  if (DruidQuery
      .computeProjectGroupSet(project, aggregate.getGroupSet(), query.table.getRowType(), query)
      == null) {
    return;
  }
  final List<String> aggNames = Util
      .skip(aggregate.getRowType().getFieldNames(), aggregate.getGroupSet().cardinality());
  if (DruidQuery.computeDruidJsonAgg(aggregate.getAggCallList(), aggNames, project, query)
      == null) {
    return;
  }
  final RelNode newProject = project.copy(project.getTraitSet(),
          ImmutableList.of(Util.last(query.rels)));
  final RelNode newAggregate = aggregate.copy(aggregate.getTraitSet(),
          ImmutableList.of(newProject));
  List<Integer> filterRefs = getFilterRefs(aggregate.getAggCallList());
  final DruidQuery query2;
  if (filterRefs.size() > 0) {
    query2 = optimizeFilteredAggregations(call, query, (Project) newProject,
        (Aggregate) newAggregate);
  } else {
    final DruidQuery query1 = DruidQuery.extendQuery(query, newProject);
    query2 = DruidQuery.extendQuery(query1, newAggregate);
  }
  call.transformTo(query2);
}
 
Example 6
Source File: RelBuilder.java    From calcite with Apache License 2.0 5 votes vote down vote up
/** Creates a {@link Project} of the given
 * expressions and field names, and optionally optimizing.
 *
 * <p>If {@code fieldNames} is null, or if a particular entry in
 * {@code fieldNames} is null, derives field names from the input
 * expressions.
 *
 * <p>If {@code force} is false,
 * and the input is a {@code Project},
 * and the expressions  make the trivial projection ($0, $1, ...),
 * modifies the input.
 *
 * @param nodes       Expressions
 * @param fieldNames  Suggested field names, or null to generate
 * @param force       Whether to create a renaming Project if the
 *                    projections are trivial
 */
public RelBuilder projectNamed(Iterable<? extends RexNode> nodes,
    Iterable<String> fieldNames, boolean force) {
  @SuppressWarnings("unchecked") final List<? extends RexNode> nodeList =
      nodes instanceof List ? (List) nodes : ImmutableList.copyOf(nodes);
  final List<String> fieldNameList =
      fieldNames == null ? null
        : fieldNames instanceof List ? (List<String>) fieldNames
        : ImmutableNullableList.copyOf(fieldNames);
  final RelNode input = peek();
  final RelDataType rowType =
      RexUtil.createStructType(cluster.getTypeFactory(), nodeList,
          fieldNameList, SqlValidatorUtil.F_SUGGESTER);
  if (!force
      && RexUtil.isIdentity(nodeList, input.getRowType())) {
    if (input instanceof Project && fieldNames != null) {
      // Rename columns of child projection if desired field names are given.
      final Frame frame = stack.pop();
      final Project childProject = (Project) frame.rel;
      final Project newInput = childProject.copy(childProject.getTraitSet(),
          childProject.getInput(), childProject.getProjects(), rowType);
      stack.push(new Frame(newInput.attachHints(childProject.getHints()), frame.fields));
    }
  } else {
    project(nodeList, rowType.getFieldNames(), force);
  }
  return this;
}
 
Example 7
Source File: AbstractMaterializedViewRule.java    From Bats with Apache License 2.0 4 votes vote down vote up
@Override
protected RelNode rewriteQuery(RelBuilder relBuilder, RexBuilder rexBuilder, RexSimplify simplify,
        RelMetadataQuery mq, RexNode compensationColumnsEquiPred, RexNode otherCompensationPred,
        Project topProject, RelNode node, BiMap<RelTableRef, RelTableRef> viewToQueryTableMapping,
        EquivalenceClasses viewEC, EquivalenceClasses queryEC) {
    // Our target node is the node below the root, which should have the maximum
    // number of available expressions in the tree in order to maximize our
    // number of rewritings.
    // We create a project on top. If the program is available, we execute
    // it to maximize rewriting opportunities. For instance, a program might
    // pull up all the expressions that are below the aggregate so we can
    // introduce compensation filters easily. This is important depending on
    // the planner strategy.
    RelNode newNode = node;
    RelNode target = node;
    if (unionRewritingPullProgram != null) {
        final HepPlanner tmpPlanner = new HepPlanner(unionRewritingPullProgram);
        tmpPlanner.setRoot(newNode);
        newNode = tmpPlanner.findBestExp();
        target = newNode.getInput(0);
    }

    // All columns required by compensating predicates must be contained
    // in the query.
    List<RexNode> queryExprs = extractReferences(rexBuilder, target);

    if (!compensationColumnsEquiPred.isAlwaysTrue()) {
        compensationColumnsEquiPred = rewriteExpression(rexBuilder, mq, target, target, queryExprs,
                viewToQueryTableMapping.inverse(), queryEC, false, compensationColumnsEquiPred);
        if (compensationColumnsEquiPred == null) {
            // Skip it
            return null;
        }
    }
    // For the rest, we use the query equivalence classes
    if (!otherCompensationPred.isAlwaysTrue()) {
        otherCompensationPred = rewriteExpression(rexBuilder, mq, target, target, queryExprs,
                viewToQueryTableMapping.inverse(), viewEC, true, otherCompensationPred);
        if (otherCompensationPred == null) {
            // Skip it
            return null;
        }
    }
    final RexNode queryCompensationPred = RexUtil.not(RexUtil.composeConjunction(rexBuilder,
            ImmutableList.of(compensationColumnsEquiPred, otherCompensationPred)));

    // Generate query rewriting.
    RelNode rewrittenPlan = relBuilder.push(target)
            .filter(simplify.simplifyUnknownAsFalse(queryCompensationPred)).build();
    if (unionRewritingPullProgram != null) {
        rewrittenPlan = newNode.copy(newNode.getTraitSet(), ImmutableList.of(rewrittenPlan));
    }
    if (topProject != null) {
        return topProject.copy(topProject.getTraitSet(), ImmutableList.of(rewrittenPlan));
    }
    return rewrittenPlan;
}
 
Example 8
Source File: SortProjectTransposeRule.java    From Bats 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;
      final RexCallBinding binding =
          RexCallBinding.create(cluster.getTypeFactory(), cast,
              ImmutableList.of(RelCollations.of(RexUtil.apply(map, fc))));
      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 9
Source File: MaterializedViewJoinRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
@Override protected RelNode rewriteQuery(
    RelBuilder relBuilder,
    RexBuilder rexBuilder,
    RexSimplify simplify,
    RelMetadataQuery mq,
    RexNode compensationColumnsEquiPred,
    RexNode otherCompensationPred,
    Project topProject,
    RelNode node,
    BiMap<RelTableRef, RelTableRef> viewToQueryTableMapping,
    EquivalenceClasses viewEC, EquivalenceClasses queryEC) {
  // Our target node is the node below the root, which should have the maximum
  // number of available expressions in the tree in order to maximize our
  // number of rewritings.
  // We create a project on top. If the program is available, we execute
  // it to maximize rewriting opportunities. For instance, a program might
  // pull up all the expressions that are below the aggregate so we can
  // introduce compensation filters easily. This is important depending on
  // the planner strategy.
  RelNode newNode = node;
  RelNode target = node;
  if (unionRewritingPullProgram != null) {
    final HepPlanner tmpPlanner = new HepPlanner(unionRewritingPullProgram);
    tmpPlanner.setRoot(newNode);
    newNode = tmpPlanner.findBestExp();
    target = newNode.getInput(0);
  }

  // All columns required by compensating predicates must be contained
  // in the query.
  List<RexNode> queryExprs = extractReferences(rexBuilder, target);

  if (!compensationColumnsEquiPred.isAlwaysTrue()) {
    compensationColumnsEquiPred = rewriteExpression(rexBuilder, mq,
        target, target, queryExprs, viewToQueryTableMapping.inverse(), queryEC, false,
        compensationColumnsEquiPred);
    if (compensationColumnsEquiPred == null) {
      // Skip it
      return null;
    }
  }
  // For the rest, we use the query equivalence classes
  if (!otherCompensationPred.isAlwaysTrue()) {
    otherCompensationPred = rewriteExpression(rexBuilder, mq,
        target, target, queryExprs, viewToQueryTableMapping.inverse(), viewEC, true,
        otherCompensationPred);
    if (otherCompensationPred == null) {
      // Skip it
      return null;
    }
  }
  final RexNode queryCompensationPred = RexUtil.not(
      RexUtil.composeConjunction(rexBuilder,
          ImmutableList.of(compensationColumnsEquiPred,
              otherCompensationPred)));

  // Generate query rewriting.
  RelNode rewrittenPlan = relBuilder
      .push(target)
      .filter(simplify.simplifyUnknownAsFalse(queryCompensationPred))
      .build();
  if (unionRewritingPullProgram != null) {
    rewrittenPlan = newNode.copy(
        newNode.getTraitSet(), ImmutableList.of(rewrittenPlan));
  }
  if (topProject != null) {
    return topProject.copy(topProject.getTraitSet(), ImmutableList.of(rewrittenPlan));
  }
  return rewrittenPlan;
}
 
Example 10
Source File: FilterProjectTransposeRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Filter filter = call.rel(0);
  final Project project = call.rel(1);

  if (RexOver.containsOver(project.getProjects(), null)) {
    // In general a filter cannot be pushed below a windowing calculation.
    // Applying the filter before the aggregation function changes
    // the results of the windowing invocation.
    //
    // When the filter is on the PARTITION BY expression of the OVER clause
    // it can be pushed down. For now we don't support this.
    return;
  }
  // convert the filter to one that references the child of the project
  RexNode newCondition =
      RelOptUtil.pushPastProject(filter.getCondition(), project);

  final RelBuilder relBuilder = call.builder();
  RelNode newFilterRel;
  if (copyFilter) {
    final RelNode input = project.getInput();
    final RelTraitSet traitSet = filter.getTraitSet()
        .replaceIfs(RelCollationTraitDef.INSTANCE,
            () -> Collections.singletonList(
                    input.getTraitSet().getTrait(RelCollationTraitDef.INSTANCE)))
        .replaceIfs(RelDistributionTraitDef.INSTANCE,
            () -> Collections.singletonList(
                    input.getTraitSet().getTrait(RelDistributionTraitDef.INSTANCE)));
    newCondition = RexUtil.removeNullabilityCast(relBuilder.getTypeFactory(), newCondition);
    newFilterRel = filter.copy(traitSet, input, newCondition);
  } else {
    newFilterRel =
        relBuilder.push(project.getInput()).filter(newCondition).build();
  }

  RelNode newProjRel =
      copyProject
          ? project.copy(project.getTraitSet(), newFilterRel,
              project.getProjects(), project.getRowType())
          : relBuilder.push(newFilterRel)
              .project(project.getProjects(), project.getRowType().getFieldNames())
              .build();

  call.transformTo(newProjRel);
}
 
Example 11
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 12
Source File: ProjectJoinRemoveRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
@Override public void onMatch(RelOptRuleCall call) {
  final Project project = call.rel(0);
  final Join join = call.rel(1);
  final boolean isLeftJoin = join.getJoinType() == JoinRelType.LEFT;
  int lower = isLeftJoin
      ? join.getLeft().getRowType().getFieldCount() - 1 : 0;
  int upper = isLeftJoin
      ? join.getRowType().getFieldCount()
      : join.getLeft().getRowType().getFieldCount();

  // Check whether the project uses columns whose index is between
  // lower(included) and upper(excluded).
  for (RexNode expr: project.getProjects()) {
    if (RelOptUtil.InputFinder.bits(expr).asList().stream().anyMatch(
        i -> i >= lower && i < upper)) {
      return;
    }
  }

  final List<Integer> leftKeys = new ArrayList<>();
  final List<Integer> rightKeys = new ArrayList<>();
  RelOptUtil.splitJoinCondition(join.getLeft(), join.getRight(),
      join.getCondition(), leftKeys, rightKeys,
      new ArrayList<>());

  final List<Integer> joinKeys = isLeftJoin ? rightKeys : leftKeys;
  final ImmutableBitSet.Builder columns = ImmutableBitSet.builder();
  joinKeys.forEach(key -> columns.set(key));

  final RelMetadataQuery mq = call.getMetadataQuery();
  if (!mq.areColumnsUnique(isLeftJoin ? join.getRight() : join.getLeft(),
      columns.build())) {
    return;
  }

  RelNode node;
  if (isLeftJoin) {
    node = project
        .copy(project.getTraitSet(), join.getLeft(), project.getProjects(),
            project.getRowType());
  } else {
    final int offset = join.getLeft().getRowType().getFieldCount();
    final List<RexNode> newExprs = project.getProjects().stream()
        .map(expr -> RexUtil.shift(expr, -offset))
        .collect(Collectors.toList());
    node = project.copy(project.getTraitSet(), join.getRight(), newExprs,
        project.getRowType());
  }
  call.transformTo(node);
}