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

The following examples show how to use org.apache.calcite.rel.core.Filter#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: RelMdAllPredicates.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Add the Filter condition to the list obtained from the input.
 */
public RelOptPredicateList getAllPredicates(Filter filter, RelMetadataQuery mq) {
  final RelNode input = filter.getInput();
  final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
  final RexNode pred = filter.getCondition();

  final RelOptPredicateList predsBelow = mq.getAllPredicates(input);
  if (predsBelow == null) {
    // Safety check
    return null;
  }

  // Extract input fields referenced by Filter condition
  final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>();
  final RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
  pred.accept(inputFinder);
  final ImmutableBitSet inputFieldsUsed = inputFinder.inputBitSet.build();

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

  // Replace with new expressions and return union of predicates
  final Set<RexNode> allExprs =
      RelMdExpressionLineage.createAllPossibleExpressions(rexBuilder, pred, mapping);
  if (allExprs == null) {
    return null;
  }
  return predsBelow.union(rexBuilder, RelOptPredicateList.of(rexBuilder, allExprs));
}
 
Example 2
Source File: RelMdPredicates.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Add the Filter condition to the pulledPredicates list from the input.
 */
public RelOptPredicateList getPredicates(Filter filter, RelMetadataQuery mq) {
  final RelNode input = filter.getInput();
  final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
  final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);

  return Util.first(inputInfo, RelOptPredicateList.EMPTY)
      .union(rexBuilder,
          RelOptPredicateList.of(rexBuilder,
              RexUtil.retainDeterministic(
                  RelOptUtil.conjunctions(filter.getCondition()))));
}
 
Example 3
Source File: RelFieldTrimmer.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
 * {@link org.apache.calcite.rel.logical.LogicalFilter}.
 */
public TrimResult trimFields(Filter filter, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
    final RelDataType rowType = filter.getRowType();
    final int fieldCount = rowType.getFieldCount();
    final RexNode conditionExpr = filter.getCondition();
    final RelNode input = filter.getInput();

    // We use the fields used by the consumer, plus any fields used in the
    // filter.
    final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>(extraFields);
    RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
    inputFinder.inputBitSet.addAll(fieldsUsed);
    conditionExpr.accept(inputFinder);
    final ImmutableBitSet inputFieldsUsed = inputFinder.inputBitSet.build();

    // Create input with trimmed columns.
    TrimResult trimResult = trimChild(filter, input, inputFieldsUsed, inputExtraFields);
    RelNode newInput = trimResult.left;
    final Mapping inputMapping = trimResult.right;

    // If the input is unchanged, and we need to project all columns,
    // there's nothing we can do.
    if (newInput == input && fieldsUsed.cardinality() == fieldCount) {
        return result(filter, Mappings.createIdentity(fieldCount));
    }

    // Build new project expressions, and populate the mapping.
    final RexVisitor<RexNode> shuttle = new RexPermuteInputsShuttle(inputMapping, newInput);
    RexNode newConditionExpr = conditionExpr.accept(shuttle);

    // Use copy rather than relBuilder so that correlating variables get set.
    relBuilder.push(filter.copy(filter.getTraitSet(), newInput, newConditionExpr));

    // The result has the same mapping as the input gave us. Sometimes we
    // return fields that the consumer didn't ask for, because the filter
    // needs them for its condition.
    return result(relBuilder.build(), inputMapping);
}
 
Example 4
Source File: RelMdAllPredicates.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Add the Filter condition to the list obtained from the input.
 */
public RelOptPredicateList getAllPredicates(Filter filter, RelMetadataQuery mq) {
  final RelNode input = filter.getInput();
  final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
  final RexNode pred = filter.getCondition();

  final RelOptPredicateList predsBelow = mq.getAllPredicates(input);
  if (predsBelow == null) {
    // Safety check
    return null;
  }

  // Extract input fields referenced by Filter condition
  final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>();
  final RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
  pred.accept(inputFinder);
  final ImmutableBitSet inputFieldsUsed = inputFinder.build();

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

  // Replace with new expressions and return union of predicates
  final Set<RexNode> allExprs =
      RelMdExpressionLineage.createAllPossibleExpressions(rexBuilder, pred, mapping);
  if (allExprs == null) {
    return null;
  }
  return predsBelow.union(rexBuilder, RelOptPredicateList.of(rexBuilder, allExprs));
}
 
Example 5
Source File: RelMdPredicates.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Add the Filter condition to the pulledPredicates list from the input.
 */
public RelOptPredicateList getPredicates(Filter filter, RelMetadataQuery mq) {
  final RelNode input = filter.getInput();
  final RexBuilder rexBuilder = filter.getCluster().getRexBuilder();
  final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);

  return Util.first(inputInfo, RelOptPredicateList.EMPTY)
      .union(rexBuilder,
          RelOptPredicateList.of(rexBuilder,
              RexUtil.retainDeterministic(
                  RelOptUtil.conjunctions(filter.getCondition()))));
}
 
Example 6
Source File: ProjectFilterTransposeRule.java    From calcite with Apache License 2.0 4 votes vote down vote up
public void onMatch(RelOptRuleCall call) {
  final Project origProject;
  final Filter filter;
  if (call.rels.length >= 2) {
    origProject = call.rel(0);
    filter = call.rel(1);
  } else {
    origProject = null;
    filter = call.rel(0);
  }
  final RelNode input = filter.getInput();
  final RexNode origFilter = filter.getCondition();

  if ((origProject != null)
      && RexOver.containsOver(origProject.getProjects(), null)) {
    // Cannot push project through filter if project contains a windowed
    // aggregate -- it will affect row counts. Abort this rule
    // invocation; pushdown will be considered after the windowed
    // aggregate has been implemented. It's OK if the filter contains a
    // windowed aggregate.
    return;
  }

  if ((origProject != null)
      && origProject.getRowType().isStruct()
      && origProject.getRowType().getFieldList().stream()
        .anyMatch(RelDataTypeField::isDynamicStar)) {
    // The PushProjector would change the plan:
    //
    //    prj(**=[$0])
    //    : - filter
    //        : - scan
    //
    // to form like:
    //
    //    prj(**=[$0])                    (1)
    //    : - filter                      (2)
    //        : - prj(**=[$0], ITEM= ...) (3)
    //            :  - scan
    // This new plan has more cost that the old one, because of the new
    // redundant project (3), if we also have FilterProjectTransposeRule in
    // the rule set, it will also trigger infinite match of the ProjectMergeRule
    // for project (1) and (3).
    return;
  }

  final RelBuilder builder = call.builder();
  final RelNode topProject;
  if (origProject != null && (wholeProject || wholeFilter)) {
    builder.push(input);

    final Set<RexNode> set = new LinkedHashSet<>();
    final RelOptUtil.InputFinder refCollector = new RelOptUtil.InputFinder();

    if (wholeFilter) {
      set.add(filter.getCondition());
    } else {
      filter.getCondition().accept(refCollector);
    }
    if (wholeProject) {
      set.addAll(origProject.getProjects());
    } else {
      refCollector.visitEach(origProject.getProjects());
    }

    // Build a list with inputRefs, in order, first, then other expressions.
    final List<RexNode> list = new ArrayList<>();
    final ImmutableBitSet refs = refCollector.build();
    for (RexNode field : builder.fields()) {
      if (refs.get(((RexInputRef) field).getIndex()) || set.contains(field)) {
        list.add(field);
      }
    }
    set.removeAll(list);
    list.addAll(set);
    builder.project(list);
    final Replacer replacer = new Replacer(list, builder);
    builder.filter(replacer.visit(filter.getCondition()));
    builder.project(replacer.visitList(origProject.getProjects()),
        origProject.getRowType().getFieldNames());
    topProject = builder.build();
  } else {
    // The traditional mode of operation of this rule: push down field
    // references. The effect is similar to RelFieldTrimmer.
    final PushProjector pushProjector =
        new PushProjector(origProject, origFilter, input,
            preserveExprCondition, builder);
    topProject = pushProjector.convertProject(null);
  }

  if (topProject != null) {
    call.transformTo(topProject);
  }
}
 
Example 7
Source File: RelDecorrelator.java    From calcite with Apache License 2.0 4 votes vote down vote up
public Frame decorrelateRel(Filter rel) {
  //
  // Rewrite logic:
  //
  // 1. If a Filter references a correlated field in its filter
  // condition, rewrite the Filter to be
  //   Filter
  //     Join(cross product)
  //       originalFilterInput
  //       ValueGenerator(produces distinct sets of correlated variables)
  // and rewrite the correlated fieldAccess in the filter condition to
  // reference the Join output.
  //
  // 2. If Filter does not reference correlated variables, simply
  // rewrite the filter condition using new 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;
  }

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

  final CorelMap cm2 = new CorelMapBuilder().build(rel);

  // Replace the filter expression to reference output of the join
  // Map filter to the new filter over join
  relBuilder.push(frame.r)
      .filter(decorrelateExpr(currentRel, map, cm2, rel.getCondition()));

  // Filter does not change the input ordering.
  // Filter rel does not permute the input.
  // All corVars produced by filter will have the same output positions in the
  // input rel.
  return register(rel, relBuilder.build(), frame.oldToNewOutputs,
      frame.corDefOutputs);
}
 
Example 8
Source File: RelFieldTrimmer.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
 * {@link org.apache.calcite.rel.logical.LogicalFilter}.
 */
public TrimResult trimFields(
    Filter filter,
    ImmutableBitSet fieldsUsed,
    Set<RelDataTypeField> extraFields) {
  final RelDataType rowType = filter.getRowType();
  final int fieldCount = rowType.getFieldCount();
  final RexNode conditionExpr = filter.getCondition();
  final RelNode input = filter.getInput();

  // We use the fields used by the consumer, plus any fields used in the
  // filter.
  final Set<RelDataTypeField> inputExtraFields =
      new LinkedHashSet<>(extraFields);
  RelOptUtil.InputFinder inputFinder =
      new RelOptUtil.InputFinder(inputExtraFields, fieldsUsed);
  conditionExpr.accept(inputFinder);
  final ImmutableBitSet inputFieldsUsed = inputFinder.build();

  // Create input with trimmed columns.
  TrimResult trimResult =
      trimChild(filter, input, inputFieldsUsed, inputExtraFields);
  RelNode newInput = trimResult.left;
  final Mapping inputMapping = trimResult.right;

  // If the input is unchanged, and we need to project all columns,
  // there's nothing we can do.
  if (newInput == input
      && fieldsUsed.cardinality() == fieldCount) {
    return result(filter, Mappings.createIdentity(fieldCount));
  }

  // Build new project expressions, and populate the mapping.
  final RexVisitor<RexNode> shuttle =
      new RexPermuteInputsShuttle(inputMapping, newInput);
  RexNode newConditionExpr =
      conditionExpr.accept(shuttle);

  // Build new filter with trimmed input and condition.
  relBuilder.push(newInput)
      .filter(filter.getVariablesSet(), newConditionExpr);

  // The result has the same mapping as the input gave us. Sometimes we
  // return fields that the consumer didn't ask for, because the filter
  // needs them for its condition.
  return result(relBuilder.build(), inputMapping);
}