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

The following examples show how to use org.apache.calcite.rel.core.Project#getInput() . 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: RelMdExpressionLineage.java    From Bats with Apache License 2.0 6 votes vote down vote up
/**
 * Expression lineage from Project.
 */
public Set<RexNode> getExpressionLineage(Project rel,
    final RelMetadataQuery mq, RexNode outputExpression) {
  final RelNode input = rel.getInput();
  final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();

  // Extract input fields referenced by expression
  final ImmutableBitSet inputFieldsUsed = extractInputRefs(outputExpression);

  // Infer column origin expressions for given references
  final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
  for (int idx : inputFieldsUsed) {
    final RexNode inputExpr = rel.getChildExps().get(idx);
    final Set<RexNode> originalExprs = mq.getExpressionLineage(input, inputExpr);
    if (originalExprs == null) {
      // Bail out
      return null;
    }
    final RexInputRef ref = RexInputRef.of(idx, rel.getRowType().getFieldList());
    mapping.put(ref, originalExprs);
  }

  // Return result
  return createAllPossibleExpressions(rexBuilder, outputExpression, mapping);
}
 
Example 2
Source File: RelMetadataTest.java    From calcite with Apache License 2.0 6 votes vote down vote up
@Test void testCorrelateUniqueKeys() {
  final String sql = "select *\n"
      + "from (select distinct deptno from emp) as e,\n"
      + "  lateral (\n"
      + "    select * from dept where dept.deptno = e.deptno)";
  final RelNode rel = convertSql(sql);
  final RelMetadataQuery mq = rel.getCluster().getMetadataQuery();

  assertThat(rel, isA((Class) Project.class));
  final Project project = (Project) rel;
  final Set<ImmutableBitSet> result = mq.getUniqueKeys(project);
  assertThat(result, sortsAs("[{0}]"));
  if (false) {
    assertUniqueConsistent(project);
  }

  assertThat(project.getInput(), isA((Class) Correlate.class));
  final Correlate correlate = (Correlate) project.getInput();
  final Set<ImmutableBitSet> result2 = mq.getUniqueKeys(correlate);
  assertThat(result2, sortsAs("[{0}]"));
  if (false) {
    assertUniqueConsistent(correlate);
  }
}
 
Example 3
Source File: RelMdExpressionLineage.java    From calcite with Apache License 2.0 6 votes vote down vote up
/**
 * Expression lineage from Project.
 */
public Set<RexNode> getExpressionLineage(Project rel,
    final RelMetadataQuery mq, RexNode outputExpression) {
  final RelNode input = rel.getInput();
  final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();

  // Extract input fields referenced by expression
  final ImmutableBitSet inputFieldsUsed = extractInputRefs(outputExpression);

  // Infer column origin expressions for given references
  final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
  for (int idx : inputFieldsUsed) {
    final RexNode inputExpr = rel.getProjects().get(idx);
    final Set<RexNode> originalExprs = mq.getExpressionLineage(input, inputExpr);
    if (originalExprs == null) {
      // Bail out
      return null;
    }
    final RexInputRef ref = RexInputRef.of(idx, rel.getRowType().getFieldList());
    mapping.put(ref, originalExprs);
  }

  // Return result
  return createAllPossibleExpressions(rexBuilder, outputExpression, mapping);
}
 
Example 4
Source File: RelMetadataTest.java    From calcite with Apache License 2.0 5 votes vote down vote up
/** Unit test for
 * {@link org.apache.calcite.rel.metadata.RelMetadataQuery#getAverageColumnSizes(org.apache.calcite.rel.RelNode)},
 * {@link org.apache.calcite.rel.metadata.RelMetadataQuery#getAverageRowSize(org.apache.calcite.rel.RelNode)}. */
@Test void testAverageRowSize() {
  final Project rel = (Project) convertSql("select * from emp, dept");
  final Join join = (Join) rel.getInput();
  final RelOptTable empTable = join.getInput(0).getTable();
  final RelOptTable deptTable = join.getInput(1).getTable();
  Frameworks.withPlanner((cluster, relOptSchema, rootSchema) -> {
    checkAverageRowSize(cluster, empTable, deptTable);
    return null;
  });
}
 
Example 5
Source File: RelMetadataTest.java    From calcite with Apache License 2.0 5 votes vote down vote up
/** Unit test for
 * {@link org.apache.calcite.rel.metadata.RelMdCollation#project}
 * and other helper functions for deducing collations. */
@Test void testCollation() {
  final Project rel = (Project) convertSql("select * from emp, dept");
  final Join join = (Join) rel.getInput();
  final RelOptTable empTable = join.getInput(0).getTable();
  final RelOptTable deptTable = join.getInput(1).getTable();
  Frameworks.withPlanner((cluster, relOptSchema, rootSchema) -> {
    checkCollation(cluster, empTable, deptTable);
    return null;
  });
}
 
Example 6
Source File: RelMetadataTest.java    From calcite with Apache License 2.0 5 votes vote down vote up
@Test void testAllPredicates() {
  final Project rel = (Project) convertSql("select * from emp, dept");
  final Join join = (Join) rel.getInput();
  final RelOptTable empTable = join.getInput(0).getTable();
  final RelOptTable deptTable = join.getInput(1).getTable();
  Frameworks.withPlanner((cluster, relOptSchema, rootSchema) -> {
    checkAllPredicates(cluster, empTable, deptTable);
    return null;
  });
}
 
Example 7
Source File: RelMetadataTest.java    From calcite with Apache License 2.0 5 votes vote down vote up
/** Unit test for
 * {@link org.apache.calcite.rel.metadata.RelMdPredicates#getPredicates(Join, RelMetadataQuery)}. */
@Test void testPredicates() {
  final Project rel = (Project) convertSql("select * from emp, dept");
  final Join join = (Join) rel.getInput();
  final RelOptTable empTable = join.getInput(0).getTable();
  final RelOptTable deptTable = join.getInput(1).getTable();
  Frameworks.withPlanner((cluster, relOptSchema, rootSchema) -> {
    checkPredicates(cluster, empTable, deptTable);
    return null;
  });
}
 
Example 8
Source File: ProjectRule.java    From dremio-oss with Apache License 2.0 5 votes vote down vote up
@Override
public void onMatch(RelOptRuleCall call) {
  final Project toTransform = call.rel(0);
  final RelNode input = toTransform.getInput();
  final RelTraitSet traits = toTransform.getTraitSet().plus(Rel.LOGICAL);
  final RelNode convertedInput = convert(input, input.getTraitSet().plus(Rel.LOGICAL).simplify());
  call.transformTo(ProjectRel.create(toTransform.getCluster(), traits, convertedInput, toTransform.getProjects(), toTransform.getRowType()));
}
 
Example 9
Source File: DrillProjectRule.java    From Bats with Apache License 2.0 5 votes vote down vote up
@Override
public void onMatch(RelOptRuleCall call) {
  final Project project = call.rel(0);
  final RelNode input = project.getInput();
  final RelTraitSet traits = project.getTraitSet().plus(DrillRel.DRILL_LOGICAL);
  final RelNode convertedInput = convert(input, input.getTraitSet().plus(DrillRel.DRILL_LOGICAL).simplify());
  call.transformTo(new DrillProjectRel(
      project.getCluster(), traits, convertedInput, project.getProjects(), project.getRowType()));
}
 
Example 10
Source File: MergeProjectRule.java    From dremio-oss with Apache License 2.0 4 votes vote down vote up
@Override
public void onMatch(RelOptRuleCall call) {
  final Project topProject = call.rel(0);
  final Project bottomProject = call.rel(1);
  final RelBuilder relBuilder = call.builder();

  // merge projects assuming it doesn't alter the unique count of flattens.
  final FlattenCounter counter = new FlattenCounter();
  counter.add(topProject);
  counter.add(bottomProject);
  final int uniqueFlattens = counter.getCount();

  // If one or both projects are permutations, short-circuit the complex logic
  // of building a RexProgram.
  final Permutation topPermutation = topProject.getPermutation();
  if (topPermutation != null) {
    if (topPermutation.isIdentity()) {
      // Let ProjectRemoveRule handle this.
      return;
    }
    final Permutation bottomPermutation = bottomProject.getPermutation();
    if (bottomPermutation != null) {
      if (bottomPermutation.isIdentity()) {
        // Let ProjectRemoveRule handle this.
        return;
      }
      final Permutation product = topPermutation.product(bottomPermutation);
      relBuilder.push(bottomProject.getInput());
      List<RexNode> exprs = relBuilder.fields(product);
      relBuilder.project(exprs, topProject.getRowType().getFieldNames());

      if(FlattenVisitors.count(exprs) == uniqueFlattens){
        call.transformTo(relBuilder.build());
      }
      return;
    }
  }

  final List<RexNode> newProjects =
      RelOptUtil.pushPastProject(topProject.getProjects(), bottomProject);
  final RelNode input = bottomProject.getInput();
  if (RexUtil.isIdentity(newProjects, input.getRowType()) && uniqueFlattens == 0) {
    call.transformTo(input);
    return;
  }

  // replace the two projects with a combined projection
  relBuilder.push(bottomProject.getInput());
  relBuilder.project(newProjects, topProject.getRowType().getFieldNames());
  if(FlattenVisitors.count(newProjects) == uniqueFlattens){
    call.transformTo(relBuilder.build());
  }
}
 
Example 11
Source File: DrillMergeProjectRule.java    From Bats with Apache License 2.0 4 votes vote down vote up
@Override
public void onMatch(RelOptRuleCall call) {
  final Project topProject = call.rel(0);
  final Project bottomProject = call.rel(1);
  final RelBuilder relBuilder = call.builder();

  // If one or both projects are permutations, short-circuit the complex logic
  // of building a RexProgram.
  final Permutation topPermutation = topProject.getPermutation();
  if (topPermutation != null) {
    if (topPermutation.isIdentity()) {
      // Let ProjectRemoveRule handle this.
      return;
    }
    final Permutation bottomPermutation = bottomProject.getPermutation();
    if (bottomPermutation != null) {
      if (bottomPermutation.isIdentity()) {
        // Let ProjectRemoveRule handle this.
        return;
      }
      final Permutation product = topPermutation.product(bottomPermutation);
      relBuilder.push(bottomProject.getInput());
      relBuilder.project(relBuilder.fields(product),
          topProject.getRowType().getFieldNames());
      call.transformTo(relBuilder.build());
      return;
    }
  }

  // If we're not in force mode and the two projects reference identical
  // inputs, then return and let ProjectRemoveRule replace the projects.
  if (!force) {
    if (RexUtil.isIdentity(topProject.getProjects(),
        topProject.getInput().getRowType())) {
      return;
    }
  }

  final List<RexNode> pushedProjects =
      RelOptUtil.pushPastProject(topProject.getProjects(), bottomProject);
  final List<RexNode> newProjects = simplifyCast(pushedProjects);
  final RelNode input = bottomProject.getInput();
  if (RexUtil.isIdentity(newProjects, input.getRowType())) {
    if (force
        || input.getRowType().getFieldNames()
        .equals(topProject.getRowType().getFieldNames())) {
      call.transformTo(input);
      return;
    }
  }

  // replace the two projects with a combined projection
  relBuilder.push(bottomProject.getInput());
  relBuilder.project(newProjects, topProject.getRowType().getFieldNames());
  call.transformTo(relBuilder.build());
}
 
Example 12
Source File: ProjectMergeRule.java    From Bats with Apache License 2.0 4 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Project topProject = call.rel(0);
  final Project bottomProject = call.rel(1);
  final RelBuilder relBuilder = call.builder();

  // If one or both projects are permutations, short-circuit the complex logic
  // of building a RexProgram.
  final Permutation topPermutation = topProject.getPermutation();
  if (topPermutation != null) {
    if (topPermutation.isIdentity()) {
      // Let ProjectRemoveRule handle this.
      return;
    }
    final Permutation bottomPermutation = bottomProject.getPermutation();
    if (bottomPermutation != null) {
      if (bottomPermutation.isIdentity()) {
        // Let ProjectRemoveRule handle this.
        return;
      }
      final Permutation product = topPermutation.product(bottomPermutation);
      relBuilder.push(bottomProject.getInput());
      relBuilder.project(relBuilder.fields(product),
          topProject.getRowType().getFieldNames());
      call.transformTo(relBuilder.build());
      return;
    }
  }

  // If we're not in force mode and the two projects reference identical
  // inputs, then return and let ProjectRemoveRule replace the projects.
  if (!force) {
    if (RexUtil.isIdentity(topProject.getProjects(),
        topProject.getInput().getRowType())) {
      return;
    }
  }

  final List<RexNode> newProjects =
      RelOptUtil.pushPastProject(topProject.getProjects(), bottomProject);
  final RelNode input = bottomProject.getInput();
  if (RexUtil.isIdentity(newProjects, input.getRowType())) {
    if (force
        || input.getRowType().getFieldNames()
            .equals(topProject.getRowType().getFieldNames())) {
      call.transformTo(input);
      return;
    }
  }

  // replace the two projects with a combined projection
  relBuilder.push(bottomProject.getInput());
  relBuilder.project(newProjects, topProject.getRowType().getFieldNames());
  call.transformTo(relBuilder.build());
}
 
Example 13
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 14
Source File: ProjectMergeRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Project topProject = call.rel(0);
  final Project bottomProject = call.rel(1);
  final RelBuilder relBuilder = call.builder();

  // If one or both projects are permutations, short-circuit the complex logic
  // of building a RexProgram.
  final Permutation topPermutation = topProject.getPermutation();
  if (topPermutation != null) {
    if (topPermutation.isIdentity()) {
      // Let ProjectRemoveRule handle this.
      return;
    }
    final Permutation bottomPermutation = bottomProject.getPermutation();
    if (bottomPermutation != null) {
      if (bottomPermutation.isIdentity()) {
        // Let ProjectRemoveRule handle this.
        return;
      }
      final Permutation product = topPermutation.product(bottomPermutation);
      relBuilder.push(bottomProject.getInput());
      relBuilder.project(relBuilder.fields(product),
          topProject.getRowType().getFieldNames());
      call.transformTo(relBuilder.build());
      return;
    }
  }

  // If we're not in force mode and the two projects reference identical
  // inputs, then return and let ProjectRemoveRule replace the projects.
  if (!force) {
    if (RexUtil.isIdentity(topProject.getProjects(),
        topProject.getInput().getRowType())) {
      return;
    }
  }

  final List<RexNode> newProjects =
      RelOptUtil.pushPastProjectUnlessBloat(topProject.getProjects(),
          bottomProject, bloat);
  if (newProjects == null) {
    // Merged projects are significantly more complex. Do not merge.
    return;
  }
  final RelNode input = bottomProject.getInput();
  if (RexUtil.isIdentity(newProjects, input.getRowType())) {
    if (force
        || input.getRowType().getFieldNames()
            .equals(topProject.getRowType().getFieldNames())) {
      call.transformTo(input);
      return;
    }
  }

  // replace the two projects with a combined projection
  relBuilder.push(bottomProject.getInput());
  relBuilder.project(newProjects, topProject.getRowType().getFieldNames());
  call.transformTo(relBuilder.build());
}
 
Example 15
Source File: RelDecorrelator.java    From calcite with Apache License 2.0 4 votes vote down vote up
public Frame decorrelateRel(Project rel) {
  //
  // Rewrite logic:
  //
  // 1. Pass along any correlated variables coming from the input.
  //

  final RelNode oldInput = rel.getInput();
  Frame frame = getInvoke(oldInput, rel);
  if (frame == null) {
    // If input has not been rewritten, do not rewrite this rel.
    return null;
  }
  final List<RexNode> oldProjects = rel.getProjects();
  final List<RelDataTypeField> relOutput = rel.getRowType().getFieldList();

  // Project projects the original expressions,
  // plus any correlated variables the input wants to pass along.
  final List<Pair<RexNode, String>> projects = new ArrayList<>();

  // If this Project has correlated reference, create value generator
  // and produce the correlated variables in the new output.
  if (cm.mapRefRelToCorRef.containsKey(rel)) {
    frame = decorrelateInputWithValueGenerator(rel, frame);
  }

  // Project projects the original expressions
  final Map<Integer, Integer> mapOldToNewOutputs = new HashMap<>();
  int newPos;
  for (newPos = 0; newPos < oldProjects.size(); newPos++) {
    projects.add(
        newPos,
        Pair.of(
            decorrelateExpr(currentRel, map, cm, oldProjects.get(newPos)),
            relOutput.get(newPos).getName()));
    mapOldToNewOutputs.put(newPos, newPos);
  }

  // Project any correlated variables the input wants to pass along.
  final SortedMap<CorDef, Integer> corDefOutputs = new TreeMap<>();
  for (Map.Entry<CorDef, Integer> entry : frame.corDefOutputs.entrySet()) {
    projects.add(
        RexInputRef.of2(entry.getValue(),
            frame.r.getRowType().getFieldList()));
    corDefOutputs.put(entry.getKey(), newPos);
    newPos++;
  }

  RelNode newProject = relBuilder.push(frame.r)
      .projectNamed(Pair.left(projects), Pair.right(projects), true)
      .build();

  newProject = RelOptUtil.copyRelHints(rel, newProject);

  return register(rel, newProject, mapOldToNewOutputs, corDefOutputs);
}
 
Example 16
Source File: RelMdPredicates.java    From Bats with Apache License 2.0 4 votes vote down vote up
/**
 * Infers predicates for a project.
 *
 * <ol>
 * <li>create a mapping from input to projection. Map only positions that
 * directly reference an input column.
 * <li>Expressions that only contain above columns are retained in the
 * Project's pullExpressions list.
 * <li>For e.g. expression 'a + e = 9' below will not be pulled up because 'e'
 * is not in the projection list.
 *
 * <blockquote><pre>
 * inputPullUpExprs:      {a &gt; 7, b + c &lt; 10, a + e = 9}
 * projectionExprs:       {a, b, c, e / 2}
 * projectionPullupExprs: {a &gt; 7, b + c &lt; 10}
 * </pre></blockquote>
 *
 * </ol>
 */
public RelOptPredicateList getPredicates(Project project,
    RelMetadataQuery mq) {
  final RelNode input = project.getInput();
  final RexBuilder rexBuilder = project.getCluster().getRexBuilder();
  final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);
  final List<RexNode> projectPullUpPredicates = new ArrayList<>();

  ImmutableBitSet.Builder columnsMappedBuilder = ImmutableBitSet.builder();
  Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION,
      input.getRowType().getFieldCount(),
      project.getRowType().getFieldCount());

  for (Ord<RexNode> expr : Ord.zip(project.getProjects())) {
    if (expr.e instanceof RexInputRef) {
      int sIdx = ((RexInputRef) expr.e).getIndex();
      m.set(sIdx, expr.i);
      columnsMappedBuilder.set(sIdx);
    // Project can also generate constants. We need to include them.
    } else if (RexLiteral.isNullLiteral(expr.e)) {
      projectPullUpPredicates.add(
          rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL,
              rexBuilder.makeInputRef(project, expr.i)));
    } else if (RexUtil.isConstant(expr.e)) {
      final List<RexNode> args =
          ImmutableList.of(rexBuilder.makeInputRef(project, expr.i), expr.e);
      final SqlOperator op = args.get(0).getType().isNullable()
          || args.get(1).getType().isNullable()
          ? SqlStdOperatorTable.IS_NOT_DISTINCT_FROM
          : SqlStdOperatorTable.EQUALS;
      projectPullUpPredicates.add(rexBuilder.makeCall(op, args));
    }
  }

  // Go over childPullUpPredicates. If a predicate only contains columns in
  // 'columnsMapped' construct a new predicate based on mapping.
  final ImmutableBitSet columnsMapped = columnsMappedBuilder.build();
  for (RexNode r : inputInfo.pulledUpPredicates) {
    RexNode r2 = projectPredicate(rexBuilder, input, r, columnsMapped);
    if (!r2.isAlwaysTrue()) {
      r2 = r2.accept(new RexPermuteInputsShuttle(m, input));
      projectPullUpPredicates.add(r2);
    }
  }
  return RelOptPredicateList.of(rexBuilder, projectPullUpPredicates);
}
 
Example 17
Source File: JoinProjectTransposeRule.java    From calcite with Apache License 2.0 3 votes vote down vote up
/**
 * Returns the child of the project that will be used as input into the new
 * LogicalJoin once the projects are pulled above the LogicalJoin.
 *
 * @param call      RelOptRuleCall
 * @param project   project RelNode
 * @param leftChild true if the project corresponds to the left projection
 * @return child of the project that will be used as input into the new
 * LogicalJoin once the projects are pulled above the LogicalJoin
 */
protected RelNode getProjectChild(
    RelOptRuleCall call,
    Project project,
    boolean leftChild) {
  return project.getInput();
}
 
Example 18
Source File: JoinProjectTransposeRule.java    From Bats with Apache License 2.0 3 votes vote down vote up
/**
 * Returns the child of the project that will be used as input into the new
 * LogicalJoin once the projects are pulled above the LogicalJoin.
 *
 * @param call      RelOptRuleCall
 * @param project   project RelNode
 * @param leftChild true if the project corresponds to the left projection
 * @return child of the project that will be used as input into the new
 * LogicalJoin once the projects are pulled above the LogicalJoin
 */
protected RelNode getProjectChild(
    RelOptRuleCall call,
    Project project,
    boolean leftChild) {
  return project.getInput();
}
 
Example 19
Source File: ProjectRemoveRule.java    From calcite with Apache License 2.0 2 votes vote down vote up
/**
 * Returns the child of a project if the project is trivial, otherwise
 * the project itself.
 */
public static RelNode strip(Project project) {
  return isTrivial(project) ? project.getInput() : project;
}
 
Example 20
Source File: ProjectRemoveRule.java    From Bats with Apache License 2.0 2 votes vote down vote up
/**
 * Returns the child of a project if the project is trivial, otherwise
 * the project itself.
 */
public static RelNode strip(Project project) {
  return isTrivial(project) ? project.getInput() : project;
}